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 関数のように、コールバックの新しい dict を構築する方法だけですが、ここにさらにコンテキストを含めます。これは、ある種の機能パラダイムの残虐行為を犯している可能性があるためです。おそらくプログラム全体を修正したいと考えています。:)

4

2 に答える 2

6

Clojure でのデータ構造の構築にはreduce、最終的な戻り値を蓄積する関数に一連の入力を供給する が含まれることがよくあります。username から の戻り値へのマップ (つまり、辞書) を作成する関数を作成する 2 つの方法を次に示しますopen-connection

;; 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 コードのようにグローバル状態を変更しないことに注意してください。グローバルな状態は本質的に悪いわけではありませんが、値の生成を状態操作から切り離すのは良いことです。状態については、おそらく次のものが必要ですatom

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

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

そして、ここcancel-allに完全を期すためのものがあります:

(defn cancel-all []
  (doseq [cancel-fn (vals @canel-fns)]
    (cancel-fn)))
于 2012-08-13T19:48:33.547 に答える
2

Pythonでの機能的なアプローチは次のとおりです。

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

主に関数型言語を使用する前に、Pythonで関数型スタイルに「翻訳」する方が簡単な場合があります。

于 2012-08-13T20:04:19.697 に答える