15

関数へのオプションのフラグとしてキーワードを実装する最良の方法は何ですか? 次のような関数呼び出しを行いたい:

(myfunction 5)
(myfunction 6 :do-this)
(myfunction 3 :go-here)
(myfunction 2 :do-this :do-that)

defn を使用すると、次のような関数を定義できます。

(defn myfunction [value & flags] ... )

しかし、flagsリストになります。リストを検索する独自の関数を作成できますが、そのような関数はコア ライブラリに含まれていないため、慣用的ではないと思います。

私が今使っているもの:

(defn flag-set? [list flag] (not (empty? (filter #(= flag %) list))))
(defn flag-add [list flag] (cons flag list))
(defn flag-remove [list flag] (filter #(not= flag %) list))
4

5 に答える 5

9

リスト (およびベクターとマップ) は、値ベースのルックアップ (線形時間になります) のデータ構造として適切な選択ではありません。そのため、clojure.core にはそのような関数がありません。

セットは「contains?」を介して高速な値ベースのルックアップを提供します。

(defn foo [value & flags]
  (let [flags (set flags)]
    (if (contains? flags :add-one)
      (inc value)
      value)))

複数のフラグがない場合は、次のように分割を使用できます。

(defn foo [value & [flag]] …)
于 2009-06-25T22:36:42.830 に答える
5

clojure.contrib.def-マクロが含まれているdefnkため、キーワード引数を使用して関数を簡単に定義できます。

于 2009-06-26T09:05:52.573 に答える
1

次のように、オプションのパラメーターの分解にハッシュマップバインディングを使用できます。

(defn myfunction 
  [value & {:keys [go-there do-this do-that times] :or {times 1}}]
  {:pre [(integer? times) (< 0 times)]}
  (println "Saw a" value)
  (when go-there
    (dotimes [n times]
      (when do-this (println "Did THIS with" value))
      (when do-that (println "Did THAT with" value)))))

上記の関数は、次の方法で呼び出すことができます。

(myfunction "foo" :go-there true :do-this true :do-that false :times 5)

:or {times 1}句を使用してキーのデフォルト値を定義できることに注意してください。次の関数呼び出しは、そのデフォルトにより 1 回だけループします。

(myfunction "foo" :go-there true :do-this true :do-that false)

また、Clojure の事前条件式{:pre [...]}を使用すると、パラメーター バインドの直後の式でわかるように、パラメーターのテストを便利に行うことができます。これは、構造化解除されたキーの値にも適用されます。次の呼び出しは、前提条件チェックが原因で失敗します。

(myfunction "foo" :go-there true :do-this true :do-that false :times -1)
于 2014-05-13T19:41:25.443 に答える
0

これは厳密に言えば、これを書く最も効率的な方法ではありませんが、明らかです

(defn myfunction [値とフラグ]
  (cond (contains? (セットフラグ) :a) 1
        (含む? (フラグを設定) :b) 2)

因数分解 (フラグを設定) する方が効率的です。

于 2009-06-25T22:34:23.773 に答える