|
锁定老贴子 主题:Ruby函数式风格编程
该帖已经被评为良好帖
|
|
|---|---|
| 作者 | 正文 |
|
时间:2007-02-05 关键字: ruby, erlang, 函数编程
虽然打算把自己的一个开源项目移植到erlang,但手头的一个工作项目却是在用ruby on rails,花了一段时间了解ruby后,发现ruby还是有点意思的。(反倒是不太喜欢Rails。我喜欢直来直去的编程,rails里面太多的magic,实在让我这个喜欢刨根究底的人难受)。
回到主题,Ruby之所以比Python、groovy和Javascript更适合函数风格的编程,尤其是erlang风格,主要因为以下几点:
例一、 命令式风格: ruby 代码
ruby 代码
注意15行删nil项,因为在一个if .. end子句中,总会返回一个值,在不满足所有条件的情况下,就是返回nil 例二 命令式风格: ruby 代码
ruby 代码
或者: ruby 代码
函数式风格的好处是,如果这一段代码只是为了给某几个变量赋值,那么函数式的写法一目了然,副作用也变得尽在掌控中。而命令式风格则没那个好处了。 说明: 1、并行赋值的重要性主要在于让处理分支中的多变量赋值时方便,否则例二中的情况就很难用函数式风格处理了 2、例二中的a,b,c,d当然可以直接用[]括起来处理(如上),但我用abcd也是为了让代码一目了然,个人感觉而已。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
时间:2007-02-06
确实有意思,能多讲讲ruby的FP编程吗?
|
|
| 返回顶楼 | |
|
时间:2007-02-06
返回多值其实就是个列表
并行赋值倒是有意思,但这不是FP的一部分 |
|
| 返回顶楼 | |
|
时间:2007-02-06
* everything is message(也即任何语句都会返回值)
* may return multiple values(可以返回多值) * parallel assignment(并行赋值 ------------------------------------ 这些跟FP编程有什么关系? |
|
| 返回顶楼 | |
|
时间:2007-02-06
有意思
|
|
| 返回顶楼 | |
|
时间:2007-02-06
我的意思是函数式“风格”,尤其是我打算用的erlang的风格。
即使没有上面说的几条,python, javascript和groovy等也都可以有各自的函数式风格,但就是不那么直接了当。 比如在javascript里,if-else子句是不能想象成一个函数的,也就是说你不能写:
var a = if (cond())
1;
else
2;
当然有其它转换成函数形式的方法(不包括var a = cond() ? 1 : 2;),比如象上面那句: var a = (cond() && 1) || (true && 2); 这种例子很多人写过。 还有就是ruby的begin-end子句,可以直接把一段“括”起来并返回最后一句作为值,这样就可以随手在ruby代码中写一段函数,而不用先定义lambda,然后再call它。比如上面那一段:
:limit => begin
limit = par[:m] ? par[:m].to_i : 20
limit >= 4096 ? 4096 : limit
end,
并行赋值和多值返回跟是否FP确实关系不大,但ruby里的这些内建语法让这些东西写起来比较有我喜欢的风格。如果写一个javascript的例子,也不会那么直接了当滴。 有空我会把找到的erlang和ruby之间的一些对应贴出来。 |
|
| 返回顶楼 | |
|
时间:2007-02-06
begin...end就是个lambda
if cond()那个例子是模式匹配,我只在haskell erlang见过 |
|
| 返回顶楼 | |
|
时间:2007-02-07
这是另一段代码,是一个直来直去的权限条件判定,返回一个hash给以后的find用:
prvlg_cond = privilege_cond(user, params[:g]) Feed.find(:all, :conditions => [prvlg_cond[:pre], *prvlg_cond[:sub]) 有点象erlang了。
# grp_str: p -> public(0) , u -> user(1), f -> friends(2)
def privilege_cond(user, grp_str)
grp_str ||= 'puf'
cond = {:pre => "", :sub => []}
cond = if loggedin?(user)
frds = grp_str.include?('f') ? user.friends.find(:all) : []
frd_ids = frds.collect { |frd| frd.friend_id.to_i }
cond = if grp_str.include?('u')
{:pre => cond[:pre] + (cond[:pre] == "" ? "" : "OR") +
" user_id = ? ",
:sub => cond[:sub] + [user.id]}
else
cond
end
cond = if grp_str.include?('f') && !frd_ids.empty?
{:pre => cond[:pre] + (cond[:pre] == "" ? "" : "OR") +
" user_id in (?) AND privilege in (?) ",
:sub => cond[:sub] + [frd_ids, [0, 2]]}
else
cond
end
cond = if grp_str.include?('p')
{:pre => cond[:pre] + (cond[:pre] == "" ? "" : "OR") +
" user_id != ? AND privilege = ? ",
:sub => cond[:sub] + [user.id, 0]}
else
cond
end
else
{:pre => "privilege = ?",
:sub => [0]}
end
end
|
|
| 返回顶楼 | |
|
时间:2007-02-10
Javascript if-else的方案:
var a = function() {
if (cond())
return 1;
else
return 2;
}()
不知道是不是画了一条用脚走路的蛇,另外对性能可能也有影响。 |
|
| 返回顶楼 | |
|
时间:2007-02-14
dcaoyuan 写道 这是另一段代码,是一个直来直去的权限条件判定,返回一个hash给以后的find用:
prvlg_cond = privilege_cond(user, params[:g]) Feed.find(:all, :conditions => [prvlg_cond[:pre], *prvlg_cond[:sub]) 有点象erlang了。
# grp_str: p -> public(0) , u -> user(1), f -> friends(2)
def privilege_cond(user, grp_str)
grp_str ||= 'puf'
cond = {:pre => "", :sub => []}
cond = if loggedin?(user)
frds = grp_str.include?('f') ? user.friends.find(:all) : []
frd_ids = frds.collect { |frd| frd.friend_id.to_i }
cond = if grp_str.include?('u')
{:pre => cond[:pre] + (cond[:pre] == "" ? "" : "OR") +
" user_id = ? ",
:sub => cond[:sub] + [user.id]}
else
cond
end
cond = if grp_str.include?('f') && !frd_ids.empty?
{:pre => cond[:pre] + (cond[:pre] == "" ? "" : "OR") +
" user_id in (?) AND privilege in (?) ",
:sub => cond[:sub] + [frd_ids, [0, 2]]}
else
cond
end
cond = if grp_str.include?('p')
{:pre => cond[:pre] + (cond[:pre] == "" ? "" : "OR") +
" user_id != ? AND privilege = ? ",
:sub => cond[:sub] + [user.id, 0]}
else
cond
end
else
{:pre => "privilege = ?",
:sub => [0]}
end
end
上面的代码感觉有点坏味道,可以重构一下么? |
|
| 返回顶楼 | |











