2017-01-08 65 views
1

一年前,我使用Alphabeta prunning算法編寫了國際象棋AI。這在C++中是比較直接的。我在做這件事時考慮的一個主要問題是使我的代碼高效。我通過使用我稱之爲「遊戲」的數據類型來完成這項工作,該數據類型是通過算法創建的搜索樹傳遞的。爲了提高效率,我並沒有複製「遊戲」數據類型,而是改變了它,同時保留了將其返回到先前狀態所需的底層信息。函數式編程中的國際象棋編程

最近我一直在閱讀關於函數式編程和純粹使用函數的概念,這些函數不會改變它們傳遞給我的參數的狀態。我想知道如何使用函數式編程的範例,同時還要考慮到程序的效率。

在OOP中,解決方案似乎非常直截了當(這是我實現的),而在函數編程中似乎複製數據類型是底層的,這會降低效率。沒有這種效率損失,是否可以使用函數式編程?

回答

2

在函數式編程中,數據結構並不總是完全複製。在很多情況下,只有需要複製的部分才能被複制,而舊的部分可以被引用(因爲沒有允許變化,這是安全的)。

關於persistant data structures的文章更詳細地描述了這一點。

2

Jephron的答案指出了一個重要的事實,即只有持久數據結構的小部分需要更新,因此更大的部分是在舊狀態和新狀態之間共享的。

說實話,在大多數情況下,這仍然會比突變慢。

但是不可變的持久數據結構還有其他優點。假設您已經完成了播放引擎。現在,你想要實現一個歷史記錄(例如,讓玩家撤消早先的動作)。這很簡單:只要記住列表中的所有狀態即可。你會發現你只需要觸及幾個函數就可以獲取狀態列表,而不僅僅是最後一個狀態,而且你已經完成了。你不必擔心會影響你的遊戲引擎---沒有全局變量或者你可能破壞的東西。

另一件事是利用你可能通過採用並行機制獲得的許多CPU內核。不用說,你不能讓許多任務,線程,光纖或任何操作在單個可變數據結構上。這隻會成爲同步的噩夢,你的代碼甚至可能會變慢。但是,對於不可變數據,根本不存在同步問題,因爲它們只讀取所有線程。即使在功能性數據結構上「做一個動作」比在可變數據上慢得多,這也可能會加速代碼的速度,使得C++解決方案相形見絀。

下面是將棋盤遊戲(TTT)從單線程變爲併線的示例:https://dierk.gitbooks.io/fregegoodness/content/src/docs/asciidoc/incremental_episode4.html