5

私が次のことをした場合:

user=> (-> ["1" "2"] (partial apply str)) 
#<core$partial__5034$fn__5040 clojure.core$partial__5034$fn__5040@d4dd758>

...部分関数が返されます。ただし、それを変数にバインドすると、次のようになります。

user=> (def apply-str (partial apply str))
#'user/apply-str
user=> (-> ["1" "2" "3"] apply-str)       
"123"

...コードは意図したとおりに機能します。それらは同じものだと思いますが、そうではないようです。なぜこれが私にあるのか誰かが説明できますか?

4

5 に答える 5

6

->はマクロなので、アプリケーションに関して期待するルールに従う必要はありません。マクロは、フォームが評価される前にソースを変換します。フォームをマクロ展開してみてください。

user> (macroexpand '(-> ["1" "2"] (partial apply str)))
(partial ["1" "2"] apply str)

'->'マクロを使用してここで何を達成しようとしていますか?

編集:注意:

user> ((partial apply str) ["1" "2"])
"12"
于 2010-04-05T02:49:44.147 に答える
5

あなたはそれをする必要は全くありません。

(->> ["1" "2" "3"] (apply str))

代わりにそれをしてみませんか?

于 2010-04-05T11:22:24.917 に答える
4

最初の式、、は次の(-> ["1" "2"] (partial apply str))ように展開されます。

(partial ["1" "2"] apply str)これは基本的に次のことを意味します。

Varsを使用して、最初の2つの引数として既に提供されて["1" "2"]いる関数(ベクトルはインデックスキーの関数であるため、これも関数です!)を作成します。この関数は奇妙な文字列として出力されます。ベクトルは2つのVar引数ではなく、1つの整数引数のみを取るため、この関数が呼び出される場合にのみIllegalArgumentExceptionが発生します。applystr#<core$partial...>

于 2010-04-05T16:07:27.387 に答える
1

マクロ-> 2番目の引数としてexprをフォームに通します。あなたの場合、次のように展開することになります:(partial ["1" "2"] apply str)、ベクトルに基づいてparital関数を作成します。

しかし、スレッド化されたexprのapplyとstrに基づいてparital関数を呼び出したいので、次のものが必要です。

(-> ["1" "2"] ((partial apply str)))

ええと:このコードはかなり混乱していて、慣用的なClojureではありません。

于 2010-04-05T19:12:48.450 に答える
0

->マクロは2番目のバージョンで親を追加します。そのapply-strため、マクロはコードに展開され、最終的に関数を呼び出すことになります。のソースコードを見ると、次の->ことがわかります。

(defmacro ->
  "Threads the expr through the forms. Inserts x as the
  second item in the first form, making a list of it if it is not a
  list already. If there are more forms, inserts the first form as the
  second item in second form, etc."
  ([x] x)
  ([x form] (if (seq? form)
              (with-meta `(~(first form) ~x ~@(next form)) (meta form))
              (list form x)))
  ([x form & more] `(-> (-> ~x ~form) ~@more)))

関連する部分は、2つの引数とを処理する場合xですformformがseqの場合x、そのリストの2番目の引数として挿入されます。それ以外の場合、マクロはそれをリスト自体にform入れます。xこれは、1つのシンボルを含むリストの省略形として裸のシンボルを使用できるようにするためです。

user> (macroexpand '(-> 123 (foo)))
(foo 123)
user> (macroexpand '(-> 123 foo))
(foo 123)
于 2010-04-05T17:18:12.793 に答える