Ruby What are blocks, procs, and lambdas?

bajiudongfeng · 发布于 2017年04月08日 · 最后由 bajiudongfeng 回复于 2017年04月09日 · 431 次阅读
14935

原文链接

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

共收到 2 条回复
4215

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

14935

@chenge 好的下次试试

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