邏輯程式設計與函式程式設計的介紹

banq發表於2013-11-19
邏輯程式設計(又稱關係正規化)的突出優勢是什麼?因為該死的美學,邏輯程式設計簡直太美了,他們自然的宣告勝過於函數語言程式設計中的任何寶石。邏輯程式設計使用搜尋,這樣能夠就不會被演算法細節牽著鼻子走,如果你還沒有嘗試過Prolog,關係程式設計簡直無法讓人想象。

學習關係正規化最重要原因是因為它有趣。

swannodette/logic-tutorial提供了在Clojure 下學習邏輯程式設計的開源專案。

準備:
鍵入lein repl或cake repl
進入Cojure提示介面,輸入:
user=> (require 'clojure.core.logic)
user=> (load "logic_tutorial/tut1")
user=> (in-ns 'logic-tutorial.tut1)
這樣就準備好了環境。

關係程式設計是問計算機問題,在問問題之前,我們需要計算機瞭解一些事實,比如男人。
tut1=> (defrel man x)
#'tut1/man
然後定義幾個不同名字的人:
tut1=> (fact man 'Bob)
nil
tut1=> (fact man 'John)
nil
然後我們就可以提問男人是誰?問問題使用run,希望計算機將可能的答案給q:
tut1=> (run 1 [q] (man q))
(John)

我們剛才問了只有一個答案的問題,可以問超多個答案的問題:
tut1=> (run 2 [q] (man q))
(John Bob)

如果問更多呢?
tut1=> (run 3 [q] (man q))
(John Bob)

同樣回答。這是因為我們已經告訴計算機這個世界上有兩個男人,它不能給我們它不知道的。

下面讓我們定義另外一種關係和事實:
tut1=> (defrel fun x)
#'tut1/fun
tut1=> (fact fun 'Bob)
nil
問一個新問題:
tut1=> (run* [q] (man q) (fun q))
(Bob)
我們使用run*,這意味著所有這個問題的答案都會出現,問題是:誰是男人而且有趣。

再定義新的:
tut1=> (defrel woman x)
#'tut1/woman
tut1=> (fact woman 'Lucy)
nil
tut1=> (fact woman 'Mary)
nil
tut1=> (defrel likes x y)
#'tut1/likes

關係不一定有關單個實體,可以在事情之間定義關係:
tut1=> (fact likes 'Bob 'Mary)
nil
tut1=> (fact likes 'John 'Lucy)
nil
tut1=> (run* [q] (likes 'Bob q))
(Mary)
我們可以問誰喜歡誰這樣的關係問題。

tut1=> (run* [q] (likes 'Mary q))
()
卻沒有答案,因為我們沒有說過Mary被誰喜歡,只有“Bob喜歡Mary”。

看看:
tut1=> (fact likes 'Mary 'Bob)
nil
tut1=> (run* [q] (fresh [x y] (likes x y) (== q [x y])))
([Mary Bob] [Bob Mary] [John Lucy])

這裡fresh是 Clojure vector類似陣列,存放誰喜歡誰很多可能值。

再看看:
tut1=> (run* [q] (fresh [x y] (likes x y) (likes y x) (== q [x y])))
([Mary Bob] [Bob Mary])
只列出誰彼此喜歡的人。

完,有興趣者可進入專案主頁繼續學習研究。


相關文章