我可以将一个本身期望块的块传递给ruby中的instance_exec吗?

问题描述 投票:0回答:3

我期待代码

foo=proc{puts "foo"}

instance_exec(1,2,3,&foo) do |*args , &block|
  puts *args
  block.call
  puts "bar"
end

输出

1
2
3
富
酒吧

但出现错误

给定的块arg和实际块

我可以将一个本身期望块的块传递给ruby中的instance_exec吗?

ruby block proc
3个回答
6
投票

&foo
尝试将
foo
作为块传递给
instance_exec
,并且您已经在传递显式块。省略 & 符号会像任何其他参数一样发送
foo
(除了它是
Proc
实例)。所以,试试这个:

instance_exec(1,2,3,foo) do |*args, block|
  puts *args
  block.call
  puts "bar"
end

这也意味着您可以执行以下操作:

bar = proc{ |*args, block|
  puts *args
  block.call
  puts "bar"
}

instance_exec(1,2,3,foo,&bar)

并得到相同的结果。

更多信息请访问Ruby 中的 block 和 &block 之间的区别


2
投票

我参加这个聚会大约晚了 3 年,但我想我应该分享一种方法,让你将内部块更像是一个真正的块,而不仅仅是一个普通的旧争论。

我所知道的最好方法是创建一个对象来充当绑定上下文并将外部块定义为方法。因此,如果我按如下方式重写原始示例而不调用 instance_exec...

inner_proc = proc { puts "inner" }
outer_proc = proc { |*args, &inner_block|
  puts *args
  inner_block.call
  puts "bar"
}

我们可以将

outer_proc
定义为对象上的方法

scope_object = Object.new
scope_object.define_singleton_method :bound_proc, &outer_proc

现在您可以调用

scope_object.bound_proc
而不是上面的
instance_exec
调用。

scope_object.bound_proc 1, 2, 3, &inner_proc

你会得到:

1
2
3
inner
bar

不幸的是,如果你尝试在

outer_proc
内部而不是
inner_block.call
内进行屈服,你会得到一个 LocalJumpError,我不完全确定为什么。如果有人有这个答案,那么我会很感兴趣。


0
投票

添加到之前的评论,如果您想要确切的所需行为,以便该块将作为块传递到底层过程,但不作为Proc的实例,您可以使用以下解决方法:

foo = proc { puts 'foo' }
bar =  proc do |*args, &block|
  puts *args
  block.call
  puts "bar"
end

instance_exec(&->{ bar.call(1, 2, 3, &foo) })
© www.soinside.com 2019 - 2024. All rights reserved.