【问题标题】:Ruby: Strange behaviour when defining methods that utilize syntax sugarRuby:定义使用语法糖的方法时的奇怪行为
【发布时间】:2018-01-01 01:17:30
【问题描述】:

目前我正在玩一些元编程的想法,让我先介绍一下: 我可以将classmodule 中的字符串“模板”定义为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.由于我想如何使用它们,我想将它们与常规函数分开。

所以我决定创建一个新类来继承 Proc... 并包含 module 以输入百分比/模数语法。

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

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

为什么在使用% 作为方法名称时,该方法似乎遗漏了第二个给定参数?

【问题讨论】:

  • 在这种模棱两可的情况下你不需要括号吗?
  • 尝试更改您的代码以使其以这种方式工作:puts Test2::ConstString % ["test", "test2"]。也许 String 的 % 方法只需要一个参数。
  • 它确实适用于明确传递的[],但是我想知道为什么.make 示例接受隐含的"string", "string" 和`%` 不接受,如果有办法让它接受隐含的。
  • ProcPercentSyntax 的% 方法中的p args 是什么?
  • #=&gt; "test" 似乎Test2::ConstString % "test", "test2" 在这里被解释为[Test2::ConstString.%("test"), "test2"],在这种情况下,我可能不得不满足于您的数组语法。

标签: ruby syntax metaprogramming


【解决方案1】:
puts Test2::ConstString % "test", "test2"

但是……

#=> this is a string with test and 

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

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

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

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

puts 1+1, 3

打印?完全一样!

为什么在使用% 作为方法名称时,该方法似乎遗漏了第二个给定参数?

%二元 运算符,如 &lt;&lt;|。它只需要 两个 操作数,一个在左边(消息的接收者),一个在右边。 Ruby 中只有一个三元运算符 (?:),但是 a) 右侧不采用两个操作数,它采用交错的运算符 (如 a ? b : c) 和 b) 它不能重载.

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

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

【讨论】:

  • 我的方法中有很多puts,却忽略了通过我的对象上的测试puts 输出的附加行。您的回答为我提供了完成代码所需的洞察力,谢谢!
猜你喜欢
  • 2016-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多