2013-10-03 58 views
0

我真的很感興趣成爲Clojure/Clojurescript的Web應用程序精通者。現在,我正在製作簡單的命令行應用程序來感受語言。瞭解Clojure的方法

但是現在很難掌握如何在沒有可變變量的語言中完成任務的工作流程。

我的問題是:我做一點點RPN計算器,其中用戶可以輸入數字添加到一個堆棧,也做在棧上的數學運算:

> ;adding to stack 
> 4 4 
> ; print the stack 
> [4, 4] 
> 2 3 
> p 
> [4 4 2 3] 
> ; adding the top two items to the stack 
> + 
> p 
> [4 4 5] 
> + - 
> p 
> [-5] 

所以我的問題是,如何跟蹤堆棧,如果沒有變量。我首先使用Java堆棧在Java中編寫了這個代碼,顯然在Clojure中這將是一種非常不同的方法,但我不太確定解決問題的方法。

回答

1

雖然它的工作,我會避免atom/ref方法,因爲這些不是真正的「Clojure方式」。 (他們有些問題的正確工具,但不是這個)。堆棧框架方法更符合Clojure哲學。

要展開在堆疊幀溶液中,每次操作中的應用將是一個函數,如:

new-stack (apply-op stack op) 

操作等+和 - 將做明顯,而「P」將具有副作用效果(IO),但返回原始堆棧。

循環是微不足道的,然後:

(loop [stack [] op (get-op!)] 
    (if (not= 'q op) 
     (recur (apply-op stack op) (get-op!)))) 

我假定「Q」的終止命令的象徵,並獲得-OP!作爲閱讀操作。

另外值得注意的是,由於first/rest/cons的所需操作已經可用,所以「堆棧」更自然地用列表實現。例如,應用任何二進制運算符基於列表的棧就是:

(cons (the-operator (first stack) (second stack)) (rest (rest stack))) 

或者用解構爲清楚:

(let [[a b & r] stack] (cons (the-operator a b) r)) 

使用向量作爲堆棧也不是那麼容易,也沒有效率。

1

您可以使用類似於Java的方式將它與atomref結構化,以跟蹤當前堆棧或將問題重構爲遞歸循環,以便將當前堆棧「存儲」到調用堆棧。後一種解決方案可能會使用很多堆棧幀,因此您需要使用recur來防止堆棧溢出。

+0

好的,謝謝你的回答。 – Emil