Ruby的Proc.new 与Lambda 的区别
Ruby的Proc.new 与Lambda 的区别
缘起,Block 与 Proc
Block 在ruby 中会像空气一般的存在于大量的代码当中。块最开始是用来循环时候用的东西,但慢慢的,block变成了委托利器,贯穿于各种代码之间。
举个例子,我有一个数组1,2,3,4,5,6 我想得到这个数组的平方 在传统的程序里面,我们这样实现
1 2 3 4 5 6 |
|
如果在ruby中,我们即可使用块来完成
1
|
|
这里的{|item| item**2} 就是一个Block。
当然之所以这里的ruby 代码简洁的原因是因为map本身隐藏了一些逻辑,实际上map由模块Emuneration 实现 其实通过上面的代码基本上可以看出,Block类似其他语言中的C#或者java中的委托、事件的实现。
我们来仿照着写一个Block的应用(自行实现map)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
我们把目光还是集中在{|item| item **2}
中,这个代码是我们手敲上去的,那有没有方式将其放入变量里呢?
答案是 有,就是Proc对象 就是我们的Proc.new 和lambda,他们会返回Proc对象,记得在做参数的时候要加&符号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Ruby 下的Proc.new 和Lambda 都是为了生成我们的Proc 而使用的指令,从大方向上来说,他们功能上非常相似,但从细节上来讲,他们又有一些不同点
相同点非常简单,他们都返回Proc对象,结构一样,那么不同点呢?
- Proc.new 的参数不需要严格匹配,但是lambda 需要严格匹配
比如这里的func1 = Proc.new {|p,q| p p,q};func1.call("x")
, 则输出 "x" nil
,但是换做lambda,就不行:
2.2.0 :014 > func2 = lambda {|p,q| p p,q};func2.call("x")
ArgumentError: wrong number of arguments (1 for 2)
from (irb):14:in `block in irb_binding'
from (irb):14:in `call'
from (irb):14
from /Users/atpking/.rvm/rubies/ruby-2.2.0/bin/irb:11:in `<main>'
- Proc.new 如果里面出现了return,则代表的外部的return,而不是Proc自己的return,则是返回一个Proc对象,比如说
2.2.0 :035 > def Hello
2.2.0 :036?> p = Proc.new{return "inner proc"}
2.2.0 :037?> p.call
2.2.0 :038?> return "func return"
2.2.0 :039?> end
2.2.0 :041 > Hello()
=> "inner proc"
注意此处,返回的是inner proc,
注意,如果直接在irb 里写p = Proc.new{return 1}
之后p.call 的化,是要报localJumpError的,因为此时irb 并没有结束,还没有return
2.2.0 :061 > def Hello2
2.2.0 :062?> p = lambda{return "inner proc"}
2.2.0 :063?> p.call
2.2.0 :064?> return "func return"
2.2.0 :065?> end
=> :Hello2
2.2.0 :068 > Hello2()
=> "func return"
此处是func return。
那么这些区别会带来什么变化呢?答案是,lambda 可以带参数的回传, 更加灵活了。比如下面的一个例子
1 2 3 4 5 6 7 8 9 |
|
而proc,就会出现下列的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|