块是作为参数传递的吗?

时间:2013-05-29 17:49:37

标签: ruby syntax

我可以将参数传递给这样的函数:

func 1, 2, 3

或者我可以使用括号:

func(1, 2, 3)

后来我学会了list.each之类的函数,我通过这个函数(不确定这是不是真的发生了)一个块来操作每个元素:

list.each {|x| puts x}

我认为这只是将块作为参数传递给each函数,但似乎并非如此:

list.each( {|x| puts x} )

不起作用。

我在展示时意识到了这一点:

5.upto(9) {|x| puts x}

如果块只是一个参数,那么根本没有意义。

这里发生了什么?您可以指点我帮助解释这个问题的任何资源,以及其他可能不是很明显的结构事物吗?

2 个答案:

答案 0 :(得分:6)

块确实有点特殊,但也可以用作参数。考虑这个功能:

def greet
  yield "Hello"
end

greet{ |greeting| puts "#{greeting} to you" }

你也可以写出完全相同的东西:

def greet(&block)
  block.call("Hello")
end

greet{ |greeting| puts "#{greeting} to you" }

# which is equivalent to:
my_proc = proc{ |greeting| puts "#{greeting}, nice to see you." }
greet(&my_proc)

最后,块是一种特殊形式的proc,它具有特殊的语法,使它们更有用。但你仍然可以访问过程并传递它们。

答案 1 :(得分:4)

方法可以只接受一个块,作为特殊参数。

def foo
  yield 123
end

foo { |x| puts x }
#=> 123

注意该方法如何接受零参数,但仍然接受一个块。那是因为这种方法挂起一个块的语法是一种特殊情况。传递给方法的任何块都可以使用yield关键字运行。您甚至可以询问是否使用block_given?关键字传入了一个块。

如果要在局部变量中捕获它,可以使用一些特殊语法来实现。

def foo(a, &block)
  block.call a
end

foo(123) { |x| puts x }
#=> 123

在这种情况下,您将显式捕获块参数,并在参数列表中使用&前缀。您现在有一个该块的变量,您可以发送call消息以便执行。只要知道这必须出现在参数列表的末尾。

还要注意那些parens。 foo(123) { |x| puts x }。参数列表停止,parens关闭,附加的块后来。同样,因为这是语法中的特殊情况。