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

时间:2018-01-01 01:17:31

标签: ruby syntax metaprogramming

目前我正在玩一些元编程思想,让我先介绍一下: 我可以定义一个字符串'模板'在import UIKit class ViewController: UIViewController { @IBOutlet weak var funFactLabel: UILabel! @IBOutlet weak var showButton: UIButton! var factProvider = FactProvider() override func viewDidLoad() { super.viewDidLoad() funFactLabel.text = factProvider.randomFact() } @IBAction func showFact() { funFactLabel.text = factProvider.randomFact() let newColor = BackgroundColorProvider.randomColor() view.backgroundColor = newColor showButton.tintColor = newColor } } class作为module并稍后使用它:

Constant

问题是

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

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

湾我希望将这些与常规函数分开,因为我想要使用它们。

所以我决定创建一个继承Proc的新类... 并包含 user system total real Constant: 1.080000 0.000000 1.080000 ( 1.087187) Function: 0.350000 0.000000 0.350000 ( 0.346578) 以输入Percent / Modulo语法。

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 作为方法名称时,为什么该方法似乎错过了第二个给定参数?

1 个答案:

答案 0 :(得分:4)

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
打印?它完全一样!

  

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

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

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

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