gpt4 book ai didi

macros - let* 和 set 的区别?在普通 Lisp 中

转载 作者:太空宇宙 更新时间:2023-11-03 18:43:20 26 4
gpt4 key购买 nike

我正在从事基因编程爱好项目。

我有一个函数/宏设置,当以 setq/setf 形式评估时,将生成一个看起来像这样的列表。

(setq trees (make-trees 2)) 
==> (+ x (abs x))

然后它将绑定(bind)到一个 lambda 函数 #<FUNCTION :LAMBDA (X) ... >通过策略性地使用函数/宏

但是,我想用这个比手动分配给变量更有效,所以我写了这样的东西:

(setq sample 
(let* ((trees (make-trees 2))
(tree-bindings (bind-trees trees))
(evaluated-trees (eval-fitness tree-bindings))))
(list (trees tree-bindings evaluated-trees)))

但是,我得到 EVAL: trees has no value当我把它放在 let 形式时。我怀疑与 SETF 相比,宏扩展在 LET 中没有得到完全执行,但这对我来说没有意义。

这个问题的原因是什么?

--- 编辑:提取我的代码并将整个文件放入一个 pastebin ---

假设我决定 setq 不会为我做这件事,我写了一个简单的函数来做这件事:

(defun 生成样本 () (let ((twiggs (make-trees 2))) (让((树绑定(bind)(绑定(bind)树 Twig ))) (let ((evaluated-trees (eval-fitness tree-bindings)))
(列出 twiggs 树绑定(bind)评估树)))))

这会产生大量...帮助文件错误消息(??!?)...和“eval:变量 twiggs 没有值”,这源于 SLIME 检查中的绑定(bind)树定义。

我有理由相信我已经完全清除了我的宏。 http://pastebin.org/673619

最佳答案

(Setq make-trees 2) 将变量 make-trees 的值设置为 2,然后返回 2。

我看不到您描述的宏的原因。您的 make-trees 创建了一棵可以被解释为程序的随机树,这是真的吗?只需使用 defun 将其定义为函数即可。我在想这样的事情:

(defun make-tree (node-number)
(if (= node-number 1)
(make-leaf)
(cons (get-random-operator)
(mapcar #'make-tree
(random-partition (- node-number 1))))))

Letsetq 做完全不同的事情。 Setq 为现有变量赋值,而 let 创建一个具有多个词法绑定(bind)的新词法范围。

我认为你应该展示更多你的代码;目前,您的问题没有多大意义。


更新:

我将修复您的代码段的缩进,使事情更清楚:

(setq sample 
(let* ((trees (make-trees 2))
(tree-bindings (bind-trees trees))
(evaluated-trees (eval-fitness tree-bindings))))
(list (trees tree-bindings evaluated-trees)))

现在,如前所述,let* 建立词法绑定(bind)。这些仅在其主体范围内:

(setq sample 
(let* ((trees (make-trees 2))
(tree-bindings (bind-trees trees))
(evaluated-trees (eval-fitness tree-bindings)))
;; here trees, tree-bindings, and evaluated-trees are bound
) ; end of let* body
;; here trees, tree-bindings, and evaluated trees are not in scope anymore
(list (trees tree-bindings evaluated-trees)))

最后一行也是虚假的。如果这些名字被绑定(bind),它会返回一个元素的列表,这将是评估的结果函数 treestree-bindingsevaluated-trees 作为参数。

你可能会像这样得到你想要的:

(setq sample 
(let* ((trees (make-trees 2))
(tree-bindings (bind-trees trees))
(evaluated-trees (eval-fitness tree-bindings)))
(list trees tree-bindings evaluated-trees)))

另一个更新:

宏的目的是在函数无法消除重复代码时消除重复代码。一种常见的应用是在处理场所时,您还需要它们来定义新的控制结构。只要您没有发现某些东西不能作为函数工作,就不要为它使用宏。

下面是一些可能对您有帮助的代码:

(defun make-tree-lambda (depth)
(list 'lambda '(x)
(new-tree depth)))

(defun make-tree-function (lambda-tree)
(eval lambda-tree))

(defun eval-fitness (lambda-form-list input-output-list)
"Determines how well the lambda forms approach the wanted function
by comparing their output with the wanted output in the supplied test
cases. Returns a list of mean quadratic error sums."
(mapcar (lambda (lambda-form)
(let* ((actual-results (mapcar (make-tree-function lambda-form)
(mapcar #'first input-output-list)))
(differences (mapcar #'-
actual-results
(mapcar #'second input-output-list)))
(squared-differences (mapcar #'square
differences)))
(/ (reduce #'+ squared-differences)
(length squared-differences))))
lambda-form-list))

(defun tree-fitness (tree-list input-output-list)
"Creates a list of lists, each inner list is (tree fitness). Input
is a list of trees, and a list of test cases."
(mapcar (lambda (tree fitness)
(list tree fitness))
tree-list
(eval-fitness (mapcar #'make-tree-lambda tree-list)
input-output-list)))

关于macros - let* 和 set 的区别?在普通 Lisp 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3518874/

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