为什么带有哈希值的Ruby字符串格式在不同版本中表现不一致?

时间:2017-11-30 01:44:12

标签: ruby

我写了一些使用“动态哈希”的代码来返回键的值,其中值是计算的。我在 irb (RUBY_VERSION 2.3.3)下进行了测试,一切看起来都不错。下面是一个展示这个想法的简单例子。

PROPS = Hash.new { |hash,key| key.to_s + "!" }
"Foo: %{foo} Bar: %{bar}" % PROPS  # => "Foo: foo! Bar: bar!"
PROPS[:xyzzy] # => "xyzzy!"

但是然后将我的代码部署到它使用的环境(建模工具Sketchup的插件),这显然有Ruby 2.2.4上面的字符串格式化示例产生KeyError:key {foo} not found。

PROPS = Hash.new { |hash,key| key.to_s + "!" }
"Foo: %{foo} Bar: %{bar}" % PROPS  # KeyError: key{foo} not found
PROPS[:xyzzy] # => "xyzzy!"

但是使用任何键访问哈希都可以正常工作......在http://ruby-doc.org/core-2.2.4/Kernel.html#method-i-sprintf处读取并没有提供太多指定哈希默认值不会按预期运行的方式。

显然我可以做不同的事情,比如发明我自己的替换函数和变量语法。顺便说一下,显然传递给“%”或sprintf的“哈希”实际上必须是哈希对象,这违反了Ruby所谓的鸭子类型灵活性。

1 个答案:

答案 0 :(得分:1)

我可以确认它在Ruby 2.1.5中不起作用。

我将提供一些提示,告诉你如何找出要定义的ruby代码,以便在不从MRI读取C或Ruby代码的情况下获取内容。

我知道,这不是一个完整的答案,但文字太长,无法发表评论。

以下是irb会话

  >> detector = Object.new
  => #<Object:0x00000002257900>
  >> def detector.method_missing m
  >>   puts m.to_s
  >> end
  => :method_missing
  >> "Foo: %{fnoo} Bar: %{bar}" % detector
  to_ary
  to_hash
  ArgumentError: one hash required
      from (irb):37:in `%'
      from (irb):37
      from /home/felix/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'

这告诉我们在插值方法中调用了我们的虚拟“探测器”对象(to_hash)没有实现的精确;通过其他测试,我知道如果给定对象是哈希,也会调用to_ary,所以我们可以忽略那个)。

然而,它并没有告诉我们是否已经有detector.classdetector is_a Hash?等。被叫了。

现在我等待downvotes;)

顺便说一句,如果你想通过C潜水 - 而且我开始相信这可能是需要的 - 你可以在这里开始挖掘:https://github.com/ruby/ruby/blob/6d728bdae9de565ad9d0b2fee2d4c2a33c6f4eac/sprintf.c#L579(在ruby 2.1上或多或少“sprintf”)