Macros let*和set之间的区别?通用口齿不清
我正在做一个基因编程爱好项目 我有一个函数/宏设置,当以setq/setf形式进行计算时,它将生成一个类似这样的列表Macros let*和set之间的区别?通用口齿不清,macros,lisp,common-lisp,Macros,Lisp,Common Lisp,我正在做一个基因编程爱好项目 我有一个函数/宏设置,当以setq/setf形式进行计算时,它将生成一个类似这样的列表 (setq trees (make-trees 2)) ==> (+ x (abs x)) 然后,通过策略性地使用函数/宏,它将绑定到lambda函数# 但是,我希望通过这种方式比手动分配变量更有效,所以我写了如下内容: (setq sample (let* ((trees (make-trees 2)) (tree-bindings (
(setq trees (make-trees 2))
==> (+ x (abs x))
然后,通过策略性地使用函数/宏,它将绑定到lambda函数#
但是,我希望通过这种方式比手动分配变量更有效,所以我写了如下内容:
(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 (node-number)
(if (= node-number 1)
(make-leaf)
(cons (get-random-operator)
(mapcar #'make-tree
(random-partition (- node-number 1))))))
(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表单中时,我得到了EVAL:trees没有值。我的怀疑是,与SETF相比,LET并不能完全执行宏扩展,但这对我来说毫无意义
这个问题的原因是什么
---编辑:猛拉我的代码,把整个文件放在一个粘贴箱里---
假设我决定setq不为我做这件事,我写了一个简单的函数来做:
(取消生成样本()
让(小枝做树2)
(let((树绑定(绑定树和树枝)))
(let((评估树(评估适应度树绑定))
(列出twiggs树绑定评估的树(()()))
这会产生大量的…帮助文件错误消息(???)。。。“eval:variable twiggs没有值”,这源于黏液检查中的绑定树定义
我有理由相信我已经完全冲洗了我的宏 (Setq make trees 2)
将变量make trees
的值设置为2,然后返回2
我看不出在您描述的内容中使用宏的原因。您的make trees
创建了一个可以解释为程序的随机树,这是真的吗?只需使用defun
将其定义为一个函数即可。我在想这样的事情:
(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 (node-number)
(if (= node-number 1)
(make-leaf)
(cons (get-random-operator)
(mapcar #'make-tree
(random-partition (- node-number 1))))))
(setq sample
(let* ((trees (make-trees 2))
(tree-bindings (bind-trees trees))
(evaluated-trees (eval-fitness tree-bindings)))
(list trees tree-bindings evaluated-trees)))
让
和setq
做完全不同的事情Setq
为现有变量赋值,而let
使用大量词汇绑定创建新的词汇作用域
我认为你应该展示更多的代码;目前,你的问题没有多大意义
更新:
我将修复代码片段的缩进以使事情更清楚:
(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*
建立词汇绑定。这些
仅在其主体范围内:
(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)))
最后一行也是假的。如果这些名字被绑定,它将
返回一个元素的列表,这将是计算的结果
带有树绑定的树
函数和评估树
函数如下
争论
您可能会像这样得到您想要的:
(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 (node-number)
(if (= node-number 1)
(make-leaf)
(cons (get-random-operator)
(mapcar #'make-tree
(random-partition (- node-number 1))))))
(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)))
我不太明白你的宏在做什么。你的“函数/宏的战略性使用”是做什么的?所有顶级的setq都有什么用?一个setq是全球的“人口池”;其他的只是开发的产物。我的宏从相当任意的表达式树动态生成一个函数(考虑起来有点复杂)。您的第二个代码片段不完整。在let
表单的主体中发生了什么?缩进也有误导性,括号也不平衡。@Svante-现在在工作,无法得到代码-但当我这样做时,我得到的是“树不是值”。@Paul Nathan:好吧,如果我模拟你展示的东西,它不会。你试过踩它吗?@Svante:我感到莫名其妙。我的文件在粘贴箱链接中@保罗·内森:我在你的邮箱里添加了一些评论。中心问题似乎是您不了解宏的用途。尤其是您的绑定树
,而且评估适合度
对我来说非常难懂。@Svante:谢谢您对我的lisp的评论。我还在学习。我试图做的是使用操作符列表和任意值X随机构造一个列表(“树”),然后取那个“树”并从中构造一个匿名函数。给定随机生成的函数,我想用一些示例值(eval fitness
)运行它,看看它是否适合目标函数。我的下一个目标是交换树的分支,以尝试改进目标函数。我使用宏将树“粘贴”到模板(lambda(X)树)。