【发布时间】:2022-01-02 03:00:06
【问题描述】:
我一直在努力创建一个宏,它允许我将&env 中的任何内容动态绑定到binding 表单中,然后委托给pry 之类的函数来打开一个可以看到的REPL那些绑定&env 符号。
我的简单pry func,按预期工作
(defn pry []
(print (str "pry(" *ns* ")> "))
(flush)
(let [expr (read)]
(when-not (= expr :exit)
(println (eval expr))
(recur))))
使用pry 函数:
clojure-noob.core=> (def a 1)
#'clojure-noob.core/a
clojure-noob.core=> (pry)
pry(clojure-noob.core)> (+ a 1)
2
pry(clojure-noob.core)> :exit
nil
clojure-noob.core=>
我尝试创建binding 的动态调用:
(defmacro binding-pry []
(let [ks (keys &env)]
`(let [ks# '~ks
vs# [~@ks]
bs# (vec (interleave ks# vs#))]
(binding bs# (pry)))))
但是,这会失败,因为内部符号 bs# 没有扩展为实际向量,而是生成的符号,binding 抛出了 clojure.core/binding requires a vector for its binding 异常。
clojure-noob.core=> (let [a 1 b 2] (binding-pry))
Syntax error macroexpanding clojure.core/binding at (/tmp/form-init14332359378145135257.clj:1:16).
clojure.core/binding requires a vector for its binding in clojure-noob.core:
clojure-noob.core=>
带有调试打印的代码引用表单,打印时解析bs#符号,但我不知道在构造binding表单时如何使其解析为向量。
(defmacro binding-pry []
(let [ks (keys &env)]
`(let [ks# '~ks
vs# [~@ks]
bs# (vec (interleave ks# vs#))]
(println bs#)
`(binding bs# (pry)))))
clojure-noob.core=> (let [a 1 b 2] (binding-pry))
[a 1 b 2]
(clojure.core/binding clojure-noob.core/bs__2464__auto__ (clojure-noob.core/pry))
clojure-noob.core=>
我非常有信心我没有正确地解决这个问题,但我没有看到其他方法。
【问题讨论】:
-
这可能是我见过的新用户帖子中最好的第一个问题。
-
您要求“类似 Ruby”的行为,但这是一个 Clojure 问题,并不是每个人都对 Ruby 足够熟悉以知道您期望什么行为。您有一个“简单化”
pry函数的示例,但正如您所说,它按预期工作。但是,我没有看到您对binding-pry的期望的示例。如果您添加预期的行为,它会更容易提供帮助。
标签: clojure