Raku-Kurs / Funktionale, nebenläufige, reaktive und Web-Programmierung / Funktionale Programmierung / Rekursion
Rekursion mit multi-Subroutinen
Bisher war der Grundfall eine Zeile innerhalb der Subroutine
— ein ternärer Ausdruck oder ein frühes return, das das
Argument prüft. Raku bietet einen ausdrucksstärkeren Weg, dasselbe zu
schreiben. Da eine Subroutine mehrere multi-Kandidaten
haben kann, können Sie dem Grundfall und dem rekursiven Schritt
je eine eigene Subroutine geben und die Mehrfachauswahl
für jeden Aufruf die richtige wählen lassen.
Erinnern Sie sich an die Fakultät. Mit multi werden ihre
zwei Fälle zu zwei Subroutinen:
multi fact(0) { 1 }
multi fact($n) { $n * fact($n - 1) }
say fact(5); # 120Der erste Kandidat trifft nur, wenn das Argument genau 0
ist — dieses Literal in der Signatur ist der Grundfall. Jeder
andere Aufruf geht an den zweiten Kandidaten, der multipliziert und sich
selbst aufruft. Wenn fact($n - 1) schließlich
0 erreicht, wechselt die Auswahl zum ersten Kandidaten, und
die Kette der Aufrufe wickelt sich ab. Der Grundfall ist keine im Rumpf
vergrabene Verzweigung mehr; er ist eine Subroutine, die für einen
einzigen Wert besteht.
Warum 0 und nicht 1? Weil jeder Schritt
eins abzieht, landet jede Ausgangszahl irgendwann genau auf
0, und 0! ist als 1 festgelegt —
bei 0 endet der Abstieg also wirklich. Ein Literal-Kandidat
trifft genau einen Wert, ein Grundfall
multi fact(1) würde fact(1) also richtig
berechnen, aber fact(0) zu multi fact($n)
durchfallen lassen und ewig über null hinaus weiterrekursieren. Bei
0 anzuhalten hält die Subroutine für jede nichtnegative
ganze Zahl richtig, fact(0) eingeschlossen.
Besonders gut liest sich das, wenn es mehr als einen Grundfall gibt. Fibonacci braucht zwei:
multi fib(0) { 0 }
multi fib(1) { 1 }
multi fib($n) { fib($n - 1) + fib($n - 2) }
say fib(10); # 55Jeder Grundfall ist ein eigener einzeiliger Kandidat, und der rekursive Kandidat erledigt alles Übrige — ganz ohne verschachtelte Bedingungen.
Ein Literal wie 0 trifft nur genau diesen Wert. Deckt
der Grundfall einen Bereich ab — „$n ist
1 oder kleiner“ —, nehmen Sie stattdessen eine
where-Einschränkung:
multi fact($n where * <= 1) { 1 }
multi fact($n) { $n * fact($n - 1) }
say fact(6); # 720Der eingeschränkte Kandidat ist spezifischer, Raku probiert ihn also
zuerst; der schlichte $n-Kandidat fängt alles Übrige
auf.
Dieselbe Sorgfalt wie zuvor gilt weiterhin: Jeder rekursive Weg muss
einen Grundfall-Kandidaten erreichen. Die Fakultät mit dem Literal
0 ist etwa nur für nichtnegative ganze Zahlen sicher —
fact(-1) würde über 0 hinausschreiten und ewig
weiterrekursieren, weil nie ein Kandidat trifft. Die Fälle auf
multi-Subs zu verteilen nimmt die Notwendigkeit eines
Grundfalls nicht weg; es gibt diesem Grundfall nur einen eigenen Namen
und ein eigenes Zuhause.
Praxis
Lösen Sie 1 Quiz zum Inhalt dieses Themas.
Kursnavigation
← Quiz — Der Basisfall | Quiz — Rekursion mit multi-Subroutinen →
💪 Oder springen Sie direkt zu den Übungen dieses
Abschnitts.