我想用 ruby 编写一个小的 DSL 来进行简单的算术运算。它看起来像这样:
whats 1 + 1
=> 2
whats 2 * 2
=> 4
用例是教我的孩子编程。我正在向她展示基本的编程irb
,当我给她键盘时,她输入了“whats 2 + 2”——可能用 ruby 吗?
由于 Ruby 的运算符优先级,你想要的东西不能那么优雅地完成。换句话说,因为与(and )whats 1 + 1
相同,所以该方法不知道在其参数中发生了操作。whats(1 + 1)
whats(2)
whats
您必须覆盖Fixnum#+
(和任何其他运算符)才能返回某种构建器对象。例如:
MathQuery = Struct.new(:left, :operator, :right)
class Fixnum
def + other
MathQuery.new(self, :+, other)
end
end
然后1 + 1
将返回一个 MathQuery 实例,该实例whats
将接收并知道如何处理。
当然,这样做的问题是您还需要以某种方式使正常的数学运算仍然有效,因为很多代码显然都希望它们能够工作。不过,不太确定如何做到这一点。也许如果一切都总是被强迫to_int
等等......</p>
在这种情况下,您最好使用类似Treetop的东西编写一个真正的迷你语言和解析器。
其实,很简单:
def whats expr; expr end
whats 1 + 1
# => 2
编写一个名为“whats”的方法,接受任意数量的参数,匹配运算符部分,然后继续。