简体   繁体   English

如何在本地repl中查看Clojure局部变量?

[英]How to see Clojure local variables in local repl?

I want to play around and develop expressions based on local variables by placing a repl (with clojure.main/repl) inside a function body: 我想通过在函数体中放置一个repl(使用clojure.main / repl)来开发并基于局部变量开发表达式:

(ns something)

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

(myfunc 666)

When I executed this, the repl starts ok, but the parameters of the function and local let-bindings do not seem to be visible in the prompt: 当我执行此操作时,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

I have been able to pass the values by creating new ^:dynamic vars and setting their values locally with binding, but this is quite complex and requires separate binding for each local variable: 我已经能够通过创建新的^:动态变量并通过绑定在本地设置它们的值来传递值,但这非常复杂并且需要为每个局部变量单独绑定:

(def ^:dynamic x)

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

Is there simpler way to pass/access local values in such local repl? 是否有更简单的方法来传递/访问此类本地repl中的本地值? Or is there some better way to do access the local variables from non-local repl, such as the "lein repl"? 或者是否有更好的方法从非本地repl访问本地变量,例如“lein repl”?

Using the :init hook, you can define arbitrary vars in the REPL namespace. 使用:init钩子,可以在REPL命名空间中定义任意变量。

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

Here's a repl macro to make adding a breakpoint easier: 这是一个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#))))

Now you can just drop in (repl) : 现在你可以直接进入(repl)

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

I don't know a good answer for using the repl, but I favor using good old-fashioned printouts. 我不知道使用repl的好答案,但我赞成使用好的老式打印输出。 This is facilitated by the spyx , let-spy , and let-spy-pretty macros: 这是通过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)))

with result: 结果:

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

Documentation on spyx & friends is here in the README , and there is also full API documentation on GitHub pages . 有关spyx和朋友的文档在README中 ,并且还有关于GitHub页面的完整API文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM