2010-08-19 62 views
3

我正在開發一個遺傳編程愛好項目。let *和set之間的區別?在Common Lisp

我有一個函數/宏設置,當以setq/setf形式進行求值時,將生成一個如下所示的列表。

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

然後,它會得到通過戰略性地使用功能/宏綁定了一個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中完全實現,但這對我來說沒有意義。

這個問題的原因是什麼?

---編輯:猛拉我的代碼,並把整個文件中的一個引擎收錄---

假設我決定一setq是不會做對我來說,我寫一個簡單的功能做到這一點:

(defun定義生成樣本() (讓((特威格斯(使樹2))) (讓((樹綁定(綁定樹特威格斯))) (讓((評估 - 樹(eval-fitness樹綁定)))
(list twiggs tree-bindings evaluate-trees)))))

這產生了......幫助文件錯誤消息(??!?)......和「eval:變量twiggs沒有值」的爆炸式增長,這源於SLIME檢查上的綁定樹定義。

我相當確定我已經徹底清理了我的宏。 http://pastebin.org/673619

+0

我不明白到底是什麼宏在做什麼。什麼是你的「功能/宏」的戰略使用,以及所有的頂級'setq's是什麼? – Ken 2010-08-19 05:16:40

+0

那麼,一個setq就是全球「人口池」。其他人只是發展的文物。我的宏從相當隨意的表達式樹中動態地生成一個函數(它會變得很「複雜」)。 – 2010-08-19 05:23:24

+0

您的第二個片段不完整。 「let」形式的內容會發生什麼?縮進也是誤導,括號不平衡。 – Svante 2010-08-19 14:46:08

回答

2

(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使用多個詞法綁定創建新的詞法作用域。

我認爲你應該提供更多的代碼;目前,你的問題沒有多大意義。


更新:

我將解決您的片段的縮進,使事情更清楚:現在

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

最後一行是虛假的,太。如果這些名字被綁定,那麼 將返回一個元素的列表,這將是評估 函數trees,tree-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))) 
+0

@Svante - 現在在工作中,無法獲得代碼 - 但是當我這樣做時,我會得到「樹木無價值」。 – 2010-08-19 16:53:40

+0

@保羅·納森:那麼,如果我嘲笑你展示的東西,它不會。你嘗試過踩踏它嗎? – Svante 2010-08-20 10:38:48

+0

@Svante:我無法理解,我的文件在pastebin鏈接中。 >。< – 2010-08-21 16:22:53

相關問題