Ruby:instance_exec,其中一个块将块作为参数

时间:2018-01-12 14:48:48

标签: ruby

请考虑以下代码:

def a &block_a
    define_method :b do |&block_b|
        puts "Running in define_method"
        instance_exec block_a, &block_b
    end
end

a do
    puts "In block A"
end

b do |&block|
    puts "In block B"
    instance_eval &block
end

我喜欢方法' b'作为参数给出方法' a' (b动态创建)。 但是会返回以下输出/错误:

Running in define_method
In block B
wrong number of arguments (given 0, expected 1..3)
(repl):14:in `instance_eval'
(repl):14:in `block in <main>'
(repl):4:in `instance_exec'
(repl):4:in `block in a'
(repl):12:in `<main>'

好像是&#39;&amp; block&#39;是nil(尝试调用&#39; block.call&#39;而不是&#39; instance_eval&amp; block&#39;提升&#39; block是nil&#39;错误)。自从更换&#39; b&#39;之后,逻辑似乎很好。带字符串的块参数确实有效:

def a s
    define_method :b do |&block_b|
        puts "Running in define_method"
        instance_exec s, &block_b
    end
end

a "LOL"

b do |s|
    puts "In block B"
    puts s
end

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

要理解你想要完成的事情是非常难以理解的,而且我对你的事情过于复杂有102%的肯定(读:做错了。)

您的代码存在的问题是您在块及其参数中丢失了。

block方法调用中的b不是nilb应该yield某些东西,并且不允许产生块。可以明确地调用块来代替屈服:

def a &block_a
  define_method :b do |&block_b|
  # ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓
    block_b.(&block_a)
  end
end

a { puts "A" }

b { |&block| puts "B"; instance_eval &block }

其他方式可能是接受b中的普通参数,因为你传递的是block_a,这是一个普通的proc实例:

def a &block_a
  define_method :b do |&block_b|
    instance_exec block_a, &block_b
  end
end

a { puts "A" }

#   ⇓⇓⇓⇓⇓⇓⇓
b { |block| puts "B"; instance_eval &block }