私がフォームの式を持っていることを考えると
'(map? %)
どうすればそれを次のようなものに変換できますか
'#(map? %)
最終的に次のようなものに拡張できるように
'(apply #(map? %) value)
何らかの方法でマクロを使用する必要があると思いますが、方法がわかりません。
私がフォームの式を持っていることを考えると
'(map? %)
どうすればそれを次のようなものに変換できますか
'#(map? %)
最終的に次のようなものに拡張できるように
'(apply #(map? %) value)
何らかの方法でマクロを使用する必要があると思いますが、方法がわかりません。
リーダー マクロの#
呼び出しとリーダー マクロの展開は、通常のマクロ展開が発生する前に発生します。したがって、あなたが言及したことを行うには、read-string
以下に示すようにマクロでリーダーを通過する必要があります。
(defmacro pred [p v]
(let [s# (str \# (last p))]
`(apply ~(read-string s#) ~v)))
user=> (pred '(map? %) [{}])
true
user=> (pred '(map? %) [[]])
false
データ、つまり述語式が実行時に利用できる場合は、関数を使用する必要があります (マクロよりも柔軟です)。
(defn pred [p v]
(let [s (read-string (str \# p))]
(eval `(apply ~s ~v))))
user=> (map #(pred % [12]) ['(map? %)'(even? %)])
(false true)
#(...)
リーダーマクロです。リーダーマクロで式を生成できるとは思いません。たとえば、'#(map? %)
自動的に(fn* [p1__352#] (map? p1__352#))
または同様のものに展開されます。
これは、他のリーダー マクロに関するやや関連性のある議論です。
述語の形式を変更することは可能でしょうか? 次のような場合:
'([arg1] (map? arg1))
次に、関数をそれから作成するのは簡単です。
(cons 'fn '([arg1] (map? arg1)))
(def pred (eval (cons 'fn '([p](map? p)))))
#'predicate.core/pred
(pred {})
true
(pred 10)
false
次に投稿する内容について、私を嫌いにならないでください。関数リーダー マクロの非常に単純化されたバージョンを作成しました。
(defn get-args [p]
(filter #(.matches (str %) "%\\d*")
(flatten p)))
(defn gen-args [p]
(into []
(into (sorted-set)
(get-args p))))
(defmacro simulate-reader [p]
(let [arglist (gen-args p)
p (if (= (str (first p)) "quote")
(second p)
p)]
(list 'fn (gen-args p) p)))
それを使用するのは非常に簡単です。
((simulate-reader '(map? %)) {}) ; -> true
; or without quote
((simulate-reader (map? %)) {})
; This also works:
((simulate-reader '(+ %1 %2)) 10 5) ; -> 15
@Ankur が提供する他のソリューションとの違いは次のとおりです。