如何执行"做"在clojure序列中的元素

时间:2014-03-09 03:43:58

标签: clojure

我一直在试图弄清楚如何执行作为序列中元素存储的表达式。例如,以下是序列中的两个表达式:

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)

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:3)

Do是一个用于评估其args的宏,并返回最后一个。 letfnfor等包含隐式执行机构。

在你的地图示例中,“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