我一直在试图弄清楚如何执行作为序列中元素存储的表达式。例如,以下是序列中的两个表达式:
user=> (def z '((println 'x) 'y))
#'user/z
user=> z
((println (quote x)) (quote y))
尝试在他们身上使用执行或 doall 似乎没有做任何事情
user=> (do z)
((println (quote x)) (quote y))
user=> (doall z)
((println (quote x)) (quote y))
我想要获得的输出是,如果我不是作为序列而是作为参数列表执行它们
user=> (do (println (quote x)) (quote y))
x
y
我尝试映射 eval ,但这给了我一个额外的nil并返回一个列表
user=> (map eval z)
(x
nil y)
非常感谢任何帮助!
答案 0 :(得分:3)
Do是一个用于评估其args的宏,并返回最后一个。 let
,fn
,for
等包含隐式执行机构。
在你的地图示例中,“extra nil”是println的返回值,它实际上是额外的x(它是打印输出与map返回的序列交错)。
您对z
的定义不会创建可执行对象,而是列表。列表只是在使用时评估自己。
您是否需要评估存储为文字的表达式?
很容易将每一个都包装为thunk(无参数的函数)。
user> (def z [#(println 'x) #(do 'y)])
#'user/z
我们可以使用reduce来执行所有操作,只返回最后一个。
user> (reduce (fn [_ e] (e)) nil z)
x
y
此处打印x,并返回y。
如果您确实需要使用带有eval的列表,则可以将其替换为上面的(e)
变为(eval e)
并且z得到您的原始定义。
答案 1 :(得分:1)
您正在寻找eval代码。
user=> (def z '(do (println "hey!" 'x) 'y))
#'user/z
user=> (eval z)
hey! x
y
请注意,我添加了do,以便评估两个表达式。问题中的代码包含错误。
((println 'x) 'y)
首先发生的事情是打印'x和println返回nil,因此表达式将如下所示。
(nil 'y)
nil不是一个函数,但它正在列表的头部进行评估,所以这是一个错误。或者在这种情况下为空指针异常。
user=> (def z '((println 'x) 'y))
#'user/z
user=> (eval z)
x
NullPointerException user/eval674 (NO_SOURCE_FILE:1)
答案 2 :(得分:1)
(def z '((println 'x) 'y))
您的z
定义有引用说不要评估我。因此z
被定义为未评估的表达式。您想要评估未评估的代码,因此您自然希望使用eval
;但(eval z)
无效,因为(println x)
会打印x
但会返回值nil
。 (nil y)
将无效,而不是您想要的。
你想要的是do
; do
仅返回此处使用的最后一个表达式的值nil
不会妨碍您执行所有表达式。您希望最终结果为:
(do (println 'x)
'y))
让我们将z
变换为这样。
(cons 'do z)
=> (do (println (quote x)) (quote y))
看起来很熟悉? eval
它!
(eval (cons 'do z))
=> x
y