0

我现在正在研究街区,他们难倒了我。

我以此为例:

class ProcExample
  attr_reader :proc_class
  def initialize(&block)
    @stored_proc = block
    @proc_class = @stored_proc.class
  end
  def use_proc(arg)
    @stored_proc.call(arg)
  end
end

eg = ProcExample.new {|t| puts t}
p eg.proc_class
p eg.use_proc("Whoooooooo")

现在我有点(不是真的(了解块是如何传递到@stored_proc 的。我使用@proc_class 是因为我很好奇块对象实际存储为哪个类。

但是,如果我想将块存储在常规变量中怎么办?

例如:

block_object = {|param| puts param**2}

但我发现这被视为哈希而不是块/过程。自然会出现错误。我已经尝试在变量名中使用&符号分配它,并且在块的开头,但这不起作用。

最终我想知道是否可以调用一个函数并用包含该块的变量替换该块。

像这样:

(1..10).each block_object

这在Ruby中可能吗?

4

3 回答 3

4

您不能将块分配给变量。

块不是真正的对象。它们是将代码传递给高阶方法的特殊语法。如果你想要一段可以分配给变量、传递和操作的可执行代码,你需要使用一个Proc对象。

有两种Procs:lambdas 和常规 procs。它们在两个方面表现不同:参数绑定语义和return语义。lambdas 绑定方法和return从 lambda 中返回的参数,就像return在方法中从方法返回一样。常规过程绑定参数,如块,并return从封闭方法返回,而不是过程,就像return在块中一样。

可以通过将块传递给Proc.new或替代地来创建常规 procs Kernel#proc。可以通过将块传递给Kernel#lambda或使用“stabby lambda”字面语法来创建 Lambda:

lambda_object = ->param { puts param**2 }

为了将Procs 转换为块,反之亦然,Ruby 具有一元前缀&修饰符。此修饰符仅在参数列表和参数列表中有效。在参数列表中使用时,表示“将块包装在 proc 中并将其绑定到此变量”。在参数列表中使用时。它的意思是“将此过程解包到一个块中(如果它还不是一个过程,to_proc请先调用它)并将其作为块参数传递”。

(1..10).each(&lambda_object)

我很惊讶您还没有看到&以这种方式使用的一元前缀修饰符,它实际上相当普遍,例如在类似['1', '2'].map(&:to_s).

一种也代表一段可执行代码的对象是Method对象。它支持一些与 s 相同的接口,Proc特别是#call,等。有两种方法可以获取对象:使用该方法从接收器中获取绑定到接收器的方法,或者从类中获取对象或模块(例如 using )并将其绑定到接收器,使用该接收器将返回一个对象。#to_proc#arguments#arityMethodObject#methodUnboundMethodModule#instance_methodUnboundMethod#bindMethod

由于Methodimplements ,您可以使用一元前缀修饰符to_proc将其作为块传递给方法,例如:&

# Warning: extremely silly example :-)

ary = []

(1..10).each(&ary.method(:<<))

ary
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

ary = []

(1..10).each(&Array.instance_method(:<<).bind(ary))

ary
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
于 2013-05-12T01:47:28.130 回答
2

我相信你正在寻找一个 proc 对象。

block = proc { ... }
于 2013-05-11T23:30:28.383 回答
1

您可以使用 proc 或 lambda。它们之间有一些细微的差别;以及 Ruby 版本之间。在这里可以看到一个很好的概述:https ://www.youtube.com/watch?v=VBC- G6hahWA 由 Peter Cooper 给出

于 2013-05-11T23:46:47.680 回答