Fixation du retrait, votre code devient
(define (children? node)
(define list '(1))
En utilisant l'astuce sentinelle de la tête. Bon bien...). Mais puisque son but est d'être modifié par voie chirurgicale, il doit être fraîchement préparé, non cité donnée:
(define list (list 1))
attente, quoi? Deux list
s? Ce n'est pas du Common Lisp, n'est-ce pas? Le schéma est un Lisp-1, pas Lisp-2; Les noms des fonctions et des valeurs résident dans le même espace de noms; alors; ne fais pas ça.
(define lst (list 1))
(map (lambda (x)
(cond
((equal? (car x) node)
(if (equal? list '(1))
(set-car! list x)
(append! list x)))))
Deux conditions dans une rangée est juste un and
, mais plus important encore, l'astuce sentinelle de tête signifie que vous retournerez le vrai résultat que (cdr lst)
, donc il n'y a pas besoin de modifier le contenu de sa tête. Le code simplifie alors, ce qui est tout le but d'utiliser la sentinelle de la tête en premier lieu:
(map (lambda (x)
(if (equal? (car x) node)
(append! lst x))) ; changed the name
aucune clause autre? En général, désapprouvé, mais ici vous faites la carte pour son effet secondaire, donc, tant que vous ne pas utiliser le résultat map
, tout va bien. Plus facile que est juste toujours gérer la clause alternative comme une question d'habitude et un bon style, comme
(map (lambda (x)
(if (equal? (car x) node)
(append! lst x) ; append two lists together... (see below)
#f))
data)
data
? Qu'est-ce que c'est? Il devrait être ajouté comme un autre paramètre formel de children?
.
(if (equal? lst '(1))
equal?
? Pourquoi? Pour voir si nous avons modifié, il suffit de juste
(if (null (cdr lst))
l'action moins principe ...
#f
(cdr lst))) ; cdr carries the true payload
(Donc, fondamentalement,
(define (children? node data)
(let ((res (filter (lambda (x) (equal? (car x) node))
data)))
(if (not (null? res))
res
#f)))
). Bien. Est-ce? Eh bien, cela dépend du fonctionnement suivant correctement.
(define (append! lst . lsts)
(if (not (null? lsts))
(if (null? (cdr lst))
(begin
(set-cdr! lst (car lsts))
(apply append! (car lsts) (cdr lsts)))
Il listes ajoute, donc (append! (list 1) (list 2))
retournera le même résultat que (list 1 2)
et (append! (list 1) (list 2 3))
les mêmes que (list 1 2 3)
. Pour ajouter un élément (comme 2
) à la fin d'une liste, nous devions le placer dans une autre liste en premier. Donc, si notre article ajouté est lui-même une liste, comme '(2 3)
, nous voulons obtenir '(1 (2 3))
de retour. Et pour cela, un élément doit être inclus dans une liste avant d'être ajouté. Donc, votre fonction doit être modifiée pour le faire.
(apply append! (cdr lst) lsts))))
Et ici vous balayez votre (de plus en plus) la liste des résultats pour trouver sa dernière cellule, encore et à nouveau pour chaque élément ajouté. Vous pouvez y remédier en conservant vous-même le dernier pointeur de cellule et en l'utilisant directement. Quel est ce "pointeur"? c'est lst
, que vous cdr
chaque fois que vous append!
quelque chose à lui; de sorte que vous pouvez faire (set-cdr! lst (list item))
directement yoursef. Vous ne pouvez bien sûr pas utiliser la variable lst
pour cela (pourquoi?).
Votre empreinte est tout faux, vous ne devriez pas utiliser la modification de la liste destructive si elle n'est pas nécessaire, et doit fournir un exemple devrait de ce 'data' ressemble réellement. Cela étant dit, vous utilisez probablement 'append' quelque part vous devriez utiliser' list' ou 'cons'. –