【问题标题】:How to see Clojure local variables in local repl?如何在本地 repl 中查看 Clojure 局部变量?
【发布时间】:2018-04-01 15:35:38
【问题描述】:

我想通过在函数体中放置一个 repl(带有 clojure.main/repl)来玩弄和开发基于局部变量的表达式:

(ns something)

(defn myfunc [ p ]
   (let [local (+ p 10)]
        (clojure.main/repl)
        (+ local 100)))

(myfunc 666)

当我执行这个时,repl 启动正常,但函数的参数和本地 let-bindings 似乎在提示中不可见:

something=> p
CompilerException java.lang.RuntimeException: Unable to resolve symbol: p in this context
something=> local
CompilerException java.lang.RuntimeException: Unable to resolve symbol: local in this context

我已经能够通过创建新的 ^:dynamic 变量并使用绑定在本地设置它们的值来传递值,但这非常复杂并且需要为每个局部变量单独绑定:

(def ^:dynamic x)

(defn myfunc [ p ]
   (let [local (+ p 10)]
        (binding [x local]
                 (clojure.main/repl))
        (+ local 100)))

有没有更简单的方法来传递/访问这种本地 repl 中的本地值?或者有没有更好的方法可以从非本地 repl 访问局部变量,例如“lein repl”?

【问题讨论】:

  • 您可以使用repl fn 的:init 挂钩来定义变量。
  • 谢谢, :init 看起来很有希望。文档说“:init,没有参数的函数,初始化钩子调用了 set!-able vars 的绑定。”但是我无法通过谷歌搜索找到任何示例如何使用 :init 来传递值,你能提供一个吗?

标签: clojure binding var read-eval-print-loop


【解决方案1】:

使用:init 挂钩,您可以在 REPL 命名空间中定义任意变量。

(defn myfunc [p]
  (let [local (+ p 10)]
    (clojure.main/repl :init #(do (def p p) (def local local)))
    (+ local 100)))

这是一个repl 宏,可以更轻松地添加断点:

(defmacro locals []
  (into {}
        (map (juxt name identity))
        (keys &env)))

(defn defs [vars]
  (doseq [[k v] vars]
    (eval (list 'def (symbol k) (list 'quote v)))))

(defmacro repl []
  `(let [ls# (locals)]
     (clojure.main/repl :init #(defs ls#))))

现在你可以直接加入(repl)

(defn myfunc [p]
  (let [local (+ p 10)]
    (repl)
    (+ local 100)))

【讨论】:

  • 这个defs 函数不正确。尝试使用值为列表(1 2 3) 的本地函数:它将尝试将1 作为函数调用。您至少应该引用该值:(eval (list 'def (symbol k) (list 'quote v)))
【解决方案2】:

我不知道使用 repl 的好答案,但我喜欢使用好的老式打印输出。 spyxlet-spylet-spy-pretty 宏促进了这一点:

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test))

(defn myfunc [ p ]
  (spyx p)
  (let-spy [local (+ p 10)]
    (+ local 100)))

(dotest
  (spyx (myfunc 666)))

结果:

p              => 666
local          => 676
(myfunc 666)   => 776

spyx和朋友is here in the README的文档,还有full API documentation on GitHub pages

【讨论】:

  • 感谢间谍信息!这绝对可以成为我调试工具箱中的一个好工具。我仍在寻找现场使用 repl 的方法,因为我的主要用途是促进以现有值为基础的新表达式的开发(而不仅仅是查看现有值)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-03
  • 2023-04-07
  • 2020-03-16
  • 1970-01-01
  • 1970-01-01
  • 2020-09-02
相关资源
最近更新 更多