【问题标题】:ClojureScript Macro Gone AwryClojureScript 宏出错了
【发布时间】:2016-02-02 17:36:26
【问题描述】:

目标:我正在尝试制作一个宏,该宏将以下内容作为输入:

(cb-chan (.readFile "/path/to/file" "utf8" _))

并作为输出返回如下:

(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)。我该如何解决这个问题?

【问题讨论】:

  • 你在这里想要什么还不清楚。字符串没有.readFile 方法,所以(.readFile "/path/to/file") 永远不会是正确的。完全没有理由写(let [rep (foo)] rep x),而不仅仅是写(do (foo) x)。您可能只想写 ~(replace ...) 而不是 (replace ...),但很难确定,因为您想要的输入和输出并不完全有意义。

标签: clojure clojurescript


【解决方案1】:

首先,您需要的可能有点不同。看看你想要的代码

(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)))

【讨论】:

  • 我最初的问题并没有像它本来的那样完善,但这个答案非常清楚。
猜你喜欢
  • 2015-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-24
  • 2012-11-29
  • 2020-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多