Wir haben die Funktion
(nothing-happens ...) bereits als Prototyp für
weitere Vorgehensweisen kennengelernt (wer dieses Kapitel noch nicht
gelesen hat, sollte dies jetzt erst nachholen). nothing-happens zerlegt
sein Argument auf rekursivem Wege vollständig bis auf die Atom-Ebene,
setzt es wieder zusammen und gibt es (unverändert) zurück.
Die Funktion
(mapin ...), die jetzt hier vorgestellt werden soll, ist
nichts weiteres als ein
nothing-happens, dem als weiteres Argument eine
lambda-expression übergeben wird, die auf jedes Atom, das während der
Verarbeitung auftritt, angewendet wird.
Wichtig ist, dass weder nothing-happens noch mapin jemals die Struktur
einer übergebenen Liste in irgendeiner Weise verändern können. Werfen wir
noch einmal einen Blick auf nothing-happens:
(defun nothing-happens(any-data / )
(cond
( (null any-data)nil)
( (atom any-data)any-data)
( (and
(=(type any-data)'LIST)
(cdr any-data)
(atom(cdr any-data))
)
(cons
(nothing-happens(car any-data))
(cdr any-data)
)
)
('T
(append
(list(nothing-happens(car any-data)))
(nothing-happens(cdr any-data))
)
)
)
)
Es gibt in der Funktion zwei Stellen, wo Atomen begegnet werden kann:
nämlich gleich beim zweiten und dritten Test innerhalb von cond. Im einen
Fall wird direkt getestet, ob ein Atom vorliegt, im anderen Fall geht es
um die dotted pairs, bei denen ja der
cdr ein Atom sein muss! Dies sind
also unsere Ansatzpunkte, an denen die lambda-expression ausgeführt werden
muss.
Der Code für unsere Funktion
mapin sieht jetzt also so aus:
(defun mapin(expr a / )
(cond
( (null a)nil)
( (atom a)((eval expr)a))
( (and(=(type a)'LIST)(cdr a)(atom(cdr a)))
(cons
(mapin expr(car a))
((eval expr)(cdr a))
)
)
('T
(append
(list(mapin expr(car a)))
(mapin expr(cdr a))
)
)
)
)
Was können wir jetzt mit dieser Funktion anfangen? Hier nur ein paar
Beispiele, die für sich selber sprechen:
(mapin '1- '(1 2(3 4(5 6(((7)))8 9))10))
=> (0 1(2 3(4 5(((6)))7 8))9))
(mapin 'strcase '("abc" ("def" . "ghi")(("jkl"))))
=> ("ABC" ("DEF" . "GHI")(("JKL"))))
(mapin
'(lambda(v / )
(if(=(type v)'STRING)(strcase v))
)
'("a"(("b" . 1)("c" . "d")((5 "e"))))
)
=> ("A"(("B" . 1)("C" . "D")((5 "E"))))
Eine etwas kompliziertere Anwendung von
mapin werden wir dann im Kapitel
über Funktionsschablonen kennenlernen.