gpt4 book ai didi

clojure - 如何将列表形式转换为clojure中的函数

转载 作者:行者123 更新时间:2023-12-05 01:08:07 28 4
gpt4 key购买 nike

我有一个这样定义的函数规范,我想将它评估为一个函数对象,以便我可以传递。

(def spec '(foo [n] (* 2 n)))

我可以创建这样的宏
(defmacro evspec [name arg & body] `(defn ~name [~arg] ~@body))

那么下面的调用会给我函数 foo。当用 3 调用时,(foo 3),将返回 6。
(evspec foo n (* 2 n))

但是,如果我从上面定义的规范中获取函数体,则返回的函数 foo 不会评估主体形式 (* 2 n),而是返回主体形式。
(let [foo (first spec) arg (first (second spec)) body (last spec)]
(evspec foo arg body))

user=> (foo 3)
(* 2 n)

我注意到现在创建的 foo 函数是 $eval$foo
user=> foo
#<user$eval766$foo__767 user$eval766$foo__767@39263b07>

而工作的 foo 功能是
user=> foo
#<user$foo user$foo@66cf7fda>

任何人都可以解释为什么有区别,我怎样才能让它发挥作用?我想有办法不回复 eval 吗?来自javascript背景,不知何故我总是认为 eval 是邪恶的。

最佳答案

如果没有 eval,一般情况下根本不可能做到这一点。 .宏只是一个函数,它在编译时按字面意思传递其参数表达式(通常根本不可能知道它们在运行时的值可能是什么)。特别是在对 evspec 的调用中里面let问题文本中的形式,其中返回值为(* 2 n) , evspec宏扩展器从字面上看到符号 foo和符号 n作为它的位置参数和(body) (包含单个符号 body 的序列)作为其“rest”参数;返回值与这些输入一致。

但是,使用 eval出于这种目的是完全可以的。重要的是要记住它有相当大的运行时成本,所以你会想稍微谨慎地使用它,但是一旦你使用 eval 生成一个函数,它是一个非常好的 Clojure 函数,和其他任何函数一样快。

另外,请注意,在 JavaScript 中 eval对文本进行操作,Clojure 的 eval对 Clojure 数据结构进行操作——实际上与宏操作的数据结构相同——这可以说使其更不容易出错。

关于clojure - 如何将列表形式转换为clojure中的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17560627/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com