Macros let*和set之间的区别?通用口齿不清

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/setf形式进行计算时,它将生成一个类似这样的列表

(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)树)。