let *和set之间的区别?在普通Lisp中 [英] Difference between let* and set? in Common Lisp

查看:145
本文介绍了let *和set之间的区别?在普通Lisp中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working on a genetic programming hobby project.

我有一个功能/宏设置,当以setq/setf形式进行评估时,将生成一个看起来像这样的列表.

I have a function/macro setup that, when evaluated in a setq/setf form, will generate a list that will look something like this.

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

然后将通过策略性使用功能/宏将其绑定到lambda函数#<FUNCTION :LAMBDA (X) ... >

Then it will get bound out to a lambda function #<FUNCTION :LAMBDA (X) ... > via strategic use of functions/macros

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

However, I want to get a bit more effective with this than manually assigning to variables, so I wrote something like this:

(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 has no value.我的怀疑是,与SETF相比,LET中的宏扩展不能完全执行,但这对我来说没有意义.

However, I get EVAL: trees has no value when I place this in a let form. My suspicion is that the macro expansions don't get fully performed in a LET as compared to a SETF, but that doesn't make sense to me.

此问题的原因是什么?

---删除我的代码,然后将整个文件放入pastebin ---

--- edit: yanked my code and put the whole file in a pastebin ---

假设我决定setq不会帮我做,我编写了一个简单的函数来完成它:

Supposing that I decide that a setq isn't going to do it for me and I write a simple function to do it:

(defun generate-sample() (让((twiggs(make-trees 2)))) (让((tree-bindings(bind-trees twiggs)))) (让(((评估树(eval-fitness树绑定))))
(列出twiggs树绑定评估树))))))

(defun generate-sample () (let ((twiggs (make-trees 2))) (let ((tree-bindings (bind-trees twiggs))) (let ((evaluated-trees (eval-fitness tree-bindings)))
(list twiggs tree-bindings evaluated-trees)))))

这产生了...帮助文件错误消息(??!?)...和"eval:变量twiggs没有值"的爆炸式增长,其源于SLIME检查中的绑定树定义.

This yields an explosion of ...help file error messages (??!?)... and "eval: variable twiggs has no value", which stems from the bind-trees definition on SLIME inspection.

我可以肯定地说,我已经完全清理了宏. http://pastebin.org/673619

I am reasonably sure that I've completely hosed my macros. http://pastebin.org/673619

推荐答案

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

(Setq make-trees 2) sets the value of the variable make-trees to 2, then returns 2.

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

I do not see a reason for a macro in what you describe. Is it true that your make-trees creates a single random tree, which can be interpreted as a program? Just define this as a function with defun. I am thinking of something like this:

(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创建具有许多词法绑定的新词法作用域.

Let and setq do totally different things. Setq assigns a value to an existing variable, while let creates a new lexical scope with a number of lexical bindings.

我认为您应该展示更多代码;目前,您的问题没有任何意义.

I think that you should present more of your code; currently, your question does not make a lot of sense.

更新:

我将修复您代码段的缩进,以使内容更清晰:

I will fix your snippet's indentation to make things clearer:

(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*建立词汇绑定.这些 仅在其主体范围内:

Now, as written before, let* establishes lexical bindings. These are only in scope within its body:

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

最后一行也是虚假的.如果这些名称被绑定,它将 返回一个元素的列表,这将是求值结果 具有tree-bindingsevaluated-trees的函数trees 争论.

That last line is spurious, too. If those names were bound, it would return a list of one element, which would be the result of evaluating the function trees with tree-bindings and evaluated-trees as arguments.

您可能会像这样得到想要的东西:

You might get what you want like this:

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


另一个更新:

宏的目的是在功能无法消除重复代码的情况下消除重复代码.一种常见的应用是在处理场所时,您还需要它们来定义新的控件构造.只要您看不到某些功能不能正常工作,就不要对其使用宏.

The purpose of macros is to eliminate repeated code when that elimination is not possible with functions. One frequent application is when dealing with places, and you also need them to define new control constructs. As long as you do not see that something cannot work as a function, do not use a macro for it.

以下一些代码可能会对您有所帮助:

Here is some code that might help you:

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

这篇关于let *和set之间的区别?在普通Lisp中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆