2015-09-23 2 views
1

Je fais un programme qui accepte une liste et deux atomes et remplace atom-1 par atom-2 si atom-1 apparaît dans la liste.
Je fais la programmation dans un éditeur de texte à l'aide d'un système UbuntuCommon Lisp: erreur "CDR LST devrait être une expression lambda"

Voici mon code:

#! /usr/bin/clisp 

(defun my-replace (lst x y) 
    (cond 
    ((eq lst nil) nil) 
    ((eq (cdr lst) nil) nil) 
    ((eq (car lst) x) (setq (car lst) y)) 
    (t (my-replace ((cdr lst) x y))))) 

Lorsque je tente d'exécuter ce, Clisp montre cette erreur:

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

Je suis débutant en Lisp.
Dites-moi comment résoudre cette erreur.

+2

Ceci pourrait probablement être fermé en tant que doublon de [Erreur lisp commune: "devrait être l'expression lambda"] (http://stackoverflow.com/q/2575819/1281433), ou [lisp - devrait être une expression lambda] (http://stackoverflow.com/q/22163216/1281433), ou [Pourquoi mon code Lisp me donne-t-il ... devrait être une expression lambda?] (http://stackoverflow.com/q/26941771/1281433), ou [erreur lisp: devrait être l'expression lambda] (http://stackoverflow.com/q/23746775/1281433), ou [liste devrait être une expression lambda] (http://stackoverflow.com/q/12561779/1281433), etc., qui ont tous le même problème sous-jacent: '((...) ...)'. –

+0

@JoshuaTaylor: le message d'erreur CLISP n'est pas très bon ... –

Répondre

8

Tout d'abord vous devez améliorer la mise en forme et le retrait:

(defun my-replace (lst x y) 
    (cond 
    ((eq lst nil) nil) 
    ((eq (cdr lst) nil) nil) 
    ((eq (car lst) x) (setq (car lst) y)) 
    (t (my-replace ((cdr lst) x y))))) 

Regardons le code:

(defun my-replace (lst x y) 
; in Common Lisp you can write LIST instead of LST 
; what are x and y? The naming is not very speaking. 

    (cond 
    ((eq lst nil) nil) 

    ((eq (cdr lst) nil) nil) ; why this clause? 

    ((eq (car lst) x) (setq (car lst) y)) 
    ; instead of SETQ use SETF 

    (t (my-replace ((cdr lst) x y))))) 
        ; here is a function call? why the extra parentheses 

Je me concentrerais d'abord sur une version qui est non destructive. Vous essayez d'écrire une version qui modifie de manière destructive la liste. Ne pas. Créez une nouvelle liste avec les remplacements effectués.

Si vous voulez écrire une version destructive, vous pouvez le faire, mais vous devez d'abord avoir les bases.

+0

merci !! pouvez-vous me dire le bon matériel pour apprendre le lisp – ojas

2

Modifier: Cette réponse indique une autre erreur évidente dans l'extrait. L'erreur dans le titre est due aux parens supplémentaires autour de (cdr lst) x y, le rendant ((cdr lst) x y), ce qui n'a de sens que si (cdr lst) est une expression lambda, et peut être appelée.


Normalement, si l'on veut lier quelque chose à une valeur, on utilise set. setq est une version spéciale de set, lorsque le premier argument est une valeur qutoed, donc au lieu d'écrire (set 'horse 123), vous devez écrire (setq horse 123).

Cependant, vous ne voulez pas lier un symbole à une valeur, vous voulez faire d'un élément d'une liste une valeur. C'est quand vous voulez utiliser setf.

(let ((lst (list 1 2 3))) 
    (setf (car lst) 4) 
    (princ lst)) ;; (4 2 3) 

Voir this excellente réponse pour plus d'informations.

+2

Vous modifiez une liste littérale. Ce qui dans de nombreux langages de programmation, y compris Common Lisp, n'est généralement pas une bonne idée. Utilisez 'LIST' pour créer une nouvelle liste, qui peut être modifiée sans problème. –

+0

Tout cela est très bon conseil, et je sais OP accepté, mais cela ne permet pas d'expliquer ou d'adresser le ** SYSTEM ::% EXPAND-FORM: (CDR LST) devrait être une erreur lambda expression ** du tout. –

+0

@JoshuaTaylor bien sûr. Quelque part, j'ai mal interprété '(cdr lst)' comme '(voiture lst)'. J'ai inclus une note en haut de ma réponse. – MartinHaTh