Ruby - &prc 与 &block 不同吗?
Ruby - Is &prc different than &block?
我正在编写一个简单的方法,将 num
添加到传递给它的块的 return 值,我注意到 &block 和 &prc 都有效。我知道 proc 是一个对象,可以分配给一个方便的变量。那是唯一的区别吗?在性能、惯例或多功能性方面,这两者之间有什么区别吗?使用 &block 代替 &prc 是否更好?
def adder(num = 1, &block)
yield + num
end
对比
def adder(num = 1, &prc)
yield + num
end
Is there any difference between these two when it comes to
performance, convention, or versatility?
这些没有什么区别,你可以随意命名,只是一个名字而已。一些开发者称它为 &blk
一些 &block
或 &b
或 &foo
...
>> def foo &foo
>> yield
>> end
=> :foo
>> foo do
?> puts '1'
>> end
1
严格地说 &
是一个可以应用于任何对象的运算符,它将负责通过调用 [=18= 将该对象转换为 Proc
].
>> def bar(&some_proc)
>> some_proc
>> end
=> :bar
>> p = bar { puts 'Call proc' }
=> #<Proc:0x005601e6d69c80@(irb):4>
>> p.call
=> Call proc
>> p.class
=> Proc
只有一件事很重要,名称应该是信息性的。
在您的示例中,&block
和 &prc
之间没有区别,因为在每种情况下您只是将要调用的块传递给方法。
Block 和 proc 的相似之处在于它们都是代码块。
[1,2,3].each {|x| puts x }
{} 中的所有内容都是块。
proc 只是您可以命名并可以在以后调用的代码块。
put_element = Proc.new {|x| puts x}
然后你使用 put_element 作为函数中的参数。
为您的方法添加任何参数,名称在很大程度上是主观的。通常你会看到 &block
如果只是按照约定使用,但名称本身可以是任何你想要的,只要它是一个有效的变量名称即可。
在您的示例中,您声明了块名称但并未实际使用该名称。请记住,可以给 any Ruby 方法一个块,没有办法限制它,但如果需要,是否使用块取决于方法本身。该块可以立即或在将来的某个时候被调用 零次或多次 。将块交给方法会放弃控制权,因此请务必仔细阅读任何给定方法的文档。会有惊喜。
如果你需要链接一个块,用一个名称声明它:
def passes_through(&block)
[ 1, 2, 3, 4 ].each(&block)
end
如果您要 yield
在街区,则不需要:
def direct_call
[ 1, 2, 3, 4 ].each do |n|
yield n
end
end
如果您要保留调用并在以后使用它,那么命名它也是一种情况:
def preserved_call(&block)
@callback = block
end
def make_callback
@callback and @callback.call
end
任何方法都可以检查是否提供了块:
def tests_for_block
if (block_given?)
yield 'value'
else
'value'
end
end
通过在方法签名中声明来捕获块的成本很小但可衡量,必须进行大量计算才能正确捕获可能在闭包情况下使用的所有变量。在对性能敏感的代码中,您需要避免这种情况。
您可以动态创建区块:
def captures_conditionally
if (block_given?)
@callback = Proc.new
end
end
Proc.new
方法将控制提供给该方法的任何块(如果已经提供的话)。
我正在编写一个简单的方法,将 num
添加到传递给它的块的 return 值,我注意到 &block 和 &prc 都有效。我知道 proc 是一个对象,可以分配给一个方便的变量。那是唯一的区别吗?在性能、惯例或多功能性方面,这两者之间有什么区别吗?使用 &block 代替 &prc 是否更好?
def adder(num = 1, &block)
yield + num
end
对比
def adder(num = 1, &prc)
yield + num
end
Is there any difference between these two when it comes to performance, convention, or versatility?
这些没有什么区别,你可以随意命名,只是一个名字而已。一些开发者称它为 &blk
一些 &block
或 &b
或 &foo
...
>> def foo &foo
>> yield
>> end
=> :foo
>> foo do
?> puts '1'
>> end
1
严格地说 &
是一个可以应用于任何对象的运算符,它将负责通过调用 [=18= 将该对象转换为 Proc
].
>> def bar(&some_proc)
>> some_proc
>> end
=> :bar
>> p = bar { puts 'Call proc' }
=> #<Proc:0x005601e6d69c80@(irb):4>
>> p.call
=> Call proc
>> p.class
=> Proc
只有一件事很重要,名称应该是信息性的。
在您的示例中,&block
和 &prc
之间没有区别,因为在每种情况下您只是将要调用的块传递给方法。
Block 和 proc 的相似之处在于它们都是代码块。
[1,2,3].each {|x| puts x }
{} 中的所有内容都是块。
proc 只是您可以命名并可以在以后调用的代码块。
put_element = Proc.new {|x| puts x}
然后你使用 put_element 作为函数中的参数。
为您的方法添加任何参数,名称在很大程度上是主观的。通常你会看到 &block
如果只是按照约定使用,但名称本身可以是任何你想要的,只要它是一个有效的变量名称即可。
在您的示例中,您声明了块名称但并未实际使用该名称。请记住,可以给 any Ruby 方法一个块,没有办法限制它,但如果需要,是否使用块取决于方法本身。该块可以立即或在将来的某个时候被调用 零次或多次 。将块交给方法会放弃控制权,因此请务必仔细阅读任何给定方法的文档。会有惊喜。
如果你需要链接一个块,用一个名称声明它:
def passes_through(&block)
[ 1, 2, 3, 4 ].each(&block)
end
如果您要 yield
在街区,则不需要:
def direct_call
[ 1, 2, 3, 4 ].each do |n|
yield n
end
end
如果您要保留调用并在以后使用它,那么命名它也是一种情况:
def preserved_call(&block)
@callback = block
end
def make_callback
@callback and @callback.call
end
任何方法都可以检查是否提供了块:
def tests_for_block
if (block_given?)
yield 'value'
else
'value'
end
end
通过在方法签名中声明来捕获块的成本很小但可衡量,必须进行大量计算才能正确捕获可能在闭包情况下使用的所有变量。在对性能敏感的代码中,您需要避免这种情况。
您可以动态创建区块:
def captures_conditionally
if (block_given?)
@callback = Proc.new
end
end
Proc.new
方法将控制提供给该方法的任何块(如果已经提供的话)。