我写了一个简短的调试函数:
(defn printvar
"Print information about given variables in `name : value` pairs"
[& vars]
(dorun (map #(println (name %) ":" (eval %)) vars)))
然后我试着测试它:
(defn -main [arg1 arg2]
(def moustache true) (def answer 42) (def ocelots-are "awesome!")
(printvar 'moustache 'answer 'ocelots-are)
(printvar 'arg1 'arg2))
但遇到了一些令人困惑的行为:
$ lein repl
> (-main "one" "two")
# moustache : true
# answer : 42
# ocelots-are : awesome!
# CompilerException java.lang.RuntimeException: Unable to resolve symbol: arg1 in this context, compiling:(/tmp/form-init4449285856851838419.clj:1:1)
$ lein run "one" "two"
# Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: moustache in this context, compiling:(/tmp/form-init4557344131005109247.clj:1:113)
尝试了一下,我发现了这个:
(defn -main [arg1 arg2]
(meta #'arg1))
# Exception in thread "main" java.lang.RuntimeException: Unable to resolve var: arg1 in this context, compiling:(dict_compress/core.clj:9:11)
(defn -main [arg1 arg2]
(def arg1 arg1)
(meta #'arg1))
# {:ns #<Namespace dict-compress.core>, :name arg1, :file dict_compress/core.clj, :column 2, :line 10}
现在我完全糊涂了。
当您执行(f 'var)
和(f var)
时,您到底传递了什么?
为什么从REPL直接运行时有不同的行为?
收到的论证与定义的变量之间的区别是什么?
如何修复我的代码?
我打算以错误的方式调试吗?
答案 0 :(得分:2)
在printvar
内部,moustache
answer
和ocelots-are
正确打印,因为def
将其定义为&#34;全局&# 34。
意味着有一个moustache
var,printvar函数可以&#34;参见&#34;。
以这种方式思考,这有效:
(def moustache 43)
(defn printvar []
(println moustache)
(defn main [arg1]
(printvar))
这不起作用:
(defn printvar []
(println arg1))
(defn main [arg1]
(printvar))
这正是您正在做的事情,将参数 name 传递给eval对参数范围没有任何作用(printvar
无法看到它)
您的代码有几个问题:
defing
,本地绑定是用let
定义的eval
,则需要考虑您正在评估的范围。答案 1 :(得分:0)
只是详细说明@Guillermo的评论,这是一个宏,可以打印任何变量,无论是本地还是全局绑定。
(defmacro printvar
([])
([v & more]
`(let [v# ~v]
(println '~v "=" v#)
(when (seq '~more)
(printvar ~@more)))))
有了这个,您可以尝试以下序列:
user> (def glob-var "foo")
#'user/glob-var
user> (defn -main [loc1 loc2]
(printvar glob-var loc1 loc2))
#'user/-main
user> (-main "bar" 42)
glob-var = foo
loc1 = bar
loc2 = 42
nil
user>