Julia 中的表達問題(Expression problem in Julia)
本篇文章是啟發自 The Expression Problem and its solutions,當中談論的是在撰寫程式的過程中,所採用的程式典範不同,會在程式表達上遇到不同程度的困難,稱之為表達問題(expression problem)。
物件導向語言中的表達問題
以原文中的例子,作者想以物件導向語言來撰寫一個簡單的 expression evaluator。基本上採用直譯器模式(interpreter pattern),這邊我把程式碼以 python 重寫。
1 | class Expr: |
1 | class Constant(Expr): |
我們先定義了一個 Expr
,我們希望提供 tostring
及 eval
兩種操作。我們後續定義了常數 Constant
,也讓常數實作這兩種操作。
如果我們想要擴充 Expr
或是 Constant
的時候該怎麼做呢?更精確地說,如果我們想要新增新的操作到既有的類別上,我們該怎麼做?一般情況下可能就是直接在原有的類別上加上新的方法。不過這樣其實違反了軟體工程原則,開放封閉原則(open-closed principle),我們應該要對舊有的類別、方法、介面等等程式碼修改保持封閉,也就是不能去修改既有程式碼,我們應該對新增程式碼保持開放,也就是允許新增程式碼。
我們可以發現在物件導向語言當中,新增類別是容易的,但是新增方法是困難的。這是在物件導向語言中所遇到的表達問題。
函數式語言中的表達問題
以 Haskell 為例,撰寫以上的程式(這邊直接引用原文)。
1 | data Expr = Constant Double |
在 Haskell 中,要新增方法是容易的,但是如果要新增型別的話,就得動到 data
的定義。在函數式語言中,新增型別是困難的。這是在函數式語言中所遇到的表達問題。
Julia 語言中的表達問題?
文章中有提到 Clojure 採用的是 multi-methods,他可以對應到 Julia 的多重分派(multiple dispatch)。多重分派可以好好地處理表達問題,讓新增型別及方法都是簡單的。
1 | abstract type Expr end |
不過他文末也有提到一個關鍵是 open method,也就是將方法定義在類別之外,如此一來,新增方法就會是簡單的。所以真正解決表達問題的並不是多重分派的機制,而是 open method 的設計。