有没有技术原因使得像RSpec这样的Ruby DSL无法用Python重写?

21 投票
5 回答
3585 浏览
提问于 2025-04-16 23:42

下面的内容会详细说明,但简单来说,有人说用Ruby写的DSL RSpec不能用Python重写。这是真的吗?如果是真的,为什么呢?

我想更好地理解Ruby和Python之间的技术差异。

更新:我为什么要问这个问题?

逃离RSpec的讨论中,有人提到在Python中重建RSpec是“不可能”的。我想把问题问得更广泛一些,希望能了解更多Ruby和Python之间的技术差异。回想起来,也许我应该把问题缩小到只问在Python中重建RSpec是否真的不可能,以及如果是的话,原因是什么。

下面是逃离RSpec讨论中的一些引用。

最初的问题

过去几周我一直在思考RSpec,以及当有人问:

“我在找Python版的RSpec。在哪里可以找到这样的东西?”

时,为什么没有明确的答案。

最常见(也最能理解)的回答是Python的语法不允许这样做,而在Ruby中是可以的。

对最初问题的第一个回应

其实不是语法的问题。RSpec会在它的作用域内对每个对象进行“猴子补丁”,插入“should”和“should_not”这两个方法。你可以在Python中做一些类似的事情,但你不能对内置类型进行猴子补丁。

另一个回应

正如你所说,这确实是不可能的。Mote和PySpec只是给你的测试起个花哨的名字:它们是RSpec的一个小部分的弱实现。Mote使用了糟糕的settrace魔法;PySpec则添加了很多与领域无关的噪音。它们甚至都不支持任意的上下文字符串。RSpec更简洁、更具表现力,去掉了噪音,在Ruby中构建是完全合理的。

最后一点很重要:不仅仅是RSpec在Ruby中是可能的;它实际上是符合Ruby的习惯用法。

5 个回答

5

我开始尝试在Python中实现类似于rspec的东西。

我得到了这个:

with It('should pass') as test:
    test.should_be_equal(1, 1)

来源: https://gist.github.com/2029866

(有什么想法吗?)

编辑:我对你问题的回答是,缺少匿名代码块使得像RSpec这样的Ruby领域特定语言无法直接在Python中重写,但你可以通过使用with语句来得到一个相似的效果。

5

Ruby的一个强项就是能很方便地创建领域特定语言(DSL)。不过,关于为什么在Python中创建DSL比较困难的理由,其实可以绕过。举个例子,你可以很简单地对内置类型进行子类化,比如:

>>> class myint(int):  pass
>>> i = myint(5)
>>> i
5

如果我想在Python中创建一个DSL,我会使用pyparsing或者Parsley,并在后台使用类似上面的东西,优化语法以解决问题,而不是为了实现语言本身。

10

如果让我指出在创建Python RSpec时最大的困难,那就是Python在创建匿名函数(像JavaScript那样)或代码块(像Ruby那样)方面缺乏好的语法。对于Python程序员来说,唯一的选择就是使用lambda表达式,但这并不是一个真正的选择,因为lambda只能接受一个表达式。在RSpec中使用的do ... end代码块必须在调用describeit之前先写成一个函数,像下面这个例子:

def should_do_stuff():
    # ...
it("should do stuff", should_do_stuff)

看起来不太好,对吧?

创建should方法会有一些困难,但我敢打赌这会是一个小问题。实际上,你甚至不需要使用这种不寻常的语法——你可以使用Jasmine的语法来获得类似的结果(也许效果更好,具体看个人喜好)。

话虽如此,我觉得Python的语法更专注于高效地表示常见的程序组件,比如类、函数、变量等。它并不太适合扩展。就我个人而言,我认为一个好的Python程序是我能看到对象、函数和变量,并且我能理解这些元素各自的作用。而Ruby程序员似乎更喜欢一种类似散文的风格,为新问题定义一种新语言。这也是一种很好的做法,但不是Python的风格。Python更适合表示算法,而不是散文。

有时候这确实是个严格的限制。比如,如何使用BDD呢?通常在Python中突破这些限制的方法是自己写一个领域特定语言(DSL),但这真的应该是另一种语言。这就是Pyccuracy的意义所在:为BDD提供另一种语言。一个更主流的例子是doctest。(实际上,如果我写一个BDD的Python库,我会基于doctest来写。)另一个Python DSL的例子是Twill。还有一个例子是reStructuredText,它在Sphinx中使用。

总结一下:在我看来,Python中DSL的最大障碍是缺乏灵活的语法来创建匿名函数。这并不是一个缺陷*:Python本身就不喜欢过度探索其语法——在Python的世界里,这被认为会使代码不够清晰。如果你想在Python中使用新的语法,最好是自己写一种语言,或者至少这是我的感觉。

* 或许这确实是个缺陷——我得承认我很想念匿名函数。不过,我也意识到,考虑到Python的语义缩进,优雅地实现它们会很困难。

撰写回答