Lambda和Proc的区别

15 Jun 2013, by

代码块,proc和lambda中的return语句。

Proc在一个代码块中的return语句不仅仅会从调用代码块的迭代器返回,
它还会从调用迭代器的方法返回。
        def text
               
puts "ss"
               
1.times { puts "aa"; return } (使text方法返回)
               
puts "xxx" (没有执行)
       
end
       
text


       
proc与代码块类似。

       
def text
               
puts "ss"
               
p = Proc.new { puts "aa"; return }
               
p.call     (调用proc使方法返回)
               
puts "xxx" (没有执行)
       
end
       
text

       
def procBuilder(message)
               
Proc.new { puts message; return }
       
end
       
def text
               
puts "ee"
               
p = procBuilder("ss")
               
p.call   (打印ssLocalJumpError)
               
puts "aa"  (没有执行)
       
end
       
text

lambdareturn语句仅从lambda自身返回,而不会从产生lambda的方法中返回。

       
def text
               
puts "ss"
               
p = lambda { puts "aa"; return }
               
p.call    (调用lambda但不使方法返回)
               
puts "xxx" (执行)
       
end
       
text

       
def lambdaBuilder(message)
               
lambda { puts message; return }
       
end
       
def text
               
puts "ee"
               
l = lambdaBuilder("ss")
               
l.call   (打印ss)
               
puts "aa"  (执行)
       
end
       
text

代码块,proc和lambda中的break语句。

代码块中break语句的行为: 它使该代码块返回到它的迭代器,然后该迭代器再返回
到调用它的方法。用Proc.new创建一个proc时,这个Proc.new就是break语句返
回的地方,所以以下代码不正确:
        def text
               
puts "ss"
               
proc = Proc.new { puts "aa"; break }
               
proc.call    (LocalJumpError: iterator has already returned)
               
puts "xxx"
       
end
       
text

       
通过迭代器方法的&参数方式创建proc,可以调用它让迭代器方法返回:

       
def iterator(&proc)
               
puts "ss"
               
proc.call
               
puts "aa"  (没有执行)
       
end

       
def text
               
iterator { puts "xx"; break }
       
end
       
text

       
lambda类似方法,不出现在循环或迭代方法中则break行为类似return:

       
def test
               
puts "ss"
               
lambda = lambda { puts "aa"; break; puts "xx" }
               
lambda.call
               
puts "xxx"
       
end
       
test

传递给proc和lambda的参数。

lambda对参数有着严谨的检查,需要参数一致。proc则不需要。

调用proc使用的是yield语意:
        p = Proc.new { |x,y| print x,y }
       
p.call(1)         # Prints 1nil
       
p.call(1,2)               # Prints 12
       
p.call(1,2,3)     # Prints 12
       
p.call([1,2])     # Prints 12
proc处理参数可以抛弃多余参数,将nil赋给遗漏参数,拆开数组,
当需要单个参数时可以把多个参数打包成数组。

lambda则必须声明同样多的参数对它进行调用:
        l = lambda { |x,y| print x,y }
       
l.call(1,2)              # 正常
       
l.call(1)                # Wrong number of arguments
       
l.call(1,2,3)    # Wrong number of arguments
       
l.call([1,2])    # Wrong number of arguments
       
l.call(*[1,2])   # 显式实现将数组解开