Proc 与 Lambda的区别
1、代码块、procs和lambda中的return语句
在一个代码块中的return语句不仅仅会从掉哦你该代码块的迭代器返回,它还会从调用迭代器的方法返回。
def test
puts "entering method"
1.times {puts "entering block"; return}
puts "exiting method" #this line is never executed
end
test
proc与代码块类似,如果调用的proc执行一个return语句,它会试图从代码块所在的方法返回。
def test
puts "entering method"
p = Proc.new {puts "entering proc"; return}
p.call
puts "exiting method" #this line is never executed
end
test
但是,lambda中的语句仅仅从lambda自身返回。
def test
puts "entering method"
p = -> {puts "entering lambda"; return}
p.call
puts "exiting method" #this line is executed
end
test
def lambdaBuilder(msg)
->{puts msg; return}
end
def test
puts "entering code"
l = lambdaBuilder("hello world")
l.call
puts "exiting code" # this line is executed
end
test
2、break语句
proc中调用break语句,会是该代码块返回到它的迭代器,然后该迭代器再返回到它的调用方法。
def iterator(&proc)
puts "entering iterator"
proc.call
puts "exitring iterator" #this line is not executed
end
def test
iterator {puts "entering proc"; break}
end
test
lambda中调用break语句,只是从lambda自身返回。
下面例子这种情况下,break和return语句一样。
def test
puts "entering test method"
lambda = -> {puts "enterting lambda";break;puts "exitring lambda"}
lambda.call
puts "exitng test method"
end
test
# =>entering test method
# =>entering lambda
# => exiting test method
3、顶级的next语句在代码块、proc和lambda中有相同的行为:它使调用代码块、proc和lambda的yield语句或call返回。
redo在proc和lambda中也有相同的行为,它让控制流转向proc和lambda的开始处。
4、传给proc和lambda的参数
调用proc使用的是yield语义,而调用lambda使用的是invocation语义。
proc实例:
p = Proc.new {|x,y| print x,y}
p.call(1) # 1 nil
p.call(1,2) # 1,2
p.call(1,2,3) # 1,2 extral rvalue discarded
p.call([1,2]) #1,2 array automatically unpacked
p.call([1,2,3,4]) # 1,2
lambda实例:
puts "lambda******************************"
l = ->(x,y){ print x,y }
#l.call(1) #wrong number of arguments (1 for 2) (ArgumentError)
l.call(1,2) # this works
#l.call(1,2,3) #wrong number of arguments (3 for 2) (ArgumentError)
#l.call([1,2]) #wrong number of arguments (1 for 2) (ArgumentError)