La mutation, bien que permise, est fortement déconseillée dans Scheme. PLT est même allé jusqu'à supprimer set-car!
et set-cdr!
(bien qu'ils les "remplacés" par set-mcar!
et set-mcdr!
). Cependant, une spécification pour append!
est apparue dans SRFI-1. Ce append!
est un peu différent du vôtre. Dans le SRFI, l'implémentation peut, mais n'est pas requis pour modifier les cellules par défaut pour ajouter les listes.
Si vous voulez avoir un append!
qui est garanti de modifier la structure de la liste qui est en cours ajouté à, vous devrez probablement écrire vous-même. Il n'est pas difficile:
(define (my-append! a b)
(if (null? (cdr a))
(set-cdr! a b)
(my-append! (cdr a) b)))
Pour que la définition simple, il n'y a pas de contrôle d'erreur, mais il est clair que vous devrez passer dans une liste de longueur au moins 1 a
, et (de préférence) une liste (de n'importe quelle longueur) comme b
. La raison a
doit être au moins la longueur 1 parce que vous ne pouvez pas set-cdr!
sur une liste vide.
Puisque vous êtes intéressé par comment cela fonctionne, je verrai si je peux expliquer. Fondamentalement, ce que nous voulons faire est de descendre la liste a
jusqu'à ce que nous arrivions à la dernière paire cons
, qui est (<last element> . null)
. Donc, nous voyons d'abord si a
est déjà le dernier élément de la liste en vérifiant null
dans le cdr
. Si c'est le cas, nous utilisons set-cdr!
pour le mettre à la liste que nous ajoutons, et nous avons terminé. Sinon, nous devons appeler my-append!
sur le cdr
de a
. Chaque fois que nous faisons cela, nous nous rapprochons de la fin de a
. Comme il s'agit d'une opération de mutation, nous n'allons rien retourner, donc nous n'avons pas besoin de nous soucier de former notre liste modifiée comme valeur de retour.
Question de suivi - si la mutation est fortement déconseillée, quelles sont les meilleures pratiques pour un modèle comme "construire une liste à partir d'un dialogue d'assistant"? Venant d'un arrière-plan Ruby, c'est quelque chose que j'ai lutté avec la compréhension ... la mentalité plus que juste le code réel pour résoudre le problème. –
Dans la programmation fonctionnelle, chaque fois que vous voulez modifier une structure de données, vous pouvez la passer dans une fonction et récupérer la structure de données modifiée comme retour. Cependant, la structure 'originale' est laissée intacte et ce que vous recevez est une nouvelle copie altérée (pour ainsi dire). –
Il n'y a pas de "garantie complète" possible, ce qui est exactement le problème avec les fonctions destructives - si la liste était vide, alors aucune version de "append!" Ne pourra jamais la modifier. –