使用-?>;用Clojurescript?

使用-?>;用Clojurescript?,clojure,clojurescript,Clojure,Clojurescript,在我的Clojure共享资源中,我有以下内容(我无耻地偷了): 在我的Clojurescript代码中,我有以下内容(I:要求宏为c) 不幸的是,当我编译时,我得到: WARNING: Use of undeclared Var webstack.client/-?> at line 56 cljs-src/webstack/client.cljs WARNING: Use of undeclared Var webstack.client/-?> at line 57 cljs-s

在我的Clojure共享资源中,我有以下内容(我无耻地偷了):

在我的Clojurescript代码中,我有以下内容(I:要求宏为c)

不幸的是,当我编译时,我得到:

WARNING: Use of undeclared Var webstack.client/-?> at line 56 cljs-src/webstack/client.cljs
WARNING: Use of undeclared Var webstack.client/-?> at line 57 cljs-src/webstack/client.cljs
WARNING: Use of undeclared Var webstack.client/-?> at line 58 cljs-src/webstack/client.cljs
当我在浏览器中打开javascript时,会出现“hey Stephen”警报对话框,但在按下“hey Stephen”警报上的“ok”后,会立即出现无处不在的“Uncaught TypeError:Cannot call method'call'of undefined”错误。果然,看看生成的javascript代码,我的js/alert变成了:

alert([cljs.core.str("hey "), cljs.core.str("Stephen")].join(""));
alert(webstack.client.__QMARK__GT_.call(null, webstack.client.__QMARK__GT_.call(null, webstack.client.a, cljs.core.first), "\ufdd0'a"));
alert(webstack.client.__QMARK__GT_.call(null, webstack.client.__QMARK__GT_.call(null, webstack.client.b, cljs.core.first), "\ufdd0'a"));
alert(webstack.client.__QMARK__GT_.call(null, webstack.client.__QMARK__GT_.call(null, webstack.client.c, cljs.core.first), "\ufdd0'a"))

很明显,我可以使用宏,但是-?>(和相关)宏的编写方式导致它们无法编译。要使用这些
-?>
和“-?>”宏,我需要做什么?

可能正在创建函数,而不是宏中的另一个宏可以帮助您解决此问题:

(defmacro defnilsafe [docstring non-safe-name nil-safe-name]
  `(defn ~nil-safe-name ~docstring
     ([x# form#]
         (let [i# x#] (when-not (nil? i#) (~non-safe-name i# form#))))
     ([x# form# & more#]
         (apply ~nil-safe-name (~nil-safe-name x# form#) more#))))

-?>在使用clojure 1.5.1和cljsbuild 0.3.0时适用,但仅当我使用:use macros而不是:require macros时适用。当我使用:require macros时,clojurescript尝试将宏解析为本地名称空间中的变量,这是不正确的。我想你在clojurescript中发现了一个bug,为什么不报告呢

(ns test.test
  ;(:use-macros [test.nilsafe :only [hey-str -?>]]) ;uncomment and everything works!
  (:require-macros [test.nilsafe :as tn]))

(def a nil)
(def b [])
(def c [{:a 23}])

(.log js/console (tn/hey-str "Stephen")) ;; should display "hey Stephen"
(.log js/console (tn/-?> a first :a)) ;; should display nil
(.log js/console (tn/-?> b first :a)) ;; should display nil
(.log js/console (tn/-?> c first :a))

让我确信这是一个bug的是,取消注释:use宏将导致文件正确编译,即使我没有从变量中删除tn/scope。

marco很简单

(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."
  {:added "1.0"}
  [x & forms]
  (loop [x x, forms forms]
    (if forms
      (let [form (first forms)
            threaded (if (seq? form)
                       (with-meta `(~(first form) ~x ~@(next form)) (meta form))
                       (list form x))]
        (recur threaded (next forms)))
      x)))
写一个零安全的应该很简单(下面的例子没有经过测试),但是你得到了这个概念

(defmacro -?>
  [x & forms]
  (loop [x x, forms forms]
    (if (and forms (some? x)) ; check nil to exit eariler
      (let [form (first forms)
            threaded (if (seq? form)
                       (with-meta `(~(first form) ~x ~@(next form)) (meta form))
                       (list form x))]
        (recur threaded (next forms)))
      x)))

您可以尝试为nil-safe名称创建一个宏(从defnilsafe宏)而不是创建一个函数吗?@Ankur否,它必须是一个宏,因为它需要在计算之前在编译/宏扩展时排列表达式。@rplevy:我说的是,该宏正在创建另一个宏,相反,宏可以创建function@Ankur你将如何编写
-?>
作为函数?@Ankur这是一个反问句。正确答案是,你不能。试试
(?>nil(println“hello world”)
。这与原始宏的作用不同。这怎么可能呢?@Cubic,你是对的,它不会像处理表达式那样处理函数,而是处理函数,例如:
(?>nil println)
,但这不是->宏所做的,因此也不是-?>宏应该做的。
(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."
  {:added "1.0"}
  [x & forms]
  (loop [x x, forms forms]
    (if forms
      (let [form (first forms)
            threaded (if (seq? form)
                       (with-meta `(~(first form) ~x ~@(next form)) (meta form))
                       (list form x))]
        (recur threaded (next forms)))
      x)))
(defmacro -?>
  [x & forms]
  (loop [x x, forms forms]
    (if (and forms (some? x)) ; check nil to exit eariler
      (let [form (first forms)
            threaded (if (seq? form)
                       (with-meta `(~(first form) ~x ~@(next form)) (meta form))
                       (list form x))]
        (recur threaded (next forms)))
      x)))