为什么这个块在存储在proc中时不会运行?

我正在学习ruby并试图更好地理解Blocks,Yield,Procs和Methods,我偶然发现了使用yield的这个例子 .

def calculation(a, b)
   yield(a, b)
end

x = calculation(5,6) do|a,b|
a + b
end

puts "#{x}"

根据我的理解,Procs是持有指向Blocks的指针的对象 . 并且块首先需要一种方法来工作 . 此外,从使用yield的方式来看,我假设在方法调用之后,yield会立即跳转到块 .

我假设代码以这种方式运行:calculate(5,6)调用方法计算() . 当yield指令执行时,a和b在计算后传递给块(5,6) . 为了更好地理解并尝试了解,我尝试了这样做 .

def calculation(a, b)
   yield(a, b)
end

ankh = Proc.new do |a,b|
   a + b
end

x = calculation(5,6) *ankh

该错误表示没有给出计算块() . 但我们不是计算(5,6)块ankh吗?希望我的问题不会太混乱 .

回答(2)

2 years ago

您在 x = calculation(5,6) *ankh 行中有语法错误 . 要将方法作为块传递,请使用 & -operator .

x = calculation(5,6,&ankh)

2 years ago

首先:你所写的内容没有任何意义 . 想一想:做什么

calculation(5, 6) * ankh

意思?或者,更抽象地说,是什么

foo * bar

意思? 2 * 3 真的意思是“调用 2 并将 3 传递为块”吗?

错误表示没有给出计算块() . 但我们不是计算(5,6)块ankh吗?

不, ankh 不是块,它是Proc . 块是纯粹的句法结构 . 最重要的是,块不是对象,因此您根本无法将其存储在变量中 . 您也不能将它作为方法的正常参数传递,您必须将其作为单独的"special"块参数传递 . 块不存在独立于方法调用 .

但是,有一种方法是"converting" a Proc 进入一个块: & &符号一元前缀运算符:

x = calculation(5, 6, &ankh)
# => 11

这告诉Ruby采取 Proc ankh并将其转换为块 . 事实上,这种机制比这更通用,因为你甚至可以传递一个不是 Proc 的对象,而Ruby将首先在该对象上调用 to_proc 以允许它将自身转换为 Proc .

例如,Method实现to_proc,因此您可以将 Method s作为块传递:

def ankh(a, b) a + b end

x = calculation(5, 6, &method(:ankh))
# => 11

此外,Symbol实现to_proc

x = calculation(5, 6, &:+)
# => 11

最后,Hash也实现了to_proc .

当然,您可以编写自己的实现 to_proc 的对象:

def (ankh = Object.new).to_proc
  -> *args { "I was called with arguments #{args.inspect}!" }
end

x = calculation(5, 6, &ankh)
# => 'I was called with arguments [5, 6]!'