2010-04-04 9 views
8

Je viens de commencer à apprendre Common Lisp il y a quelques jours, et j'essaye de construire une fonction qui insère un nombre dans un arbre. Je reçois une erreur,Erreur de lisp commune: "devrait être l'expression de lambda"

*** - SYSTEM::%EXPAND-FORM: (CONS NIL LST) should be a lambda expression

De googler autour, il semble que cela se produit lorsque vous avez trop de jeux de parenthèses, mais après avoir regardé cela pour une heure et changer les choses, je peux » Je ne sais pas où je pourrais faire ça.

C'est le code où ça se passe:

(defun insert (lst probe) 
    (cond ((null lst) (cons probe lst)) 
     ((equal (length lst) 1) 
      (if (<= probe (first lst)) 
       (cons probe lst) 
       (append lst (list probe)))) 
     ((equal (length lst) 2) 
      ((cons nil lst) (append lst nil) (insertat nil lst 3) 
       (cond ((<= probe (second lst)) (insert (first lst) probe)) 
        ((> probe (fourth lst)) (insert (fifth lst) probe)) 
        (t (insert (third lst) probe))))))) 

Je suis sûr que ça se produit après la ((égale (LST longueur) 2), où l'idée est d'insérer une liste vide dans l'existant liste, puis ajouter une liste vide sur l'extrémité, puis insérez une liste vide dans le milieu

Répondre

6

Correct! Le problème est dans la ligne juste après cela, où il est dit

((cons nil lst) (append lst nil) (insertat nil lst 3) ... 

Le problème est les deux parenthèses ouvrantes. Les parenthèses peuvent changer de sens dans des contextes spéciaux (comme le formulaire cond que vous utilisez), mais dans ce contexte, les parenthèses signifient une application de fonction régulière, comme vous en avez probablement l'habitude. Cela signifie que la première chose après les parenthèses doit être une fonction. Du point de vue des parenthèses externes, la première chose est (cons nil lst), donc cela doit être une fonction (ce qui n'est pas le cas).

Notez que vous ne pouvez pas simplement supprimer les parenthèses, car la fonction cons renvoie une nouvelle liste comme vous le souhaitez mais ne modifie pas l'ancienne liste. Vous voulez probablement quelque chose comme ceci:

(setq lst (cons nil lst)) 
(setq lst (append lst nil)) 
(setq lst (insertat nil lst 3)) 
... 
+0

Je crois que vous avez raison - j'ai oublié que par contre ne modifie pas réellement la liste. –

1

Vous avez raison, à la ligne marquée « erreur est ici », il y a une erreur de syntaxe:.

(defun insert (lst probe) 
    (cond ((null lst) (cons probe lst)) 
     ((equal (length lst) 1) 
     (if (<= probe (first lst)) 
      (cons probe lst) 
      (append lst (list probe)))) 
     ((equal (length lst) 2) 
     (#|Error is here|# (cons nil lst) (append lst nil) (insertat nil lst 3) 
      (cond ((<= probe (second lst)) (insert (first lst) probe)) 
       ((> probe (fourth lst)) (insert (fifth lst) probe)) 
       (t (insert (third lst) probe))))))) 

Pour le compilateur/interpréteur, le formulaire lit comme un appel de fonction à la "fonction" (cons nil list) qui n'est pas une fonction du tout. Le compilateur se plaint ici de l'utilisation d'une forme de composé dans la position « opérateur », ce qui est un lambda (le seul type de formulaire composé accepté dans cette position.)

((cons nil lst)       #| <-- Form in operator position |# 
(append lst nil)      #| <-- First argument form |# 
(insertat nil lst 3)     #| <-- Second argument form |# 
(cond ((<= probe (second lst)) (insert (first lst) probe)) #| Third argument |# 
     ((> probe (fourth lst)) (insert (fifth lst) probe)) 
     (t (insert (third lst) probe)))) 

J'aidais avec re formuler l'expression, mais je ne suis pas sûr de ce que vous voulez accomplir ici.

7

Si vous indentez correctement la fonction, vous pouvez voir qu'il ya une parenthèse supplémentaire devant CONS NIL LST.

(defun insert (lst probe) 
    (cond ((null lst) (cons probe lst)) 
     ((equal (length lst) 1) 
     (if (<= probe (first lst)) 
      (cons probe lst) 
      (append lst (list probe)))) 
     ((equal (length lst) 2) 
     ((cons nil lst) (append lst nil) (insertat nil lst 3) 
      (cond ((<= probe (second lst)) (insert (first lst) probe)) 
       ((> probe (fourth lst)) (insert (fifth lst) probe)) 
       (t (insert (third lst) probe))))))) 

Dans la plupart des EDI Lisp, vous pouvez mettre en retrait des expressions. Dans LispWorks, sélectionnez l'expression entière et exécutez m-x Indent Region.

0

Pour corriger l'erreur immédiate, vous pouvez simplement ajouter un PROGN avant (CONS NIL ...). PROGN fonctionne en évaluant chaque formulaire et en renvoyant la valeur de la dernière forme dans sa valeur. Cependant, votre programme ne fera toujours pas ce que vous pensez qu'il fera (je suppose). Vous savez, dans Common Lisp, vous utilisez le premier objet contre pour représenter toute la liste non-vide, et vous ne pouvez pas simplement remplacer la contre-tête.Le meilleur moyen est de retourner la nouvelle liste comme valeur de la fonction.

(defun insert (lst probe) 
    (ecase (length lst) 
    (0 (list probe)) 
    (1 (let ((c (first lst))) 
     (if (<= probe c) 
      (list probe c) 
      (list c probe)))) 
    (2 (cond 
     ((<= probe (first lst)) 
      (list probe (first lst) nil (second lst) nil)) 
     ((> probe (second lst)) 
      (list nil (first lst) nil (second lst) probe)) 
     (t 
      (list nil (first lst) probe (second lst) nil)))))) 

Peut-être que vous voulez (setf lst (insert lst [some-number])) lorsque vous utilisez cette fonction.