Meine Herren!
Soll ich alter Knacker das noch ohne jegliche Funktionsbeschreibung verstehen?
Ich dachte das Beispiel wäre trivial für jemanden, der Erfahrung mit Closures und Rekursion hat. Manchmal überschlägt man sich eben selber, wenn man eingefleischtes Gelerntes versucht zu erklären.
Ich sehe ja noch nicht einmal (mit Ausnahme der Referenzen), was das mit meinem Problem zu tun haben könnte...
Und das könnte daran liegen, dass deine Problembeschreibung nicht auf dein Problem passt :P Ein Closure ist eine Funktion, die als Rückgabewert eine weitere Funktion liefert. Das Grundgerüst eines Closures, wie es auch in meinem Beispiel vorkommt ist:
$outer = function(){
$inner = function(){
}
return $inner;
}
Ich bin nun davon ausgegangen, dass das Problem darin liegt, dass die innere Funktion rekursiv arbeiten soll. Das Problem dabei ist, dass die innere Funktion anonym ist, weshalb es notwendig ist, ihr die Referenz auf sich selbst ausdrücklich bekannt zu machen.
$outer = function(){
$inner = function() use (&$inner) {
$inner(); // ACHTUNG: Endlosrekursion
}
return $inner;
}
Um Endlosrekursion zu vermeiden, habe die Variable $times eingeführt, die Zählen soll, wie häufig die innere Funktion aufgerufen wird:
$outer = function(){
$times = 0;
$inner = function() use( &$inner, &$times ){
$times++;
if ( $times < 5 ){
$inner();
}
}
return $inner;
}
Um dem Beispiel mehr Würze zu geben, habe ich die Häufigkeit, wie oft abgestiegen werden darf über den Parameter $n steuerbar gemacht:
$outer = function( $n ){
$times = 0;
$inner = function() use( &$inner, &$times, $n ){
$times++;
if ( $times < $n ){
$inner();
}
}
return $inner;
}
Die Funktionen sollten dann auch ausgeführt werden:
$inner = outer( 5 );
$inner();
Die Variablennamen an dieser Stelle waren ungünstig gewählt. $innerIntance
wäre passender gewesen.
Um zu illustrieren welche Funktion, wann aufgerufen wird, habe ich die Ausgabe reingepackt:
$outer = function ( $n ) {
echo "Outer\n";
$times = 0;
$inner = function () use ( &$times, &$inner, $n ) {
echo "Inner : ${times}\n";
$times++;
if ( $times < $n ){
$inner();
}
};
return $inner;
};
PS: Eine Eigenart dieses Beispiels, die nicht besonders intuitiv ist, dass die innere Funktion nur beim ersten Aufruf $n mal rekursiv absteigt und alle weiteren Aufrufe zwar die Variable $timer erhöhen, aber tatsächlich keine rekursiven Aufrufe mehr stattfinden.
Es wäre mMn dann auch außerordentlich hilfreich, daraus einen Wiki-Artikel zu erzeugen. Meinst Du, dass wir das hier zusammen gebacken bekommen?
Dafür habe ich nicht die nötige Zeit. Meines Erachtens nach ist das hier ein gute Artikel über funktionale Programmierweise in PHP: http://code.tutsplus.com/tutorials/functional-programming-in-php--net-35043
“All right, then, I'll go to hell.” – Huck Finn