2011-10-18 8 views
3

のは、私は私が欲しいものClojureではマップを持つキーが必要な関数を呼び出すことはできますか?

(defn test [ & {:keys [a b c]}] 
    (println a) 
    (println b) 
    (println c)) 

があるとしましょう{:a 1 :b 2 :c 3}マップでテストを呼び出すことです。

これは動作します:

(apply test [:a 1 :b 2 :c 3]) 

これらはしないでください。

(apply test {:a 1 :b 2 :c 3}) 
(apply test (seq {:a 1 :b 2 :c 3})) 

EDIT ですから、もちろん、このような関数を定義することができます。

(defn test [{:keys [a b c]}] ; No & 
    (println a) 
    (println b) 
    (println c)) 

そして、あなたはそれにマップを渡すことができます:

(test {:a 1 :b 2 :c 3}) 
1 
2 
3 

私が見逃していたことを学ぶとき、これが可能でした。それでもあなたは私によって定義された関数や私のような誰かに遭遇した場合、それにマップを渡す方法を知ることがまだ役に立つかもしれません;)

+1

それはあなたには、いくつかの空想な破壊をやろうとしていることを言及する価値があります。また、私はここでvariadic(&)argsをどのように使用するかについて混乱しています。もしあなたがvariadic argsを持っていなければ、あなたが望むようにマップを使ってtestを呼び出すことができます。 –

+1

あなたが助けることができるなら、この "キーワードargs"をしないのが最善の選択であると約束しました。珍しい特定のケースではいいですが、レイヤー間を行き来するのは面倒です。そして一連のキーバリューを地図にするのは簡単ですが、あなたが見たように、キーベルのシーケンスにマップを作るのは簡単ではありません。 – amalloy

+3

[ライブラリコーディング標準](http://dev.clojure.org/display/design/Library+Coding+Standards)は、アンロールの引数がマップを必要とするよりも優れていることを示唆しています(オプションの場合)。 –

答えて

4
user> (apply list (mapcat seq {:a 1 :b [2 3 4]})) 
(:a 1 :b [2 3 4]) 
1

これは動作しますが、無粋です:

(apply test (flatten (seq {:a 1 :b 2 :c 3})))

理由(apply test (seq {:a 1 :b 2 :c 3}))が機能しない理由は、(seq {:a 1 :b 2 :c 3})[[:a 1] [:b 2] [:c 3]]を返すことです。これはflattenが処理します。

+1

'flatten'を含まないものはこれ以上です。私のマップが '{:a [1 2 3]:b [4 5 6]}'ならば? – amalloy

+0

@amalloy良い点!あなたの答えをありがとう! – Paul

3

最初にこのように定義しないとよい理由はありますか?

(defn my-test [{:keys [a b c]}] ;; so without the & 
    (println a) 
    (println b) 
    (println c)) 

とします。出力

(my-test {:a 10 :b 20 :c 30}) 

10 
20 
30 
nil 
+0

最初は、あなたが '&'を除外できることを知らなかった。しかし、あなたが書いていない野生の機能に遭遇した場合、上記の問題に対する解決策を知ることは依然として有効です。 – Paul

関連する問題