Ruby:定义使用语法糖的方法时的奇怪行为

Ruby: Strange behaviour when defining methods that utilize syntax sugar

目前正在研究一些元编程的想法,先介绍一下: 我可以将 classmodule 中的字符串 'template' 定义为 Constant 并在以后像这样使用它:

class Test1
  ConstString = %(the string in here is %{instring})
end
puts Test1::ConstString % { instring: "test" }
#=> the string in here is test

问题是

一个。基于基准测试,仅仅定义一个函数可以做同样的事情快 3 倍(基准是 1000000.times):

                 user     system      total        real
   Constant:   1.080000   0.000000   1.080000 (  1.087187)
   Function:   0.350000   0.000000   0.350000 (  0.346578)

b。我想将它们与常规函数分开,因为我想如何使用它们。

所以我决定创建一个新的 class 来继承 Proc... 并包含一个 module 以投入 Percent/Modulo 语法。

module ProcPercentSyntax
  def %(*args)
    self.call(*args)
  end
end
class TestFromProc < Proc
  include ProcPercentSyntax
end


class Test2
  ConstString = TestFromProc.new { |x, y| %(this is a string with #{x} and #{y}) }
end

这样我就可以这么叫了!

puts Test2::ConstString % "test", "test2"

但是...

#=> this is a string with test and 

令人不安的是没有抛出任何错误。

为了确保这不是另一个问题,我继续这样做了:

module ProcNotPercentSyntax
  def make(*args)
    self.call(*args)
  end
end

class TestFromProc < Proc
  include ProcNotPercentSyntax
end

puts Test2::ConstString.make "test", "test2"

还有...

#=> this is a string with test and test2

请原谅这个问题的零星性质,我将这样总结我的意图:

Why does the method seem to miss out on the second given parameter when using % as a method name?

puts Test2::ConstString % "test", "test2"

But...

#=> this is a string with test and 

不是,那是不是的结果。结果是:

# this is a string with test and 
# test2
#=> nil

Disconcertingly without any error thrown.

为什么会出现错误?用两个参数调用 puts 是完全合法的,这就是你在这里所做的。你会期待什么

puts 1+1, 3

打印?完全一样!

Why does the method seem to miss out on the second given parameter when using % as a method name?

% 是一个 二元 运算符,类似于 <<|。它只需要两个个操作数,一个在左边(消息的接收者),一个在右边。 Ruby (?:) 中只有一个三元运算符,但是 a) 右边没有两个操作数,它的三个操作数与运算符交错(像这样 a ? b : c ) 和 b) 它不能超载。

请注意,这与名称%无关,它与运算符语法有关:

puts Test2::ConstString.% "test", "test2"
# this is a string with test and test2
#=> nil