这样理解 ruby 的匿名函数更容易

Published on:

起初,看 ruby 的匿名函数会一头雾水,被 ->、lambda、block以及 Proc 搞得晕头转向。

后来,学了一点 javascript后,再来看 ruby 的匿名函数就要容易理解的多。

js的函数,有两种表达形式:

  • 函数语法定义式
  • 函数表达式定义方式
// 这是函数语法定义方式

function print(content) {
  console.log(content);
}
print("hello, js")

// 这是表达式定义方式

var print = function (content) {
  console.log(content);
}
print("hello, js")

函数表达式的定义方式,解释了在 js 中,函数也是一种数据类型,可以像其他数据类型一样被赋值给任何变量。

回到 ruby,一样的道理,函数也是一种数据类型, ->符号相当于 js 中的 function。

print = -> (content) { puts content }
print.call "hello, ruby" # 这里带了参数,.call 可以省略,如果不带参数,则不能省略,即 print.call

# 之所以有 call 是因为 ruby 调用函数的时候,惯例可以省略括号,为了区分这两种情况,加了一个 call 的方法,调用匿名函数

其次,在 js 函数表达式定义方式中,函数可以被当做参数被其他函数接收。

var foo = function() { console.log("foo") }
function bar(x) {
    console.log("bar")
    x()
}
bar(foo)

在 ruby 中,类似的实现方式是:

foo =  -> { puts "foo" }
def bar(x)
    puts "bar"
    x.call
end
bar(foo)

不过,在实际使用过程中,ruby 偏向于用 yield。

def bar
    puts "bar"
    yield if block_given?
end
bar { puts "foo" }

至于 lambda、block以及 Proc 之间的区别,下面这篇文章说的比较详细。
聊聊 Ruby 中的 block, proc 和 lambda · Ruby China

Comments

comments powered by Disqus