如何在Clojure中获取函数参数对应的var并实现foobar打印其var形式?
在Clojure中获取函数参数对应的Var并实现打印功能
首先得搞清楚核心问题:函数里的形参(比如你写的x)是局部绑定,它指向的是传入参数的值,而不是原始的Var对象。所以直接在函数里写(println #'x)肯定达不到你想要的效果——要么会报错(如果没有全局的x Var),要么打印的是全局的#'x,和你传入的参数完全没关系。
那怎么才能实现你要的功能呢?分两种场景来说:
场景1:允许调用者显式传递Var对象
如果可以接受调用时直接传入Var(而不是Var的值),那函数写法很简单,直接打印参数就行:
(defn foobar [x] (println x)) ;; 测试示例 (def my-variable 100) (foobar #'my-variable) ; 输出 #'user/my-variable
这里调用时用#'my-variable把Var对象传进去,函数里直接打印这个对象就得到了你要的Var形式。
场景2:希望调用时直接传符号,自动获取对应的Var
如果想让调用者只写(foobar my-variable)就能打印#'my-variable,那函数做不到这一点——因为函数在运行时只能拿到参数的值,拿不到调用时的符号信息。这时候得用宏,因为宏是在编译期处理代码的,能访问到调用时的代码结构:
(defmacro foobar [x] ;; 宏展开后会变成 (println #'x),这里的x是调用时传入的符号 `(println ~(list 'var x))) ;; 测试示例 (def my-variable 100) (foobar my-variable) ; 输出 #'user/my-variable
这个宏的原理是:当你调用(foobar my-variable)时,宏会把代码展开成(println #'my-variable),这样就直接打印了对应Var。
再解释下为什么原写法无效
你写的(defn foobar [x] (println #'x)),在函数内部x是局部绑定,#'x尝试查找的是名为x的全局Var,而不是你传入的参数对应的Var。如果你的环境里没有全局定义x,运行时会抛出Unable to resolve var: x in this context的错误;如果有全局x,打印的也是全局的#'x,和传入的参数无关——这就是为什么你觉得写法无效。
内容的提问来源于stack exchange,提问作者Attilio
相关产品推荐
相关产品推荐

