Ruby What are blocks, procs, and lambdas?

bajiudongfeng · 2017年04月08日 · 最后由 bajiudongfeng 回复于 2017年04月09日 · 1589 次阅读

原文链接

1. 主要区别:

  • Proc 和 Lambda 都是对象,而 Block 不是
  • 参数列表中最多只能有一个 Block,但是可以有多个 Proc 或 Lambda

  • Lambda 对参数的检查很严格,而 Proc 则比较宽松

  • Proc 和 Lambda 中 return 关键字的行为是不同的

2. 特殊符号

  • 同时要注意&符号

The '&' tells ruby to turn the proc into a block

  • 例如
Sale.limit(5).map(&:id)

:id是一个 symbol 对象,当在其前面加上&就表示后边需要的是一个 proc,因此:id会调用其 to_sym 方法。

3. 具体代码分析

  • 基本的例子
# Block Examples
[1,2,3].each { |x| puts x*2 }   # block is in between the curly braces

[1,2,3].each do |x|
  puts x*2                    # block is everything between the do and end
end

# Proc Examples             
p = Proc.new { |x| puts x*2 }
[1,2,3].each(&p)              # The '&' tells ruby to turn the proc into a block 

proc = Proc.new { puts "Hello World" }
proc.call                     # The body of the Proc object gets executed when called

# Lambda Examples            
lam = lambda { |x| puts x*2 }
[1,2,3].each(&lam)

lam = lambda { puts "Hello World" }
lam.call
  • 区别 1(Proc 和 Lambda 都是对象,而 Block 不是) 举例
p = Proc.new { puts "Hello World" }

p.call  # prints 'Hello World'
p.class # returns 'Proc'
a = p   # a now equals p, a Proc instance
p       # returns a proc object '#<Proc:0x007f96b1a60eb0@(irb):46>'

{ puts "Hello World"}       # syntax error  
a = { puts "Hello World"}   # syntax error
[1,2,3].each {|x| puts x*2} #

p 是类 Proc 的一个实例对象,其可以调用方法,复制给其他变量,也可以返回自己. block 是方法调用的一部分,不可以单独存在,

  • 区别 2(参数列表中最多只能有一个 Block,但是可以有多个 Proc 或 Lambda) 举例
def multiple_procs(proc1, proc2,&block)
  proc1.call
  proc2.call
  block.call
end

a = Proc.new { puts "First proc" }
b = Proc.new { puts "Second proc" }

multiple_procs(a,b) {puts "block"}
  • 区别 3(Lambda 对参数的检查很严格,而 Proc 则比较宽松) 举例
proc = Proc.new { puts "Hello world" }
lam = lambda { puts "Hello World" }

proc.class # returns 'Proc'
lam.class  # returns 'Proc'

proc   # returns '#<Proc:0x007f96b1032d30@(irb):75>'
lam    # returns '<Proc:0x007f96b1b41938@(irb):76 (lambda)>'

proc 和 lam 都是 Proc 的实例对象,仅有微小的不同 参数检查的不同

proc = Proc.new { |x| puts x } # creates a proc that takes 1 argument
proc.call(2)                   # prints out 2
proc.call                      # returns nil
proc.call(1,2,3)               # prints out 1 and forgets about the extra arguments

lam = lambda { |x| puts x }    # creates a lambda that takes 1 argument
lam.call(2)                    # prints out 2
lam.call                       # ArgumentError: wrong number of arguments (0 for 1)
lam.call(1,2,3)                # ArgumentError: wrong number of arguments (3 for 1)
  • 区别 4(Proc 和 Lambda 中 return 关键字的行为是不同的) 举例
def lambda_test
  lam = lambda { return }
  lam.call
  puts "Hello world"
end

lambda_test                 # calling lambda_test prints 'Hello World'


def proc_test
  proc = Proc.new { return }
  proc.call
  puts "Hello world"
end

proc_test                 # calling proc_test prints nothing

这个有点类似循环中的continuebreak

简明扼要。排版建议用标题,这样可以有目录。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号