Question

J'apprends schéma r5rs au moment (de PocketScheme) et je trouve que je pouvais utiliser une fonction qui est intégrée dans des variantes du schéma, mais pas tous: Append

En d'autres termes -. Changer une liste destructivement

Je ne suis pas tellement intéressé par le code réel comme une réponse autant que la compréhension du processus par lequel on pourrait passer une liste en fonction (ou un vecteur ou une chaîne) et muter ensuite.

exemple:

(define (append! lst var)
    (cons (lst var))
)

Quand j'utilise l'approche comme ci-dessus, je dois faire quelque chose comme (define list (append! foo (bar)) que je voudrais quelque chose de plus générique.

Était-ce utile?

La solution

Mutation, mais a permis, est fortement déconseillée dans le schéma. 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 apparu dans SRFI-1 . Ce append! est un peu différent que le vôtre. Dans le SRFI, la mise en œuvre peut , mais n'est pas requis pour modifier les cellules cons pour ajouter les listes.

Si vous voulez avoir un append! qui est garantie pour changer la structure de la liste qui est en cours ajouté à, vous devrez probablement écrire vous-même. Il 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 toute longueur) comme b. La a raison doit être d'au moins 1 longueur est parce que vous ne pouvez pas set-cdr! sur une liste vide.

Puisque vous êtes intéressé par la façon dont cela fonctionne, je vais voir si je peux expliquer. En gros, ce que nous voulons faire est d'aller dans la liste a jusqu'à ce que nous arrivons à la dernière paire de cons, qui est (<last element> . null). Nous avons donc d'abord si a est déjà le dernier élément de la liste en vérifiant null dans le cdr. Dans ce cas, nous utilisons set-cdr! pour le mettre à la liste nous annexant, et nous avons terminé. Dans le cas contraire, nous devons appeler my-append! sur le cdr de a. Chaque fois que nous faisons cela nous approchons de la fin de a. Comme il est une opération de mutation, on ne va pas retourner quoi que ce soit, donc nous ne devons pas à vous soucier de la formation de notre liste modifiée comme la valeur de retour.

Autres conseils

Mieux vaut tard que jamais pour mettre en quelques 2-3 cents sur ce sujet ...

(1) Il n'y a rien de mal à utiliser les procédures destructrices dans le schéma en il y a une seule référence à la stucture en cours de modification. Ainsi, par exemple, la construction d'une grande liste de manière efficace, au coup par coup par une référence unique - et quand la liste complète, faisant que (maintenant sans doute pas à être modifié) connu et désigné de divers référents

.

(2) Je pense AJOUT! devrait se comporter comme append, seulement (potentiellement) destructivement. Et si APPEND! devrait attendre un certain nombre de listes comme arguments. Chaque liste, mais la dernière seraient probablement SET-CDR! D à l'autre.

(3) La définition ci-dessus AJOUT! est essentiellement Nconc de Mac Lisp et Common Lisp. (Et d'autres lisps).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top