什么是“表达式问题”?

60

我大致知道这是什么,但如果有人能够简明易懂地解释"表达式问题",我将非常乐意听取。


鉴于这是一个相当复杂的概念,我不确定你能够通过“简洁直观”的解释走得很远,尽管我很乐意被证明是错误的! - Gian
没有玩笑:)一个不完整(可能略有不准确),但是有启发性的隐喻就足够了。 - James
2
参见 Expression Problem 的完整解决方案? - Shelby Moore III
3个回答

52

观看这个讲座

这个想法是,你的程序是一个数据类型和对其进行操作的组合。该问题要求实现一种允许添加新类型的情况和新操作而无需重新编译旧模块并保持静态类型安全性(无强制转换或运行时类型检查)的实现。

有趣的是,在函数式编程语言中,添加新操作很容易,但添加数据类型的情况很难。而在面向对象语言中,则相反。这是两种编程范例之间的一个重要概念差异。


3
这里有一个解决表达式问题的方案,展示了如何在Clojure(函数式编程语言)中解决。链接为: https://gist.github.com/elnygren/e34368a86d62f0cb75f04ba903f7834a - elnygren
6
@elnygren 我 fork 了你的 Gist,并用 Haskell 替换了你的代码:https://gist.github.com/chrisdone/7e07b3a90474542c9d1ebef033c1ee6e - Christopher Done
3
这里有一个带有Scala示例的额外分支:https://gist.github.com/izmailoff/41c7f790eb97042c307885388754a0be - yǝsʞǝla
1
讲座的原始链接似乎已经过期。 我认为这个是有效的链接。 - Cnly

22

问题的背后思想是文本是一维的。即使你有行和列,你通常会逐字逐句地阅读它。编译器也是如此。

而你试图在其中表示某种二维或多维数据。例如,按行主序排列的表格看起来像这样:

((A, B, C), (D, E, F), (G, H, I))
在这种表示法中,很容易在结尾添加新行,而不必触及其他部分。
((A, B, C), (D, E, F), (G, H, I), (J, K, L))

不过添加列有些棘手,需要在4个不同的位置进行修改:

((A, B, C, M), (D, E, F, N), (G, H, I, O), (J, K, L, P))

在实践中,处理抽象类时通常会遇到这个问题:添加新的子类型作为新模块非常容易,但是当您添加新的抽象方法时,您需要触及所有模块并将其添加;您需要在许多地方执行相同的操作。通常,您会进行抽象来防止这些重复的事情。

只要使用一维表示形式,就没有解决此问题的方法。

解决此问题的方法是使用可以让您像编辑真正的表格一样编辑这些表格式内容的编辑器(在 Excel 类视图中,您可以轻松添加新列和行)。


3

这里还有一篇关于解决Clojure问题的文章, 尽管该问题是用Java呈现的,但即使您不了解Clojure,特别是在小图表的帮助下,也应该能够理解。

其中说道:

贝尔实验室的Philip Wadler在1998年通过电子邮件传播了一篇未发表的论文,提出了表达式问题的术语。正如他所说,“表达式问题是一个旧问题的新名称。目标是通过情况来定义数据类型,在保留静态类型安全性(例如,没有强制转换)的同时,可以向数据类型添加新情况和新函数,而无需重新编译现有代码。”


目前已经有一个Java实现可用 - Curiosa Globunznik
文章原文已经消失,以下是该文章的网络存档链接:https://web.archive.org/web/20200603133533/http://www.ibm.com/developerworks/library/j-clojure-protocols/ - slikts

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