ruby 为什么我不能得到一个块的context(proc)?

bkkx9g8r  于 2023-08-04  发布在  Ruby
关注(0)|答案(1)|浏览(95)

我用这个类创建了一个带有添加值的proc

class MyBuilder
    attr_reader :values
  
    def initialize(something)
      @something = something
      @values = {}
    end
  
    def inner(name, &block)
      @values[name] = block 
    end
end

字符串
我使用instance_exec函数来获取proc

require './my_builder'
class Out 
    def self.outer(sth, builder, &block)
        builder.instance_exec(&block) 
        p "result", builder.values
    end
end


当我测试的时候,这个工作得很好,这是正确的答案:oneone

Out.outer(:hello, builder) do
            builder.inner(:one) { :oneone }
        end


但这不工作,这是输入,只有我试图得到块do event :assign do ...

#   datan status: {unassigned: 0, assigned: 1, resolved: 2} do
#     event :assign do
#       transition :unassigned => :assigned
#     end
#   end

def self.datan(name = nil, values = nil, **options, &block)
# options is {unassigned: 0, assigned: 1, resolved: 2}
# block should `do event :assign do ...`

Out.outer(:hello, builder) do
            builder.inner(:one) { block }
        end

xzabzqsa

xzabzqsa1#

TL;DR

你要做的事情有很多错误,所以我不打算一行一行地解释它或调试你的代码。相反,我将简单地说你最大的两个问题是:

  1. Proc对象是闭包,所以Binding在创建它的类或绑定外部调用时并不一定是您所认为的那样。
  2. Procs和lambdas提供了一些巧妙的技巧,但是您可以将它们作为方法来完成大部分的操作。不要让代码过于复杂。“可能工作的最简单的东西”几乎总是比聪明的代码更好。
    也就是说,这里有一个工作示例,其中匿名块在类外部定义,转换为proc,存储在示例变量中作为命名的proc集合,然后使用Proc#call按名称调用。它适用于Ruby 3.2.2,所以可以根据自己的用例进行调整。

foo.rb中的示例代码

class MyBuilder
  attr_reader :procs

  def initialize
    @procs = {}
    @binding = binding
  end 

  def merge name, &block
    fail ArgumentError, "no block given" unless block_given?
    hash = { name => block }
    @procs.merge!(hash)
  end 

  alias_method :push, :merge

  def call_block name
    $stderr.printf "Calling %p ... ", name
    pp @procs[name].call
  end
end

if __FILE__ == $0
  b = MyBuilder.new
  b.push("hi") { "Hello!" }
  b.push("bye") { "Goodbye!" }

  # inspect the @procs instance variable
  $stderr.printf "%p\n\n", b.procs

  b.procs.keys.each { b.call_block _1 }
end

字符串

foo.rb输出示例

~> ruby foo.rb
{"hi"=>#<Proc:0x00000001051e9118 foo.rb:25>, "bye"=>#<Proc:0x00000001051e9078 foo.rb:26>}

Calling "hi" ... "Hello!"
Calling "bye" ... "Goodbye!"

相关问题