ClojureScript 宏出错了
ClojureScript Macro Gone Awry
目标: 我正在尝试制作一个宏,其输入如下所示:
(cb-chan (.readFile "/path/to/file" "utf8" _))
和 returns 作为如下输出:
(go (let [c (chan 1)
rep (.readFile "path/to/file" "utf8" (>? c)] ; >? is a function that I defined elsewhere that jams the result of a callback into a channel
rep
(<! c))))
请注意,原始输入中的 _
已被特殊回调(在别处定义)所取代。此回调将其结果塞入一个通道,然后在 go 块的末尾检索并返回。
尝试:
(defmacro cb-chan [func]
`(cljs.core.async.macros/go
(let [~'c (cljs.core.async/chan 1)]
~'rep (replace (quote {~'_ (cljs-async-patterns.core/>? ~'c) }) (quote ~func))
~'rep
(~'<! ~'c))))
结果: 这失败了,因为 rep
最终只是一个文字的、未计算的列表。如果我能够在倒数第二行键入 (eval rep)
而不是仅键入 rep
,我的问题就会得到解决,但我不能,因为我正在使用 ClojureScript(没有 eval)。我该如何解决这个问题?
首先,您需要的可能有点不同。查看您想要的代码
(go (let [c (chan 1)
rep (.readFile "path/to/file" "utf8" (>? c)]
rep
(<! c))))
你真的需要绑定一个变量rep
吗?你想要的可能是这样的:
(go (let [c (chan 1)]
(.readFile "path/to/file" "utf8" (>? c)
(<! c))))
因为不需要rep
但是,您应该考虑重新阅读一些有关宏的文章,因为这里有乱七八糟的随机引用和取消引用。
生成代码的宏如下所示:
(defmacro cb-chan [func]
(let [c (gensym "c")]
`(cljs.core.async.macros/go
(let [~c (cljs.core.async/chan 1)
rep# ~(replace {'_ `(cljs-async-patterns.core/>? ~c)} func)]
rep#
(cljs.core.async/<! ~c)))))
它将 (cb-chan (.readFile "/path/to/file" "utf8" _))
扩展为:
(cljs.core.async.macros/go
(let [c19307 (cljs.core.async/chan 1)
rep__19301__auto__ (.readFile
"/path/to/file"
"utf8"
(cljs-async-patterns.core/>? c19307))]
rep__19301__auto__
(cljs.core.async/<! c19307)))
对于我的变体(没有 rep
):
(defmacro cb-chan [func]
(let [c (gensym "c")]
`(cljs.core.async.macros/go
(let [~c (cljs.core.async/chan 1)]
~(replace {'_ `(cljs-async-patterns.core/>? ~c)} func)
(cljs.core.async/<! ~c)))))
扩展为:
(cljs.core.async.macros/go
(let [c19313 (cljs.core.async/chan 1)]
(.readFile
"/path/to/file"
"utf8"
(cljs-async-patterns.core/>? c19313))
(cljs.core.async/<! c19313)))
目标: 我正在尝试制作一个宏,其输入如下所示:
(cb-chan (.readFile "/path/to/file" "utf8" _))
和 returns 作为如下输出:
(go (let [c (chan 1)
rep (.readFile "path/to/file" "utf8" (>? c)] ; >? is a function that I defined elsewhere that jams the result of a callback into a channel
rep
(<! c))))
请注意,原始输入中的 _
已被特殊回调(在别处定义)所取代。此回调将其结果塞入一个通道,然后在 go 块的末尾检索并返回。
尝试:
(defmacro cb-chan [func]
`(cljs.core.async.macros/go
(let [~'c (cljs.core.async/chan 1)]
~'rep (replace (quote {~'_ (cljs-async-patterns.core/>? ~'c) }) (quote ~func))
~'rep
(~'<! ~'c))))
结果: 这失败了,因为 rep
最终只是一个文字的、未计算的列表。如果我能够在倒数第二行键入 (eval rep)
而不是仅键入 rep
,我的问题就会得到解决,但我不能,因为我正在使用 ClojureScript(没有 eval)。我该如何解决这个问题?
首先,您需要的可能有点不同。查看您想要的代码
(go (let [c (chan 1)
rep (.readFile "path/to/file" "utf8" (>? c)]
rep
(<! c))))
你真的需要绑定一个变量rep
吗?你想要的可能是这样的:
(go (let [c (chan 1)]
(.readFile "path/to/file" "utf8" (>? c)
(<! c))))
因为不需要rep
但是,您应该考虑重新阅读一些有关宏的文章,因为这里有乱七八糟的随机引用和取消引用。
生成代码的宏如下所示:
(defmacro cb-chan [func]
(let [c (gensym "c")]
`(cljs.core.async.macros/go
(let [~c (cljs.core.async/chan 1)
rep# ~(replace {'_ `(cljs-async-patterns.core/>? ~c)} func)]
rep#
(cljs.core.async/<! ~c)))))
它将 (cb-chan (.readFile "/path/to/file" "utf8" _))
扩展为:
(cljs.core.async.macros/go
(let [c19307 (cljs.core.async/chan 1)
rep__19301__auto__ (.readFile
"/path/to/file"
"utf8"
(cljs-async-patterns.core/>? c19307))]
rep__19301__auto__
(cljs.core.async/<! c19307)))
对于我的变体(没有 rep
):
(defmacro cb-chan [func]
(let [c (gensym "c")]
`(cljs.core.async.macros/go
(let [~c (cljs.core.async/chan 1)]
~(replace {'_ `(cljs-async-patterns.core/>? ~c)} func)
(cljs.core.async/<! ~c)))))
扩展为:
(cljs.core.async.macros/go
(let [c19313 (cljs.core.async/chan 1)]
(.readFile
"/path/to/file"
"utf8"
(cljs-async-patterns.core/>? c19313))
(cljs.core.async/<! c19313)))