Clojure + Clojurescript:宏读取当前文件的代码

时间:2016-10-25 00:49:15

标签: clojure clojurescript

我已经尝试过的事情

(ns my-test
  (:require blah))

(def foo 20)

(println (blah/magic))

这在clojure中效果很好,但在clojurescript中却没有(至少没有lein figwheel)。

原始问题

我需要以下内容才能在Clojure和Clojurescript中工作。我认为宏是正确的解决方案,但我对其他技术持开放态度。

我想要一种将当前文件作为字符串读取的方法。例如,

(ns my-test
  (:require blah))

(def foo 20)

(println (blah/magic))

然后应该导致(打印出来)

(println (slurp *file*))

如果我只需要在Clojure中使用它,我可以使用当前文件做有趣的事情并在运行时读取它。但是,我还需要在Clojurescript中工作(我不想设置一些REST API来提供* .cljs文件) - 因此,有没有办法在编译时通过一些宏来做到这一点? / p>

澄清

假设你想写一个"作弊的quine" - 你会怎么做?可能类似于DataArray。现在,问题是什么?当在lein figwheel下运行时,这在clojurescript中不起作用。

2 个答案:

答案 0 :(得分:3)

你需要像这样的Reader Conditionals:

(defn build-list []
  (list #?@(:clj  [5 6 7 8]
            :cljs [1 2 3 4])))

请参阅此处的文档:

http://clojure.org/guides/reader_conditionals

https://github.com/clojure/clojurescript/wiki/Using-cljc

更新1

如果要修改当前正在执行的源代码,可以始终构造字符串并使用eval

(eval (read-string "(defn darth [] (println \"I have the ultimate power now...\" ))" ))

(darth)
;=> I have the ultimate power now...

然而,由于编译了ClojureScript,我不认为有任何简单的方法可以找到源原始源代码,如果这是你之后的事情。

更新2

这是一个有趣的问题。我最接近的是这样的:

(ns clj.core)

(defmacro fred [& forms]
  (doseq [f forms]
    (println `~f)))

(fred 
  (+ 1 2)
  (* 2 3)
)

(defn -main [& args])

结果:

> lein run    
(+ 1 2)
(* 2 3)

答案 1 :(得分:0)

在这里参加聚会很晚,但是我遇到了类似的问题,经过一天的搜索,我发现*file*的ClojureScript对应词是cljs.analyzer/*cljs-file*

您还需要注意为宏创建仅宏的命名空间(除defmacro外,什么都没有),并创建一个.clj文件。此外,根据我的经验,(:require-macros [your-macro-ns])必须使用该名称空间,而不是普通的(:require ...)

所以您的问题的答案将是

my-macro.clj

(ns my-macro)

(defmacro compile-time-slurp-self []
  (slurp cljs.analyzer/*cljs-file*))

main.cljs

(ns main
  (:require-macros [my-macro]

(def foo 20)

(println (my-macro/compile-time-slurp-self))

应该注意的是,由于slurp需要Clojure,因此它仅适用于基于Clojure的ClojureScript编译器,而不适用于本身在ClojureScript上运行的新的自举式编译器。据我了解,后者主要用于基于浏览器的REPL和Java不可用的开发环境,只要您不在浏览器中构建代码,就可以了。