2016-05-06 1 views
2

これは投稿するのに最適な場所ではないとは思いますが、なぜ2)動作しないのですか?スレッディングマクロは、seqの結果を(map str)に渡しませんか?Clojureスレッドマクロ

あなたはこのように、次の2番目の項目として、各フォームを挿入する、 thread-firstマクロを使用している
;; 1 
(map str (seq (str (* 8 8)))) -> ("6" "4") 

;; 2 
(defn a [x y] 
    (-> (* x y) 
     str 
     seq 
     (map str))) 


(a 8 8) -> Don't know how to create ISeq from: clojure.core$str 

答えて

6

:あなたが欲しい

(-> (* x y) str seq (map str)) 
(-> (str (* x y)) seq (map str)) 
(-> (seq (str (* x y))) (map str)) 
(map (seq (str (* x y))) str) 

thread-lastマクロです:

(defn a [x y] 
    (->> (* x y) str seq (map str))) 

(a 8 8) ;=> ("6" "4") 
3

として、Elogentはマクロが引数を間違った場所に置いていると指摘しています。私たちが見ることができる

user> (clojure.pprint/pprint 
     (macroexpand-1 
     '(-> (* x y) 
      str 
      seq 
      (map str)))) 
(map (seq (str (* x y))) str) 
nil 

はかなり見ていません。一般的には、マクロでの作業(特にそれらを書く)ときは約macroexpand-1を知っているし、実際に実行されているもののクリアな視界を得るためにclojure.pprint/pprintとそれを組み合わせるのに役立ちます右。それは我々が期待するものに展開されるまで、だから、次の我々はそれをいじる:

user> (clojure.pprint/pprint 
     (macroexpand-1 
     '(->> (* x y) 
       str 
       seq 
       (map str)))) 
(map str (seq (str (* x y)))) 
nil 

ときあなたは、ねじ値に明示的な名前を与えることができます。このような状況を支援するためにマクロをスレッドの様々な、特にas->があります。重要な入力のための最初と最後の引数を使って代替機能をスレッド化する必要があります。ここでは

user> (as-> (* 7 42) x 
     (str x) 
     (seq x) 
     (map str x)) 
("2" "9" "4") 
+0

非常に便利です、チップのおかげで! – jeemar

1

は、(それが右から左に読みます)知って良いです代替です:

(defn a [x y] 
    ((comp (partial map str) seq str *) 
    x y)) 

これは、適用するデータから適用する変換を分離したい(文脈に対する批判を歓迎します)場合に役立ちます。

+1

あなたの意図は良いですが、すでに変換とデータを 'a'関数に結合しているので、ここでそのアプローチから実際に何も得られません。 –

1

it->スレッドフォームの使用を検討することもできます。これはスレッド優先とスレッド最後の不安を避けるために設計されています。このコードを考えてみましょう:

(ns clj.core 
    (:use tupelo.core)) 

(defn a [x y] 
    (it-> (* x y) 
     (str it) 
     (seq it) 
     (map str it))) 

(spyx (a 8 8)) 

(defn -main []) 

生成する:

(a 8 8) => ("6" "4") 

it->マクロが明示的にどこ連続する各フォームの結果を配置するように選択するプレースホルダitを使用しています。これは、コードを単純化し、このタイプのエラーを回避する簡単な方法です。

+0

提案していただきありがとうございます。それはかなり甘いライブラリのように見えます。 – jeemar