web-dev-qa-db-ja.com

Clojure-名前付き引数

Clojureには名前付き引数がありますか?もしそうなら、あなたはそれの小さな例を提供してもらえますか?

77

Clojure 1.2では、マップを非構造化するのと同じように、rest引数を非構造化できます。これは、名前付きの非定位置キーワード引数を実行できることを意味します。次に例を示します。

user> (defn blah [& {:keys [key1 key2 key3]}] (str key1 key2 key3))
#'user/blah
user> (blah :key1 "Hai" :key2 " there" :key3 10)
"Hai there10"
user> (blah :key1 "Hai" :key2 " there")
"Hai there"
user> (defn blah [& {:keys [key1 key2 key3] :as everything}] everything)
#'user/blah
user> (blah :key1 "Hai" :key2 " there")
{:key2 " there", :key1 "Hai"}

Anything上記のように、Clojureマップの構造化を関数の引数リストで行うことができます。このような引数のデフォルトを定義するために:orを使用することを含む:

user> (defn blah [& {:keys [key1 key2 key3] :or {key3 10}}] (str key1 key2 key3))
#'user/blah
user> (blah :key1 "Hai" :key2 " there")
"Hai there10"

しかし、これはClojure 1.2にあります。または、古いバージョンでは、これを実行して同じことをシミュレートできます。

user> (defn blah [& rest] (let [{:keys [key1 key2 key3] :or {key3 10}} (apply hash-map rest)] (str key1 key2 key3)))
#'user/blah
user> (blah :key1 "Hai" :key2 " there")
"Hai there10"

一般的には同じように機能します。

また、キーワード引数の前に位置引数を指定することもできます。

user> (defn blah [x y & {:keys [key1 key2 key3] :or {key3 10}}] (str x y key1 key2 key3))
#'user/blah
user> (blah "x" "Y" :key1 "Hai" :key2 " there")
"xYHai there10"

これらはオプションではなく、提供する必要があります。

Clojureコレクションと同じように、rest引数を実際に非構造化できます。

user> (defn blah [& [one two & more]] (str one two "and the rest: " more))
#'user/blah
user> (blah 1 2 "ressssssst")
"12and the rest: (\"ressssssst\")"

Clojure 1.1でもこの種のことができます。ただし、キーワード引数のマップスタイルの構造化は1.2でのみ行われました。

116
Rayne

Raynesの優れた答えに加えて、 clojure-contribのマクロ があります。

 user =>( '[clojure.contrib.def:only [defnk]]を使用)
 nil 
 user =>(defnk foo [ab:c 8:d 9] 
 [abcd])
# 'user/foo 
 user =>(foo 1 2)
 [1 2 8 9] 
 user = >(foo 1 2 3)
 Java.lang.IllegalArgumentException:キーに値が指定されていません:3(NO_SOURCE_FILE:0)
 user =>(foo 1 2:c 3)
 [1 2 3 9] 
33
Alex Taggart

Clojureバージョン1.8では、キーワードのサポートはまだ少しmehのようです。

次のようなキーワード引数を指定できます。

(defn myfn1
  "Specifying keyword arguments without default values"
  [& {:keys [arg1 arg2]}]
  (list arg1 arg2))

呼び出しの例:

(myfn1 :arg1 23 :arg2 45)  --> evaluates to (23 45)
(myfn1 :arg1 22)           --> evaluates to (22 nil)

これらのキーワード引数のデフォルト値を指定する場合:

(defn myfn2
  "Another version, this time with default values specified"
  [& {:keys [arg1 arg2] :or {arg1 45 arg2 55}}]
  (list arg1 arg2))

これは、2番目のケースで期待されることを行います。

(myfn2 :arg1 22)           --> evaluates to (22 55)

各言語の各部分には長所と短所がありますが、比較のためだけに、Common LISPで同じことを行う方法を次に示します。

(defun myfn3
    (&key arg1 arg2)
    "Look Ma, keyword args!"
    (list arg1 arg2))

(defun myfn4
    (&key (arg1 45) (arg2 55))
    "Once again, with default values"
    (list arg1 arg2))
1
agam

おそらく、名前付きパラメーターを意味しますか?これらは直接利用できませんが、必要に応じて このベクトルを使用 することができます。

At RosettaCode 破壊を使用してこれを行う方法について、より詳細な説明があります。

0
Abel