在Ruby中定义新的逻辑运算符

5

这可能只是一种想象,但通过一些巧妙的元编程技巧,能否在Ruby中定义一个新的逻辑运算符呢?我想定义一个 but 运算符。

例如,如果我想在x为true但不为y时执行某些操作,我必须编写类似以下的代码:

if x and not y

但是我想要写作

if x but not y

它应该和and完全一样,但是程序员需要明智地使用它来增强代码的可读性。

3
不更改解析器是不行的。在我看来,如果没有“and”,这个结构的语义是不清楚的。 - Dave Newton
你能举个例子说明你认为语义不清楚的原因吗?它的工作方式与“and”完全相同。唯一的区别是它会暗示x的逻辑值!= y的逻辑值。 - Russell
“if x but y” 是什么意思?这不是技术问题,而是“Dave认为不清楚”的问题——纯粹是个人喜好。 - Dave Newton
这将是一个糟糕的程序员滥用结构的例子。也许稍微好一点的是 unless x but y - 尽管它仍然有点垃圾。它基本上很适合我在问题中描述的用例,但不适用于其他情况 - 这就是为什么它只是一个空想! - Russell
1
我的意思是,滥用现有的构造并不难:例如 unless not x and not !y - Russell
显示剩余4条评论
3个回答

6

如果不编辑Ruby解析器和源代码并编译新版本的Ruby,你是无法做到的。如果你愿意,你可以使用这种丑陋的语法:

class Object
  def but(other)
    self and other
  end
end

x.but (not y)

请注意,您不能在此代码片段中删除括号或空格。这也会影响其他人阅读您的代码时的功能。不要这样做。

3
更重要的是,这个“解决方案”将始终评估xy(无短路),并且会按照相反的顺序(先yx)进行评估。 - Marc-André Lafortune
@Marc-AndréLafortune 这也许就是无法覆盖&&||的原因(而覆盖&|是可以的)。 - Mladen Jablanović
1
@MladenJablanović:你只需定义一组运算符(我们称之为懒惰运算符),这些运算符被翻译为a.OP{b}而不是a.OP(b),然后重写它们就完全没问题了。几年前,我重新实现了所有Ruby的布尔运算符作为消息发送,并且使用了RubySpec测试套件来验证它们的正确行为:https://GitHub.Com/JoergWMittag/B001e/顺便说一句:请关注该代码的*实际*语义...这是我编写的第一个Ruby项目,代码*非常糟糕* :-) - Jörg W Mittag
2
我同意。这个答案最好的部分就是不要去做。+1 - lucapette

2

如果你真的想做这个,尝试编辑parse.y并重新编译Ruby。那里定义了Ruby的语法。


我认为这并不适用于任何实际应用,但用户尝试使用它可能会学到一些东西。 - AwDogsGo2Heaven

0

正如其他人已经指出的那样,您无法在Ruby中定义自己的运算符。运算符集是预定义和固定的。您能做的就是通过响应适当的消息来影响一些现有运算符(即被转换为消息发送的运算符)的语义。

但是,当然,您可以很容易地实现一个but方法:

class Object
  def but
    self && yield
  end
end

Object.new.but { not true }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接