Ruby 我能把一个区块传给一个进程吗?

Ruby 我能把一个区块传给一个进程吗?,ruby,Ruby,我想知道是否可以将一个块传递给一个进程。仅将块传递给Proc.call不起作用: foo = Proc.new { yield } foo.call { puts "test" } 结果: LocalJumpError:未提供块(产量) 兰博达斯也是如此。但是,该方法不适用于方法对象: class Foo def bar yield end end bar = Foo.new.method :bar bar.call { puts "Success!" } 结果

我想知道是否可以将一个块传递给一个进程。仅将块传递给
Proc.call
不起作用:

foo = Proc.new {
  yield
}

foo.call {
  puts "test"
}
结果:

LocalJumpError:未提供块(产量)

兰博达斯也是如此。但是,该方法不适用于方法对象:

class Foo
  def bar
    yield
  end
end

bar = Foo.new.method :bar

bar.call { puts "Success!" }
结果:

成功

奇怪的是,将method对象转换为proc后,它仍然可以工作:

bar.to_proc.call { puts "Success!" }
结果:

成功


那么,为什么由块生成的Proc不接受块,而最初是方法的Proc接受块呢?可以从接受块的块创建进程吗?

进程不能接受块作为隐式参数(您正在尝试的格式)。proc可以显式地或使用&arguments接收其他proc对象作为参数。例如:

a = Proc.new do |&block|
  block.call
end

a.call() {puts "hi"}

yield
是一种语言级的魔法,只在方法的上下文中起作用

以上答案并非100%正确,因此不能接受。特别是这一部分


Procs无法接受块作为隐式参数(您正在尝试的格式)。proc可以显式地或使用&arguments接收其他proc对象作为参数

这是错误的。proc和lambda可以在它们的体内调用
yield
。要记住的事实是,
Proc/lambda主体有一个词法范围
!这意味着,如果在定义Proc/lambda时存在块,
yield
将成功执行,如下所示

def foo
  my_proc = Proc.new { yield }
  my_proc.call
end

foo { puts "Hello world!" } # would print "Hello world!"
如您所见,
收益率
有效!因为在定义过程时出现了阻塞

可以说,Proc被展开为方法,该方法在调用时具有块,因此
yield
worked。这也是错误的,很容易用下面的代码片段来反驳

def foo
  @my_proc ||= Proc.new { yield }
  @my_proc.call
end

foo { puts "Hello again!" } # would print "Hello world!"
foo # would print "Hello world!"
正如您再次看到的,它是关于在定义过程时使用block

如果您想更好地理解什么是词汇范围的意思,让我们看看下面的示例

class Foo
  def self.hello_proc
    Proc.new { puts name }
  end

  def self.name
    "Alice"
  end
end

class Bar
  def self.put_name
    Foo.hello_proc.call
  end

  def self.name
    "Bob"
  end
end

Bar.put_name # would print "Alice"

您可以将上述代码复制并粘贴到irb会话中,以查看输出内容。它之所以使用“Alice”是因为,在定义过程时,名称是“Alice”。

对我来说,可能的重复仍然是一个开放的相关问题:可以从产生的块创建产生的方法吗?可能的重复是否意味着块不能接受其他块作为隐式参数?因为正如我在问题中所演示的,如果proc从方法转换为proc,那么proc就可以了。@Codemonkey:我很确定too proc会创建一个&参数。我会将
proc.new do|&block
更改为
proc do|&block
,否则这是一个很好的答案。是的,proc和lambdas可以
在它们的体内产生
。然而,语句“Procs不能接受块作为隐式参数(您正在尝试的格式)。”并不否认这一点。这只是说调用
yield
不会调用传递给proc调用的块。(意思是它称之为外部语境的障碍。)我没有说它100%错了,我说它不是100%正确和误导。