7

this のような関数を明示的に定義すると(defn f [x] (get x "a"))、両方とも(-> {"a" 1} f)期待どおりに機能(f {"a" 1})します。

ただし、匿名関数を使用している場合、機能するだけで例外(#(get % "a") {"a" 1})(-> {"a" 1} #(get % "a"))スローされます。CompilerException java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot \ be cast to clojure.lang.ISeq, compiling:(NO_SOURCE_PATH:1:1)

4

1 に答える 1

12

#(get % "a")読者によって展開されます:

 user=> '#(get % "a")
 (fn* [p1__852#] (get p1__852# "a"))

この場合、fn と fn* の違いは無視できます。

(-> ...)引数を再スレッド化するだけのマクロです:

user=> (macroexpand-1 '(-> {"a" 1} f))
(f {"a" 1})

f の周りに括弧がまだない場合にのみ括弧をラップすることに注意してください。

user=> (macroexpand-1 '(-> {"a" 1} (f)))
(f {"a" 1})

fnしかし、マクロに適用すると期待どおりに動作しません。

user=> (macroexpand-1 '(-> {"a" 1} (fn [x] (get x "a"))))
(fn {"a" 1} [x] (get x "a"))

または #(...) リーダーフォーム:

user=> (macroexpand-1 '(-> {"a" 1} #(get % "a")))
(fn* {"a" 1} [p1__867#] (get p1__867# "a"))

一般的な解決策は、匿名関数をリスト内に配置することですが、名前付き関数を使用できる場合は、より明確に読み取れると思います。

user=> (macroexpand-1 '(-> {"a" 1} (#(get % "a"))))
((fn* [p1__870#] (get p1__870# "a")) {"a" 1})
于 2013-06-06T08:15:35.087 に答える