1

我正在玩 Ruby 中的 DSL 元编程。

以下程序使用嵌套块评估按预期工作;它的含义对于我在这里暴露的问题并不重要。我遇到的“错误”或麻烦与最后四行有关:

# works (using a variable 'mm' to store the result of Gen.define method)
mm=Gen.define("abc") do
  node(:func){}
end
pp mm
# returns {"abc"=>#<Definition:0x000000021f6c90 @nodes={:func=>#<Node:0x000000021f6a60 @name=:func>}>}

但以下不起作用,返回错误,也如下所示。不同之处在于define(哈希)的结果在这里直接作为参数传递给'pp'漂亮的打印机,而工作程序使用变量(mm)。

# does NOT work (no variable)
pp Gen.define("abc") do
  node(:func){}
end

为什么行为上有这样的差异?

错误是:

`instance_eval':未提供块(ArgumentError)

这是完整的(工作)程序(同样它没有做任何有用的事情)。

require 'pp'

class Gen
  def self.define name,&block
    @nodes=Definition.new(&block)
    return name => @nodes
  end
end

class Definition
  def initialize(&block)
    @nodes={}
    instance_eval(&block)
  end

  def node name,&block
    @nodes.merge!(name =>  Node.new(name,&block))
  end
end

class Node
  def initialize name,&block
    @name=name
    instance_eval(&block)
  end
end

mm=Gen.define("abc") do
  node(:func){}
end

pp mm
4

1 回答 1

1

这里的问题只是优先级:当你说

pp Gen.define("abc") do
  node(:func){}
end

就是pp这样。这与以下内容相同:

pp(Gen.define("abc")) do
  node(:func){}
end

这将做你想要的:

pp(Gen.define("abc") do
  node(:func){}
end)

有些人(包括我)建议do在方法返回值时使用大括号而不是 ...<code>end 作为块。您可能会发现这会给您带来不那么令人惊讶的结果:

pp Gen.define("abc") {
  node(:func){}
}
于 2013-10-04T13:02:56.387 回答