2012-04-26 18 views
7

我只是寫了這個代碼:如何更好地遍歷國家Clojure中(單子?)

(defn parameters [transform-factory state] 
    (lazy-seq (let [[r1 state] (uniform state) 
        [r2 state] (uniform state) 
        [t state] (transform-factory state)] 
       (cons [t [r1 r2]] (parameters transform-factory state))))) 

(defn repeated-transform [mosaic n transform-factory state] 
    (reduce transform-square mosaic 
    (take n (parameters transform-factory state)))) 

parameters函數生成從state產生的價值,這是用來進行參數重複改造的懶惰序列的東西(在這種情況下是「馬賽克」)。

在我看來,parameters顯示了一個相當常見的模式,當你必須攜帶一些state(在這種情況下產生隨機值)時,它會顯示出來。有沒有這個名字?

有沒有更好的方法來編寫第一個函數?相關的問題通常可以通過reduce來解決,而這個「攜帶」狀態,但是在這裏我沒有什麼可以減少的。同樣,reductions似乎不適合。這是一個monad的好例子嗎? (從理論上看,我沒有看到你如何定義一種將多個實例組合成一個的方法,但也許這並不會改變實際應用 - 它看起來像monads在其他地方解決的那種問題,某些州需要被帶走)。 (ps我提到了隨機數字,但我不能用一個在幕後使用可變狀態的解決方案替代這個 - 因爲「正常的」隨機例程會這樣做 - 這是與問題無關的原因)。

+0

>(ps我提到了隨機數字,但我不能用一個在幕後使用可變狀態的解決方案替代這個 - 因爲「正常」的隨機例程 - 因爲與問題無關的原因)。 你可以使用a)帶有種子的僞隨機生成器,或者b)複製可變狀態(以便它不可變)。我採用這種方法來實施[純粹的mersenne twister] [1]。 [1]:http://hackage.haskell.org/package/mersenne-random-pure64-0.2.0.3 – 2012-04-26 20:36:58

+0

我來這裏問完全相同的問題 – jes5199 2012-04-26 20:51:14

+0

@DonStewart - 我不明白那是怎麼回事改變我所問的。實際上,我正在做的是複製這個狀態 - 這就是'狀態'的上面,以及我的問題的根源。 – 2012-04-26 22:05:29

回答

4

你當然可以看看狀態monad,看看它是否適合你。

一般準則使用的單子是:

  • 順序執行(流水線作業)
  • 重複使用的模塊化副作用的處理(例如:錯誤處理/記錄/ 狀態)
  • 保持你的業務邏輯乾淨在純函數

我發現非常有用(對於Clojure)單子上的一些資源是

亞當Smyczek: 介紹單子(視頻) http://www.youtube.com/watch?v=ObR3qi4Guys

和 吉姆Duey: 單子Clojure中 http://www.clojure.net/2012/02/02/Monads-in-Clojure/

+0

謝謝 - 我來看看。希望這是一個衆所周知的問題,但顯然不是,所以有「最好的答案」cookie:o) – 2012-04-28 13:55:40

3

[回答我自己,因爲這是最好的解決方案,我發現到目前爲止]

您可以將上述內容改寫爲功能上的摺疊。所以函數變成數據,狀態是「通過」,並且所使用的函數將每個函數依次應用到狀態並累積結果。

我看不到一個優雅的方式來實現這一點 - 被摺疊的功能看起來是「新」,你需要額外的樣板來添加/分離狀態和累加器 - 所以我把整個過程包裝在一個函數稱爲fold-oversource is herean example of the function in use is here

+0

這感覺很接近我。這似乎也許這種方法與一些宏可以變成一個摺疊'let',也許這將是有用的。 – jes5199 2012-05-01 17:44:18

+0

是啊,接下來我需要了解clojure中的宏... – 2012-05-01 18:07:30

3

你應該檢查的東西是->->>,線程宏。

,而不是像這樣的代碼:

(let [state (dosomething state) 
     state (dosomethingelse state) 
     state (dolastthing state)] 
    state) 

你可以寫:

(-> state (dosomething) (dosomethingelse) (dolasttthing)) 

其中 「線程」 狀態,通過功能,最終恢復它。

現在,您的代碼並不完全遵循我所寫的內容。我想它可以遵循的方式是,如果你的功能採取並返回hashmaps。即(統一狀態)可以返回{:state state-val :r1 r1-val}

然後,你可以重寫你的代碼是這樣的:

(->> {:state state} (merge uniform) (merge uniform) (transform-factory)) 

的效果好很多! :)

+0

oooh。謝謝!將着眼於此。聽起來不錯。 – 2012-05-02 22:13:45

相關問題