2012-08-13 4 views
5

私はまだこのエイリアン機能のパラダイムを学んでいます...リストを作成してクローゼルで返すべきですか?

私はClojureで以下のコードをどのように書くのでしょうか? この欠落部分は他の場所で定義され、コメントに記述されているように動作するものとします。 これは私がよく知っているPythonで書かれています。

usernames = [] 
# just the usernames of all the connections I want to open. 
cancelfunctions = {} 
# this global contains anonymous functions to cancel connections, keyed by username 

def cancelAll(): 
    for cancel in cancelfunctions.values(): 
     cancel() 

def reopenAll(): 
    cancelfunctions = {} 
    for name in usernames: 
     # should return a function to close the connection and put it in the dict. 
     cancelfunctions[name] = openConnection() 

チャンスは、私は、機能のいくつかの種類をコミットしていますので、私は本当に知っておく必要があるのはreopenAll機能のように、コールバックの新しい辞書を構築する方法ですが、私はここにいくつかのより多くのコンテキストを含めていますパラダイムの残虐行為であり、あなたはプログラム全体を修正したいと思うでしょう。 :)

+0

これはおそらく適切ではないが、「[エイリアン機能パラダイム](http://landoflisp.com/#guilds)」への参照を見たときに共有に抵抗することはできませんでした。 – DaoWen

答えて

6

Clojureでのデータ構造の構築には、しばしばreduceが含まれ、最終的な戻り値を累積する関数に一連の入力を供給します。戻り値open-connectionにusernameのマップ(辞書)を構築する関数を書く2通りの方法があります。

;; Using reduce directly 
(defn reopen-all [usernames] 
    (reduce 
    (fn [m name] (assoc m name (open-connection))) 
    {} usernames)) 

;; Using into, which uses reduce under the hood 
(defn reopen-all [usernames] 
    (into {} (for [name usernames] 
      [name (open-connection)]))) 

これら2つの関数は値を返し、Pythonコードのようにグローバル状態を変更しないことに注意してください。グローバル状態は本質的に悪いことではありませんが、バリュー・ジェネレーションを状態操作から分離することは良いことです。完全ためcancel-allだここ

(def usernames [...]) 
(def cancel-fns (atom nil)) 

(defn init [] 
    (reset! cancel-fns (reopen-all usernames))) 

そして:

def reopen(usernames): 
    return dict((name, openConnection()) for name in usernames) 

あなたが見つけることがあります。

(defn cancel-all [] 
    (doseq [cancel-fn (vals @canel-fns)] 
    (cancel-fn))) 
+0

ありがとう、これは非常に良い答えです! – user1552512

2

ここでのpythonで機能的なアプローチだ状態の場合、あなたはおそらく​​をお勧めします主に機能的な言語を使用しようとする前に、Pythonの関数型に "変換"する方が簡単です。

関連する問題