könnten Sie rufen map-into
;-)
(defun map-into-tree (function tree)
(labels
((recurse (tree)
(typecase tree
(sequence (map-into tree #'recurse tree))
(t (funcall function tree)))))
(recurse tree)))
... oder äquivalent:
(defun map-into-tree (function tree)
(typecase tree
(sequence (map-into tree (lambda (u) (map-into-tree function u)) tree))
(t (funcall function tree))))
Test:
(map-into-tree #'1+ (copy-tree '((9 10) (8 9 10 11 (12 13)() (11)() 13))))
=> ((10 11) (9 10 11 12 (13 14) NIL (12) NIL 14))
Ich bin nicht sicher, was mit einem Baum geschehen soll welches Strings enthält: Wollen wir wirklich über jedes Zeichen iterieren? In der Tat ist das, was hier oben getan wird.
Ich stelle auch fest, dass map-in mit Sequenzen arbeitet, die Cons-Zellen enthalten, aber der entsprechende Map-in-Tree nicht, obwohl Map-In verwendet wird.
(1 (2 . 3))
ist eine richtige Liste mit zwei Elementen, nämlich 1
und (2 . 3)
. Da map-into
nicht in Elemente rekurriert, wird nur die Funktion für diese beiden Elemente aufgerufen. In Ihrem Kommentar war dies print
, die unsaubere Listen ohne Probleme drucken können.
Das zweite Element ist eine Sequenz: Wenn Sie map-into-tree
aufrufen, ruft die Funktion rekursiv map-into
mit dieser Sequenz auf, die zufällig eine falsche Liste ist. map-into
erwartet eine richtige Sequenz und schlägt daher mit falschen Listen fehl.
Bitte beachten Sie, dass in Ihrer Frage, Sie haben gesagt:
eine Funktion, die in einen beliebigen Baum von verschachtelten richtigen Listen zur Karte soll
Ein Baum mit dem falschen Listen ist kein gültiger Eingang .
Schließlich merke ich, Sie destruktiven Funktionen auf wörtliche Daten aufrufen, etwa so:
(map-into #'print '(1 2))
Die angegebene Liste ist eine Konstante, es zur Laufzeit modifizieren ist nicht definiertes Verhalten. Deshalb habe ich zuerst copy-tree
in meinem Beispiel verwendet.
würde also diese Arbeit alle Sonderfälle zu handhaben [...]
Da es bereits ein Setzkasten vorhanden ist, genügt es, den Sonderfall der cons
zu behandeln; das funktioniert unabhängig von der Art der Wert im cdr
Steckplatz gehalten:
(defun map-into-tree (function tree)
(labels
((walk (tree)
(typecase tree
(cons
(prog1 tree
(setf (car tree) (walk (car tree)))
(setf (cdr tree) (walk (cdr tree)))))
(sequence (map-into tree #'walk tree))
(t (funcall function tree)))))
(walk tree)))
Cool - die Kraft ist mit dir. Ich stelle auch fest, dass Map-In mit Sequenzen arbeitet, die Cons-Zellen enthalten, aber der entsprechende Map-In-Tree nicht, obwohl Map-In verwendet wird. Zum Beispiel: (setq x '(1 (2. 3))); (map-in x # 'x drucken') -> 1, (2. 3); aber (map-in-tree # 'x drucken') -> Fehler. Kannst du kurz erklären warum der Fehler für gepunktete Listen ist? – davypough
@davypough Ich habe die Antwort bearbeitet, weil sie nicht in einen Kommentar passte. – coredump
diese Arbeit So würde alle Sonderfälle behandeln: '(defun gepunkteter listp (Artikel) (und (consp Artikel) (cdr (letzter Punkt)))) (defun map-in-Baum (Funktionsbaum) (typecase Baum ((oder String (erfüllt dotted-listp)) (Funcall Funktion Baum)) (Sequenz (Karte in Baum (Lambda (u) (Karte in Baum-Funktion u)) Baum)) (t (funcall function tree)))) ' – davypough