Procs 与 Lambdas

到目前为止,在我们的示例中块(blocks)都和方法(methods)一起使用。这是必须的,因为匿名块在 Ruby 中不能独立存在。例如,你不能像这样创建一个独立的块:

  1. {|x| x = x*10; puts(x)}

这是”Ruby中的所有内容都是对象”这一规则的例外情况之一。块显然不是一个对象。每个对象都是从类创建的,你可以通过调用其 class 方法来查找对象的类。

例如,使用 Hash 对象执行此操作,会显示类名 “Hash”:

  1. puts({1=>2}.class)

但是,尝试对块执行此操作,你只会得到一条错误消息:

  1. puts({|i| puts(i)}.class) #<= error!

Block 还是 Hash?

Ruby 使用花括号来限定 block 和 Hash。那你(以及 Ruby)怎么能分辨哪个是哪个?答案基本上就是当它看起来像 Hash 时它是 Hash,否则它就是一个 block。Hash 看起来是在花括号中包含了键值(key-value)对… puts( {1=>2}.class ) #<= Hash…或者,当它们是空(empty)的: puts( {}.class ) #<= Hash但是,又一次的,当你省略括号时,将会出现歧义。这是一个空的 Hash 还是与 puts 方法相关联的一个 block? puts{}.class坦率地说,我不得不承认我不知道这个问题的答案,我也无法让 Ruby 告诉我。Ruby 认为这是有效的语法,但事实上,在代码执行时不会显示任何内容。所以,这个… print{}.class…打印为 nil(你不会注意到实际的 nil 类,即 Nil-Class,而是 nil 本身)。如果你发现所有的这些令人困惑(就像我一样!),请记住,通过明确地使用括号可以避免这一点: print( {}.class ) #<= Hash