如果我定义了一个运算符,
class Object
def ~@
self || ErrorlessNil.new
end
end
我怎样才能使~
首先评估,而不是最后评估?现在,像是
~[1][100].undefined_method
会抛出错误,而
(~[0][22]).randomsadfldsf
工作正常。目标是定义一个像coffeescript的问号一样工作的工具。我可以制作??
方法,但我不能以?
开头,而_?
可以正常工作,但这并不好玩。
答案 0 :(得分:3)
JörgWMittag的回答提供了一个不能按你想要的方式工作的原因,但还有另外一个原因。
如果~
的优先级高于其他方法应用,那么
~[0][22].randomsadfldsf
不会被解释为
(~[0][22]).randomsadfldsf
但是作为
(~[0])[22].randomsadfldsf
答案 1 :(得分:2)
你不能。
在Ruby中,您只能覆盖现有运算符的行为。您无法定义新的运算符,也无法更改其优先级,优点,关联性或固定性。
这与Haskell或Fortress不同,它允许您使用自己的固定(前缀,后缀,中缀),关联性(左,右,无)和优先级来定义自己的运算符。在这方面,Ruby就像Python,C#和C ++。
答案 2 :(得分:1)
明显而简单的答案是,除()
外,您无法更改运算符优先级。
但是你真的想要,你可以使用eval
*或/,你可以构建你的抽象语法树(AST)/ SEXP。
str = "~[1,2,3].first"
def foo str
if str[0] == '~'
obj, meth = str[1..-1].split '.'
eval "(~#{obj}).#{meth}"
end
end
foo str
foo
要求str
采用以下格式:
"<~><object/literal without dot><method without dot>"
随着代码越来越复杂,foo
变得越来越复杂。您将以Regexp或AST / SEXP结尾。
Build-in Ruby Ripper可以将源变为sexp。有一个名为Sorcerer的宝石。它可以将Sexp从开膛手改回源头。然而,它仅用1.9.3和2.0测试。
* eval可能不安全,因为它可能会运行您不想要的代码。在评估之前检查一下你的字符串!