2010-08-19 9 views
3

Je travaille sur un projet de passe-temps de programmation génétique.Différence entre let * et set? en commun Lisp

J'ai une fonction/configuration de macro qui, lorsqu'elle est évaluée dans une forme setq/setf, va générer une liste qui ressemblera à ceci.

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

Ensuite, il se limite à une fonction lambda #<FUNCTION :LAMBDA (X) ... > via l'utilisation stratégique des fonctions/macros

Cependant, je veux être un peu plus efficace avec ce que l'affectation manuellement aux variables, donc j'écrit quelque chose comme ceci:

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

Cependant, je reçois EVAL: trees has no value lorsque je place ce sous une forme let. Mon soupçon est que les expansions de macro ne sont pas entièrement réalisées dans un LET par rapport à un SETF, mais cela n'a pas de sens pour moi.

Quelle est la cause de ce problème?

--- modifier: tirai mon code et placez le fichier entier dans un pastebin ---

Supposant que je décide qu'un setq ne va pas le faire pour moi et j'écrire une fonction simple faire:

(defun générer échantillon() (lET ((Twiggs (faire arbres 2))) (lET ((fixations d'arbres (bind-arbres twiggs))) (let ((évalué -trees (eval-fitness tree-bindings)))
(liste des liens-arbres de twiggs-arbres évalués)))))

Cela provoque une explosion des messages d'erreur du fichier d'aide (??!?) ... et "eval: variable twiggs n'a pas de valeur", qui provient de la définition de bind-trees sur l'inspection SLIME. Je suis raisonnablement sûr que j'ai complètement arrosé mes macros. http://pastebin.org/673619

+0

Je ne comprends pas exactement ce que votre macro est en train de faire. Et que fait votre "utilisation stratégique des fonctions/macros", et avec tous les 'setq's de toplevel? – Ken

+0

Eh bien, un setq est en quelque sorte le «bassin de population» mondial; les autres ne sont que des artefacts de développement. Mes macros génèrent dynamiquement une fonction à partir d'arborescences d'expressions assez arbitraires (il devient difficile de penser à "sorta"). –

+0

Votre second extrait est incomplet. Que se passe-t-il dans le corps de votre forme 'let'? L'indentation est également trompeuse, et les parenthèses ne sont pas équilibrées. – Svante

Répondre

2

(Setq make-trees 2) définit la valeur de la variable make-trees 2, puis retourne 2.

Je ne vois pas une raison pour une macro dans ce que vous décrivez. Est-il vrai que votre make-trees crée un seul arbre aléatoire, qui peut être interprété comme un programme? Définissez simplement ceci comme une fonction avec defun. Je pense à quelque chose comme ceci:

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

Let et setq faire des choses totalement différentes. Setq attribue une valeur à une variable existante, tandis que let crée une nouvelle portée lexicale avec un nombre de liaisons lexicales.

Je pense que vous devriez présenter plus de votre code; actuellement, votre question n'a pas beaucoup de sens.


Mise à jour:

Je fixerai votre empreinte de bout pour rendre les choses plus claires:

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

Maintenant, comme il est écrit avant, let* établit des liaisons lexicales. Ces ne sont portée dans son corps:

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

Cette dernière ligne est faux aussi. Si ces noms étaient liés, retournerait une liste d'un élément, qui serait le résultat de l'évaluation de la fonction trees avec et evaluated-trees comme arguments .

Vous pouvez obtenir ce que vous voulez comme ceci:

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

Une autre mise à jour:

Le but de macros est d'éliminer le code répété lorsque que l'élimination n'est pas possible avec des fonctions. Une application fréquente est lorsqu'il s'agit de lieux, et vous avez également besoin d'eux pour définir de nouvelles constructions de contrôle. Tant que vous ne voyez pas que quelque chose ne peut pas fonctionner en tant que fonction, n'utilisez pas de macro pour cela.

Voici un code qui pourrait vous aider:

(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 - au travail maintenant, je ne peux pas obtenir le code - mais quand je le mets comme ça, je reçois des "arbres pas une valeur". –

+0

@ Paul Nathan: Eh bien, si je me mets à ce que vous avez montré, ce n'est pas le cas. Avez-vous essayé de le faire? – Svante

+0

@Svante: Je suis flumoxxed au-delà de ma compréhension. Mon fichier est dans un lien pastebin. >. < –

Questions connexes