Diskussion:Closure (Funktion)

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen

Funktionale Herkunft[Quelltext bearbeiten]

Hier fehlt definitv ein Beispiel aus Ocaml oder Haskell, das das gesamte spektrum der effekte von closures aufzeigt und beleuchtet. Sorry liebe Perl'ler (ich mag die sprache auch), aber sie ist dafür einfach nicht optimal...

-- 212.100.48.164 15:15, 9. Feb 2006 (CET)

Um Zeilen im Beispielcode hervorzuheben, wurde ''' (fett) benutzt, das hier jedoch nicht als Wikisyntax erkannt wird. Das irritiert und sollte geändert werden.

Ich fände es wichtig die Synonyme (anonyme Funktionen, Lambda Funktionen) noch mit aufzunehmen, die in anderen Sprachen eher gebräuchlich sind. Diese Begriffe finden sich auch in der verlinkten Java-Seite.

Ich bin mir im Moment auch unklar darüber warum hier nicht eindeutig von anonymen Funktionen oder Lambda-Ausrücken die Rede ist. In der aktuellen ct 19/2009 steht auch, dass Closures anonymen Funktionen oder Lambda-Ausrücke heißen. Irgendwie kommt es mir vor als ob jemand den Artikel geschrieben hat der entweder nicht besonders gut erklären kann oder zum Punk kommen kann oder der einfach keine Ahnung hat.<span id="81.210.229.29-

Closures und Lambda Funktionen sind 2 unterschiedliche Paar Schuhe! Lambda Funktionen sind einfache Anonyme Funktionen (dh. ohne Symbol) während Closures den Ausführungskontext miteinbeziehen, jedoch nicht zwangsweise müssen Closures mit Lambda Funktionen gebildet werden. -- Julian (nicht signierter Beitrag von 78.51.198.13 (Diskussion | Beiträge) 15:18, 27. Mär. 2010 (CET)) [Beantworten]
Ich finde auch, dass mindestens eine Erwähnung des Lambda-Kalküls angebracht wäre, insbesondere von Currying, das ja nur durch Einbezug von Funktionsabschlüssen möglich ist. Eine solche Erklärung wäre für jemanden ohne entsprechenden Hintergrund vielleicht erhellend, aber rein inhaltlich gehört eine Erwähnung von Currying meiner Meinung nach hier unbedingt dazu.
Vielleicht würde zur Veranschaulichung von Funktionsabschlüssen eine Gegenüberstellung von zwei Schreibweisen derselben Funktion helfen:
  • (x, y) → x + y – eine Funktion mit zwei Parametern; kein Funktionsabschluss!
  • x → (y → x + y) - dieselbe Funktion mit Currying; Funktionsabschluss! Die "innere" Funktion kennt ihr Argument x nicht über ihre Parameter, sondern als Wert, der von der "äusseren" (enthaltenden) Funktion bereitgestellt wird.
-- Hub 10:50, 6. Jun. 2010 (CEST)[Beantworten]

Überarbeiten[Quelltext bearbeiten]

Ist zwar nicht mein Baustein, aber:

  • Sind die Codebeispiele alle nötig? Nicht jeder kann Perl, Python und Ocaml. Pseudocode möglich?
    • Wozu ist ein if (0==0) gut? (dritter Codeblock)
  • Für Nichtprogrammierer/Anfänger ist der Text wohl unverständlich.

-- V·R·S (|) 11:47, 3. Sep. 2008 (CEST)[Beantworten]

Ein minimales Code-Beispiel wäre besser als das jetzige Sammelsurium.
Und: Der Artikel müsste auf den Artikel Lexical Scoping (oder wie immer das auf Deutsch heiß) aufbauen, den es unglaublicherweise noch nicht gibt. Scope verweist auf Variable (Programmierung), der überhaupt nicht auf Lexical Scoping eingeht.
In Roberto Ierusalimschy, Programmieren mit Lua, ISBN 3937514228, ist es eigentlich vorbildlich erklärt.
--Pjacobi 01:26, 3. Okt. 2008 (CEST)[Beantworten]

Ich habe mich beim Nachschlagen gerade gewundert, dass hier soviel Perl-Code auftaucht. Wie viele Leute können denn bitte Perl lesen, dass so ein riesen Beispiel hier darin geschrieben sein muss? Das ist doch nicht euer Ernst? use strict? Anonyme Subroutine? was ist das denn für eine Terminiologie, das ist zu stark an Perl angelehnt, das interessiert doch niemanden, lasst ein funktionales Beispiel drin und eins in Ruby oder Python und kürzt den Artikel radikal. Ruby kann man fast normal lesen und Python lernt fast jeder an der Uni oder auf der Arbeit aber Perl? Der Artikel scheint hier sowieso irgendwie aus dem Ruder gelaufen zu sein, denn qualitativ ist er nicht besonders gut und er müsste wesentlich kompakter sein. Und nehm die Perl Beispiele raus ich glaub das einfach nicht!

Vielen Dank für diesen sehr Konstruktiven Text. Ich bin auch der Meinung, dass hier nicht Perl als Beispiel verwendet werden sollte, sondern meine Lieblingssprache XY ... Ihr unqualifiziertes geflamme verhindert jede sachliche Diskusion. Kein Wunder, dass Sie ihren Namen weggelassen haben. Zum Thema: Solche Beispiele sind immer schwierig und dass jeder die Sprache wählt, in der er glaubt sich verständlich ausdrücken zu können ist nur natürlich. Das Perlbeispiel ist für Fachunkundige nicht weniger kryptisch als die Beispiele in Ruby, OCaml und irgend einem Lisp Dialekt. Ich wäre zware für gute Beispiele in einer für alle ( auch Bauern aus dem 13Jahrhundert ) verständlichen PseudoCode-Sprache. Als Erstes werde ich aber das Perlbeispiel mit Hilfe des Perl-Artikels kommentieren. -- Märzhase 13:53, 25. Jan. 2010 (CET)[Beantworten]


Also ich finde es ziemlich gleichgueltig in welcher Sprache das Beispiel ist. Wer sich fuer Eigenschaften von Programmiersprachen interessiert wird schon ein paar lesen koennen, Pseudocode macht es nicht immer besser, aber es sollte mindestens ein funktionales, wie ein imperatives Beispiel geben. Das Perl wuerde ich eher so schreiben:
  my $str = "outer";
  {
      my $str = "inner";
      sub innen () { say "$str"; }
  }   
  say "$str"; # "outer"
  innen(); # "inner"
Ok, oder falls man Ecma Script "verstaendlicher" findet so:
  var str = "outer";
  (
   function () {
    var str = "inner";
    alert(str);
   }()
  );
  alert(str);
Allerdings muss man sich dann gleich mit Closures vs. anonyme Funktionen beschaeftigen.
--87.78.38.1 16:49, 7. Feb. 2010 (CET)[Beantworten]


Der Artikel ist dermaßen grottenschlecht, dass ich erstmals für Löschen und Neuschreiben stimmen würde. Aus dem aktuellen Artikel ist fürchte ich nichts mehr zu machen. --Sebastian.Dietrich 19:44, 14. Jul. 2010 (CEST)[Beantworten]

Closures und Java[Quelltext bearbeiten]

Habe zwei Änderungen vorgenommen:
1. Die Unterstützung von Closures ab JDK 7 steht derzeit noch nicht fest.
2. "Sun-Konzept zur Closure-Unterstützung ab Java 7". Neal Gafter arbeitet bei Google und Gilad Bracha ist auch nicht mehr bei Sun. Das Ganze ist also nicht wirklich ein Sun-Konzept.

--24.30.187.238 07:00, 29. Jan. 2007 (CET)[Beantworten]

closures bei java: man bedenke auch die existenz von groovy: http://java.sun.com/developer/technicalArticles/JavaLP/groovy/ --Kunobert 20:47, 11. Feb. 2007 (CET)[Beantworten]

Java 8 kann es jetzt. In Java 7 kann man mit anonymen inneren Klassen und Interfaces wie Runnable auch recht gut Closures nachbauen, es ist nur mehr "noise" und dadurch weniger attraktiv.--Bk1 168 (D) 01:00, 21. Jun. 2014 (CEST)[Beantworten]

In Java 8 hat sich ja einiges geändert, und das nicht nur syntaktisch. Lambdaausdrücke sind nähmlich tatsächlich nicht als anonyme innere Klassen sondern als Funktionsreferenzen implementiert.
Damit ist der Abschnitt Limitierungen bzgl. Java nicht mehr korrekt. Im Unterschied zu z. B. C# ist es allerdings nicht möglich, die Referenz auf den umgebenden Kontext zu ändern, wohl aber den Inhalt einer Referenz.
Folgendes Beispiel kommt vollständig ohne innere Klassen aus:

Supplier<Supplier<String>> mutterfunktion = () -> {
	int container[] = {0};	// in den Kontext "mutterfunktion" eingebetteter Wert
	return () -> {
		container[0]++;
		return "Ich esse " + container[0] + " Kuchen.";
	};
};

Supplier<String> essen = mutterfunktion.get();	// erhalten der inneren Funktion
System.out.println(essen.get());		// schreibt "Ich esse 1 Kuchen." auf die Konsole
System.out.println(essen.get());		// schreibt "Ich esse 2 Kuchen." auf die Konsole
System.out.println(essen.get());		// schreibt "Ich esse 3 Kuchen." auf die Konsole

Das kann evtl. als Beispiel angefügt werden. Supplier ist ein Standardinterface aus dem Package java.util.function

Man beachte, dass container ein Array oder eine Objektreferenz sein muss, da eine eingebettete Referenz nicht geändert werden kann - sie muss in Java implizit final sein. Der Inhalt einer Referenz kann hingegen geändert werden. Das sieht im Beispiel für Python übrigens genau so aus. --Vseibt (Diskussion) 13:18, 9. Okt. 2014 (CEST)[Beantworten]

Beispiel etwas lang[Quelltext bearbeiten]

Ach, an sich finde ich das Perl-Beispiel recht einleuchtend. Allerdings finde ich es etwas aufgebläht. Statt zweier Variablen und drei Methoden hätte eine Variable und je eine Getter- und Incremtentor-"Methode" auch genügt. Eigentlich finde ich das Python-Beispel viel besser. Dann spart man sich auch die if(0==0) - Blocks.

Der Perl-Code ist nur wenig geeignet, ein Programmierkonzept zu erklären. Man sollte sich lieber auf Python beschränken oder besser noch ein Beispiel in Ruby oder Scheme bringen. 194.114.62.65 08:08, 10. Jan. 2008 (CET)[Beantworten]

Das vierte Beispiel ist etwas zu kurz und ohne Kommentare für nicht python Programmierer schwer verständlich.(für mich unverständlich)

def closure():
    __counter=[0]
    def inc():
       __counter[0]+=1
    def get():
       return __counter[0]
    return inc, get

Könnte man nicht ein Beispiel in Pseudocode schreiben, statt sich ständig um die Sprache zu streiten.? update: Hatte signatur vergessen und hab den codeblock geändert --84.58.217.1 15:00, 4. Okt. 2008 (CEST)[Beantworten]

Ich habe eine Erläuterung geschrieben, die das Beispiel verständlich macht. Diese wurde jedoch noch nicht freigegeben. Warum auch immer. Ich hoffe damit wird der Code einfacher lesbar. Wo Pseudocode einfacher als Python sein soll, ist mir jedoch ein Rätsel. schrub kn0rke 11:32, 18. Okt. 2008 (CEST)[Beantworten]

Sinn der Sache?[Quelltext bearbeiten]

Mir ist nicht so richtig klar, was man jetzt mit diesen Closures eigentlich machen soll. Das einzige Argument im Artikel ist Kapselung, aber das geht mit public/protected/private auch. (nicht signierter Beitrag von 87.153.141.163 (Diskussion) 17:57, 13. Sep. 2007 (CEST))[Beantworten]

Die Erklärung im Artikel ist in meinen Augen auch nicht wirklich erhellend, aber aus dem Stegreif könnte ich auch nicht sagen, wie man es besser sagen sollte. Klassen und Closures sind in gewisser Hinsicht isomorph. Das wird manchmal umgangssprachlich in den folgenden beiden Formeln zusammengefasst: "objects are a poor man's closures," und "closures are a poor man's objects," siehe beispielsweise hier oder hier. Man kann Closures zur Implementierung von Objektsystemen verwenden, siehe beispielsweise Kapitel 3.1 in Structure and Interpretation of Computer Programs. Umgekehrt kann man in einer Programmiersprache mit Unterstützung für objektorientierte Programmierung auch Closures auch durch entsprechende Objekte realisieren. — Tobias Bergemann 09:15, 14. Sep. 2007 (CEST)[Beantworten]

Folgendes Beispiel ist meines Erachtens sinnvoller (python):

Motivation für das Beispiel[Quelltext bearbeiten]

Ein Programm soll auf einer Liste eine Funktion anwenden.

Es wird zuerst eine Liste definiert, auf der diese Funktion angewendet werden soll:

>>> l=[2,3,4,4]

Auf alle Werte dieser Liste soll 3 hinzugezählt werden. Für diesen Zweck definiere ich ein Closure bzw. eine anonyme Funktion:

>>> f=lambda n:n+3

Dieses Closure wird mit Hilfe der Funktion map auf der Liste angewendet:

>>> map(f,l)
[5, 6, 7, 7]

Die Funktion map erwartet als Argument eine Liste und ein Closure. Die Besonderheit dieses Konzeptes ist also, dass man als Argument einer Funktion eine Funktion übergeben kann.

Die Implementierung der Funktion map lautet folgendermaßen:

def map(f,l):
    return [f(x) for x in l]

Der entscheidende Punkt an dieser Stelle ist, dass das Argument f eine Funktion ist, die innerhalb von Map aufgerufen wird.

Ein anderes Beispiel wäre ein Filter:

>>> f2=lambda n:n==4
>>>> filter(f2,l)
[4, 4]

Gegenüberstellung der Implementierung ohne Closures[Quelltext bearbeiten]

In Java (bis 1.6) würde man für den gleichen Zweck erst ein Interface definieren und dann implementieren müssen. Hier wird auch deutlich warum Closures auch anonyme Funktionen genannt werden. Denn das Closure könnte ich direkt als Argument der Funktion übergeben, ohne dass es eine Klasse oder einen Namen hat:

map(lambda n:n+3, [1,2,3,4])
public interface Filter {
    public boolean filter(Object value);
}

public class FilterFour implements Filter {
    public boolean filter(Object value) {
        return Integer.parseInt(value)==4;
    }
}

public List<Object> filter(Filter filter, List<Object> list) {
   List<Object> result = new ArrayList<Object>();
   for (Object x:list) {
       if (filter.filter(x)) {
           result.append(x);
       }
   return result;
   }
}

// Aufruf

filter(new FilterFour(), mylist);

Anhand dieser Gegenüberstellung erschließt sich vielleicht, dass Closures für solche Zwecke deutlich eleganter sind.

Closures sind dann sinnvoll einzusetzen, wenn keine Daten gekapselt werden sollen, wie hier in der Filter-Klasse. Denn dann ist die Definition eines Interfaces zuzüglich Klasse, aus der dann ein Objekt instantiiert wird, überdimensioniert, da das Objekt ja nur der Träger einer einzelnen Funktion ist. Wieso sollte ich diesen Aufwand betreiben, wenn ich nur eine einzelne Funktion benötige? Genau an dieser Stelle kommt das Closure oder die anonyme Funktion, also eine Funktion ohne Träger-Klasse ins Spiel.

Wenn ich Daten kapseln möchte (wie dies im Beispiel auf der aktuellen Seite gezeigt wird), sollte ich tunlichst auch eine Klasse definieren.

Zur Diskussion: Ich kenne das Konzept nur aus der Praxis (python, scheme/dsssl), aber nicht den theoretischen Kontext.

Die genaue Definition von Closure ist mir selber nicht klar und ich sehe zwischen der Definition auf der Java-Seite und der auf der englischen Wikipedia-Seite einen Widerspruch:

java-seite: ... parameterized delayed-execution blocks of code, variously called lambda, anonymous functions, or closures.

Hier ist Closure das gleiche wie eine anonyme Funktion.

en-wikipedia: In this example, the lambda expression (lambda (book) (>= (book-sales book) threshold)) appears within the function best-selling-books. When the lambda expression is evaluated, Scheme creates a closure consisting of the code for the lambda and a reference to the threshold variable, which is a free variable inside the lambda.

Hier wird aus einer Lambda-Funktion ein Closure (was auch immer das sein soll) erzeugt.

Wenn kein Widerspruch besteht würde ich das ganze (dann noch gescheit formatert) gerne in den Artikel übernehmen. Ich würde aber auch vorschlagen, das andere Beispiel zu entfernen. 77.24.211.226 08:58, 17. Mai 2008 (CEST)[Beantworten]

Schön wäre es, wenn das Beispiel schon hier ordentlich formatiert werden würde, denn auch mir erschließt sich die Eleganz von Closures noch nicht. (Und untschreibt bitte mit den 4 Tilden, ist schöner.) 89.246.164.202 00:09, 17. Mai 2008 (CEST)[Beantworten]

Der Sinn der Sache...[Quelltext bearbeiten]

...ist nicht nur, dass man ein Stück ausführbaren Code hin und her reichen kann ohne ein Interface dafür definieren zu müssen (siehe Interfaces und abstrakte Klassen in Java, beispielsweise ActionListener die meist anonym "in place" implementiert werden), sondern das eine Closure Zugriff auf ihren Kontext behält. Bei Java ändert sich beispielsweise die Bedeutung von "this", weil man in einer anderen Klasse ist. Außerdem kann man nicht auf Variablen im äußeren Kontext zugreifen wenn man später an anderer Stelle aufgerufen wird. Bei Sprachen mit Closures geht das, man behält einen Zeiger auf das Objekt, und arbeitet nicht auf einer Kopie und wenn sich das Objekt bzw. dessen Wert zwischen der Erstellung und der Ausführung geändert hat, sieht man diese Änderung.

TheSunToucher 14:18, 7. Nov. 2008 (CET)[Beantworten]

Bevor ich auf diesen Artikel stieß wusste ich noch gar nichts von Closures. Der Artikel hat mich dann auf die Disskussionsseite getriebn, in der Hoffnung hier eine gescheite Definition zu finden. Die vorherige ist zwar etwas kompliziert augedrückt, meint aber, so glaube ich, im wesentlichen das richtige (ganz langsam lesen): Closures sind Anonyme Funktionen, die bei ihrer Definition die, bis dahin gesetzten, Variablen aus dem selben Geltungsbereich, in dem sie definiert wurden, erben (Geltungsbereich = Scope = Kontext). Es gibt auch Programmiersprachen, denen man explizit sagen muss was vererbt werden soll.
Beispiel:<<<
definiere status = 256
definiere Satusprüfung = closure (statusquo) #Variable status wird in den neuen Geltungsbereich kopiert!
{

Wenn statusquo == status
{
gebezurück Ja
}
sonst
{
gebezurück Nein
}

}
rufeauf Statusprüfung(status) #Gibt Ja zurück
definiere status = 512
rufeauf Statusprüfung(status) #Gibt Nein zurück
>>>
Die Variable status wird automatisch in den Geltungsbereich des Closures kopiert und existiert dort bei jedem aufruf (wie als hätte man sie mit static definiert). Sie ist aber keine Referenz auf status im normalen Geltungsbereich, weswegen eine Überprüfung die Veränderung erkennt. --178.2.93.127 16:23, 6. Mär. 2011 (CET)[Beantworten]

Programmiersprachen und Beispiele[Quelltext bearbeiten]

Kann mich der Kritik bzgl. der vielen verschiedenen Programmiersprachen in den Beispielen nur anschließen. Es wäre dringend notwendig den Artikel noch einmal zu überarbeiten. Nicht-Programmierer haben meines erachtens nach gar keine Chance da irgend etwas verstehen zu können.

Im Artikel wird soweit ich das sehe auch nicht erwähnt in welcher Sprache der Beispiel-Code der ersten beiden Blöcke abgefasst ist. Da ich selbst z.B. bisher weder mit Perl, Ruby, Python, PHP, Lua, Haskell, OCaml, Groovy, Smalltalk, Scheme, oder Lisp programmiert habe, kann da ehrlich gesagt im Moment nur raten (tippe mal auf Perl oder PHP für die ersten beiden Blöcke, das ist aber wirklich aus dem Bauch raus geraten - einfach wegen der Dollar Zeichen : ) Finde es prinzipiell ja schön Beispiele in möglichst vielen unterschiedlichen Sprachen anzubieten, aber es sollte vorher unbedingt erwähnt werden welche Sprache jetzt gerade konkret verwendet wird.

Toll wäre natürlich wenn man per Link auf ein Beispiel in der bevorzugten Sprache verweisen könnte (wär' schon 'ne Sache).

C/C++, Java, Visual Basic kennen/kannten dieses Konstrukt so bisher jedenfalls nicht, und da ich selbst z.B. aus dieser Gegend komme war ich erst mal wirklich erstaunt (und ein wenig peinlich berührt).

Natürlich favorisiert jeder seine persönlichen Vorlieben bzgl. der Programmiersprache, aus welchen Gründen auch immer, die Beispiele sollten aber gerade für Leser ohne Vorwissen leicht nachzuvollziehen sein. Leser die sich bereits mit Sprachen auseinander setzen in denen Closures von anfang an angboten werden verfügen meist über ausführliche Referenzen, können diese auch verstehen, und müssen deshalb in der Regel nicht im Wikipedia nachschlagen.

Ich persönlich denke man solle auf alle Fälle wenigstens ein Beispiel mit Pseudocode anbieten.

Würde sich darüber hinaus z.B. nicht auch Javascript für ein Beispiel anbieten ? Javascript ist jedenfalls wirklich weit verbreitet.

Weiß im Moment auch nicht in welchen Sprachen ausser C# in letzter Zeit Closures noch eingeführt wurden, aber solche Neuerungen wären meines erachtens auch erwähnenswert. Auch hier könnte/sollte man vielleicht durch Verlinkung auf detailiertere Infos verweisen.

Trotzdem vielen Dank für den Artikel und die erläuternden Beiträge

(nicht signierter Beitrag von 88.217.61.43 (Diskussion) )


Du hast so recht!
Die Beispiele sind m.E. ungeschickt gewählt, außer in Javascript (oder Lua), was von jedem gelesen werden kann, der schon einmal eine algoloide Sprache programmiert hat, kann es natürlich auch in C, Pascal, oder Java aufgezeigt werden, auch wenn der Code-Schnipsel dann kein gültiges Standard-C, -Pascal oder -Java ist.
Es fehlt einfach auch an Grundlagenartikeln wie en:Funarg problem und en:Scope (programming).
--Pjacobi 23:16, 16. Mär. 2009 (CET)[Beantworten]

Erklärung dynamischen und lexikalischen Skopus als Grundlage für das Verständnis von Closures[Quelltext bearbeiten]

Ich habe eine – für das Verständnis meines Erachtens sehr hilfreiche – Erklärung lexikalischen Gültigkeitsbereichs, ausgehend vom dynamischen Skopus und der damit einhergehenden Problematik, angefügt. Durch sie kann der Leser den Sinn und die Beweggründe für lexikalische Gültigkeitsbereiche und lexikalische Closures besser verstehen.

Die Beispiele sind aus zweierlei Gründen in CL gehalten: Erstens bietet CL sowohl dynamischen als auch statischen Skopus, was für die Beispiele hilfreich ist. Zweitens sind Bindungen in Lisp visuell deutlich zu erkennen und der Gültigkeisbereich lexikalischer Variablen mithin auf den ersten Blick deutlich. Allein, ich war zu faul Quellen zu referenzieren, da ich das Ganze aus dem Kopf aufgeschrieben habe – die Beispiele können jedoch allesamt in der REPL nachvollzogen und die Quellen im HyperSpec nachgeschlagen und dann referenziert werden.

(nicht signierter Beitrag von 217.226.215.112 (Diskussion | Beiträge) 19:19, 8. Okt. 2009 (CEST)) [Beantworten]

Ja, nee is klar[Quelltext bearbeiten]

Weil der C-Standard so abgrundtief schlecht ist, interessiere ich mich für besseres, und die Vorteile purer funktionaler Funktionen, was Optimieren und Parallelisieren angeht, sind ja offensichtlich. Also lese ich gelegentlich auch mal was über diese Themen.

Das Problem dabei ist, daß die damit befaßten Menschen von dem Drang getrieben scheinen, einfache Dinge so kompliziert wie möglich auszudrücken, und dann noch ein bißchen unverständlicher zu machen. Das sieht man schon an der Syntax dieser "Programmiersprachen", bei XLST krieg ich sofort das Kotzen.

Ich würde gern ein Beispiel nennen, aber da die Angelegenheit derart unverständlich gemacht wird, weiß ich nicht, ob meine laienhafte Zusammenfassung "Closures nennt der Akademiker das, was normalerweise Klassengekapselte-Globalvariable, äh, Static, na du weißt schon" korrekt ist. Also zeige ich mal, warum z.B. dieser Artikel unverständlich ist.

Als Closure oder Funktionsabschluss bezeichnet man eine Programmfunktion, die beim Aufruf ihren Definitionskontext reproduziert, soso, Definitionskontext ja? Es geht hier um Programmieren, nicht "Geisteswissenschaft". selbst wenn dieser Kontext außerhalb der Funktion schon nicht mehr existiert. Closures „konservieren“ also ihren Kontext. Äh, Moment mal. Beim Aufruf? Ich dachte, der Witz an der funktionalen Programmierung wäre, daß eine rein funktionale Funktion eben NICHT "aufgerufen" wird, sondern einfach zeitlos da ist und Eingabe X auf Resultat Y mappt. Das war ja nun mal gar nichts, Leute. Closures bieten nun die Möglichkeit, den Gültigkeitsbereich solcher Variablen über dessen offizielles Ende hinaus auszudehnen. Offizielles Ende? Bei meiner zeitlosen Funktion, ja? Und das mit dem offiziellen Ende erinnert mich an irgendwelche Pascal-Kurse, wo die Leute "Gültigkeitsbereiche" paukten, anstatt zu verstehen, was der Unterschied zwischen einer stacklokalen und einer globalen Variable ist. Und so geht das weiter. Effektive Abschreckung. --88.74.184.93 09:23, 9. Dez. 2009 (CET)[Beantworten]

hi! ich fang mal von oben an. zuerst, wie würdest du den kontext, in dem eine funktion definiert wurde nennen? "aufruf" ist tatsächlich unsauber, aber es muß sich überhaupt nicht um eine pure, seiteneffektlose funktion im mathamatischen sinne handeln. das "offizielle ende" ist tricky, wir verstehen wohl beide was gemeint ist, aber mir fiele keine bessere formulierung ein. -- 11:44, 9. Dez. 2009 (CET)[Beantworten]
Dazu müßte ich erstmal wissen, was ein Closure genau ist. Ich kann nur sagen, daß Definitionskontext alles und jedes sein könnte. Kontext ist wohl nur ein anderes Wort für State, ich meine, offene Filedescriptoren, aktuelle Hintergrundfarbe und sowas gehört ja hier wohl nicht dazu, um mal abstruse Beispiele an den Haaren herzuzerren? Das offizielle Ende.. wie gesagt, wichtiger als die Regelwerke für die Scopes sind meistens, was damit erreicht werden soll. -- Paß mal auf. Ich habe meinetwegen einen Wert foobar. Jetzt baue ich eine anonyme Funktion, die foobar auf einen Wert draufaddiert, und verwende sie woanders weiter. Ist das ein Closure? Ist das die Idee eines Closures? Der "Kontext" wäre hier foobar. Nur finde ich es viel leichter zu verstehen, eine anonyme Funktion aus dem Parameter foobar zu bauen, als diesen als Kontext zu bezeichnen. --88.74.131.129 13:15, 9. Dez. 2009 (CET)[Beantworten]

Ich schreib doch noch mal noch mehr dazu. Also, nehmen wir an, ich akzeptiere, daß mir keine systematische Erklärung geboten wird, sondern versucht wird, mit Details von einem "Laufzeitsystem" rumzuhantieren. Gibt ja auch nicht rein funktionale Sprachen, und die Praxis ist immer wichtig. Also gut. Mit einer "Closure" kann ich also Variablen länger leben lassen als sie eigentlich laut Scope leben. Ich hab das Laufzeitsystem überlistet, gucke mal da, eine geisterhafte Globalvariable!... Äh, MOMENT MAL. Dafür sind Closures gut? Das meinen die Leute, wenn sie von einer Sprache sagen, die ist toll, weil sie Closures unterstützt? (Wer nicht weiß, was das ist, ruft eure Seite auf!) Daß man das Laufzeitsystem (bzw. den Scope) bescheißen kann? Ja nee ist klar. Oder daß man geisterhafte Globals haben kann? HALLO, jemand zu Hause? Globals kann ich in jeder nicht-verseuchten Sprache haben, sogar Java hat einen verwirrenden Mechanismus eingebaut, der nichts anderes ist. --88.74.128.249 10:06, 9. Dez. 2009 (CET)[Beantworten]

überlistet wird da niemand, lediglich die definition, welche variablen sichtbar sind ist eine andere. in C eben globale und stacklokale variablen, mit (lexikalischen) closures alle die im selben oder rekursiv umschließenden codeblock definiert wurden. "geisterhaft" könnte man das wohl tatsächlich nennen. es handelt sich aber nicht um globale variablen, zwei closures die in zwei aufrufen einer funktion erstellt wurden enthalten unterschiedliche variablen. meintest du mit dem verwirrendem mechanismus static fields? die haben damit nichts zu tun. wohl aber inner classes, die umschließen tatsächlich variablen des umgebenden scopes. allerdings read-only. -- 11:44, 9. Dez. 2009 (CET)[Beantworten]
Nee, wozu hat man denn die ganzen Scopes? Ich finde das generell keine gute Idee, sich hinterrücks über solche Mechanismen ins Bein zu schießen, insbesondere wenn der Wert schreibbar ist. Dann ist es nämlich nicht nur eine harmlose anonyme pure Funktion... (Die Variablen sind übrigens meistens nicht sichtbar, weil es sie schlicht nicht gibt, z.B. weil der Stackframe weg ist.)
es handelt sich aber nicht um globale variablen, zwei closures die in zwei aufrufen einer funktion erstellt wurden enthalten unterschiedliche variablen. Ja klar, das sind dann eben zwei verschiedene globale Variablen, ist ja gleich viel besser :) Es sind übrigens zwingend globale V., wenn sie auch noch schreibbar sind (möglicherweise weicht mein Sprachgebrauch hier ab, für mich ist die "Sichtbarkeit" syntaktischer Zucker).

Java: Hab ich schon halb verdrängt. Globals bekam man durch sogenannte inner classes in einer großen "Programm"-Klasse nach meinen Notizen. Globale Funktionen, also nicht-Methoden, heißen class methods. Ja, wirklich, Nicht-Methoden heißen Methoden, und sie können nicht auf die Klassenvariablen zugreifen (es braucht ja noch gar kein Objekt instanziiert zu sein). --88.74.131.129 13:15, 9. Dez. 2009 (CET)[Beantworten]

Wie wärs mit Übersetzen von wikipedia.org[Quelltext bearbeiten]

...dort findet sich nämlich eine vernünftige und viel klarere Definition von Closures. Und der Zusammenhang mit anonymen Klassen ist dort auch gut geklärt. Was meint Ihr? Wenn es hier einige Positiv-Stimmen gibt, würde ich mich dazu bereiterklären, die Übersetzng zu machen. (nicht signierter Beitrag von Cyrano63 (Diskussion | Beiträge) 17:33, 30. Oktober 2010)

Tolle Idee!!! Am besten Du übersetzt ihn mal auf Deiner Benutzerseite (siehe dazu Wikipedia:Importwünsche um die History sicherzustellen), ergänzt ihn um etwaige brauchbare Abschnitte von hier und lässt dann von einem Administrator diesen Artikel durch Deinen ersetzen. Wennst Hilfe brauchst, unterstütze ich Dich gerne... --Sebastian.Dietrich 18:00, 30. Okt. 2010 (CEST)[Beantworten]

Ein Blick auf den englischen Artikel und die dortigen Beispiele[Quelltext bearbeiten]

Ich habe mir eben den englischen Artikel zu diesem Thema angesehen, was ich in letzter Zeit sehr oft tue, da die Artikel in der deutschen Wikipedia oft wenig ausführlich oder einfach unverständlich sind. Das kann auch daran liegen, das mir ein akademischer Hintergrund fehlt. Ich programmiere zum Spaß und habe mich in ende der 80er Jahre bewußt gegen ein Informatikstudium entschieden und habe Büroinformationselektronikerin gelernt, besonders wegen den größeren Praxisbezug. Was ich an Programmierkenntnissen benötigte, habe ich mir selbst erarbeitet. Da ich mir früher viel mit Turbo Pascal und später Delphi beschäftigt habe - gerade jetzt auch wieder in Form von FreePascal, war das Delphi-Beispiel im englischen Artikel für mich leicht verständlich. Aber was das ganze nun soll oder was daran nun so besonders ist, des es eine eigenen Namen bekommen hat, wird mir nicht klar: Für mich ist das nicht anderes als eine Funktion mit einer statischen Variable, die auch nach verlassen der Funktion ihren Wert behält und beim nächsten Aufruf der Funktion unverändert zur Verfügung steht. Mein (vielleicht falscher) Eindruck kann aber natürlich auch an dem von mir betrachteten Delphi-Beispiel liegen. -- CenTroniX 14:35, 27. Aug. 2011 (CEST)[Beantworten]

In VB.Net würde das so aussehen:

function Counter(optional InitValue as integer = 0) as integer
    'InitValue ist ein optionaler Parameter. Wird dieser nicht übergeben erhält er den Wert 0

    static Flag as boolean = true    'Flag = true 
    static C as integer              'die statische Zähler-Variable
   
    if Flag then                     'Ist Flag = true dann
        C = InitValue                'wird C mit den Wert von InitValue gesetzt
        Flag = false                 'Flag wird negiert, damit InitValue nur einmal auf C übertragen wird
    else
        Counter = C                  'Aktuellen Wert von C als Rückgabewert speichern
        C += 1                       'C wir um eins erhöht
    endif
end function


sub main()                           'Hauptprogramm
    Counter(0)                       'Counter wird mit dem Wert 0 Initialisiert, der Rückgabewert wird nicht verwertet

    for I=1 to 10                    'Schleife mit 10 Durchläufen
       console.writeline(Counter())  'Der Rückgabewert von Counter wird auf der Konsole ausgegeben
    next
end sub



Ausgabe auf der Konsole:

0
1
2
3
4
5
6
7
8
9


Früher, bevor die statischen Variablen eingeführt wurden, habe ich das mit zahlreichen und oft fehleranfälligen globalen Variablen gelöst. In Turbo Pascal habe ich dafür dann ein Settings-Record genutzt und ab Version 5.5 mit OOP ein Settings-Objekt mit Properties, das zudem sehr einfach auf einem Datenträger gespeichert werden konnte
-- CenTroniX 14:35, 27. Aug. 2011 (CEST)[Beantworten]

Statische Variablen in diesem Sinne sind nichts anderes als globale Variablen, die nur innerhalb der Funktion sichtbar sind.
Closures enthalten aber Daten, die nicht global sind. Du kannst sie dir als Objekte mit nur einer Methode vorstellen. (Siehe auch [1] und [2]) Und genau so, wie man mehrere Objekte einer Klasse haben kann (und die haben jeweils unterschiedliche Daten, auch wenn die Felder gleich heißen), kann man mit einem Stück Code, der mehrmals aufgerufen wird, mehrere Closures mit unterschiedlichen Daten erhalten. In den ganzen Counter-Beispielen kann man natürlich auch mehrere Counter erstellen, die unabhängig voneinander sind, und sich nicht in die Quere kommen. --Daniel5Ko 16:17, 27. Aug. 2011 (CEST)[Beantworten]
Ok, die Funktionsweise habe ich nun verstanden und interpretiere das o.g. Delphi-Beispiel auch anders. Aber wozu man das nun brauchen soll, ist mir noch nicht ganz klar. Hier würde ein Beispiel aus der Praxis sehr helfen. Aber ich werde mal eine Nacht darüber schlafen, das hat bei den [Delegaten von VB.Net] auch sehr geholfen. -- CenTroniX 16:47, 27. Aug. 2011 (CEST)[Beantworten]

Ich habe mich jetzt einfach mal daran gemacht ein (hoffentlich allgemeinverständliches) Beispiel in Pseudocode zu schreiben. Damit sind die restlichen Beispiele in wahllosen Lieblingssprachen überflüssig. --greip 14:59, 29. Apr. 2012 (CEST)[Beantworten]

Warum soll eine mal-eben-erfundene Lieblingssprache ohne Spezifikation oder sonstige Dokumentation, der man ziemlich treffsicher ansehen kann, dass sie aus JavaScript hervorging und lediglich ein paar Schlüsselworte wahllos mit deutschen Vokabeln ersetzt hat, sinnvoll sein? --Daniel5Ko (Diskussion) 03:09, 30. Apr. 2012 (CEST)[Beantworten]
Hast du einen Link zu einer Pseudocode Spezifikation? Ich fand, dass aus meinem Beispiel ganz gut die Funktionsweise von Closures hervorgeht (btw, selbst das Javascript-Beispiel ist dreimal länger) und es außerdem recht simpel ist. Außerdem kannst du gerne das Pseudocode-Beispiel verändern, um es sinvoller zu machen. --greip 10:02, 30. Apr. 2012 (CEST)[Beantworten]
Mir ist keine solche Spezifikation bekannt. Je nachdem, welche Definitionen man benutzt (etwa: für eine "echte" Programmiersprache gibt es Interpreter; Programme in einer echten Programmiersprache gelten nie als Pseudo-Code; eine Spezifikation beschreibt eine Sprache genau genug, dass unterschiedliche Interpreter, die anhand der Spez. geschrieben sind, gleichen Programmen gleiche Bedeutung verleihen ), kann es auch sein, dass eine solche Spezifikation beweisbar nicht existiert. --Daniel5Ko (Diskussion) 14:04, 30. Apr. 2012 (CEST)[Beantworten]
Etwas abgeändert, um nicht mehr ganz so JavasScript-fixiert zu sein... --greip 14:18, 2. Mai 2012 (CEST)[Beantworten]

Der Pseudocode führt zwar ein Beispiel eines Closures aus, ist aber nicht sehr hilfreich, da der entstandene Vorteil nicht deutlich wird. Ein treffenderes Beispiel wäre hier hilfreich. --Nightfly85 | Disk 14:34, 2. Mai 2012 (CEST)[Beantworten]

Es wäre meine Ansicht nach zudem von Vorteil die Vorteile und Gründe für die Nutzung von Closures mal abstrahiert von irgendwelchen Beispielen im Artikel zu erwähnen -- am besten in einem eigenen Abschnitt. Dann kann man in einem Beispiel auch Bezug darauf nehmen. Deshalb mal crodsourcing: Was sind die Vorteile von Closures?

  • Kapselung
  • Ein static-Ersatz
  • ???

--greip 20:20, 3. Mai 2012 (CEST)[Beantworten]

Ganz klar: Jedes mal, wenn eine Problembeschreibung eine Lösung mit Closures nahelegt, ist es von Vorteil, wenn man Closures zur Verfügung hat! Denn wenn man keine hat, muss man sie mit Boilerplate-Code und ggf. unter Zumüllung eines Namensraumes nachbauen. (Stichwort: Objekte als poor man's Closures; diverse GoF-Patterns).
Nach den Vorteilen von Closures zu fragen ist ungefähr analog dazu, nach den Vorteilen von lokalen Variablen oder denen der Möglichkeit, Funktionen rekursiv zu formulieren, zu fragen. Wenn es die einfachste, natürlichste und übersichtlichste (oder auch erstmal nur naheliegendste) Ausdrucksweise ist, sowas zu benutzen, ist es äußerst schlecht, sowas nicht direkt benutzen zu können, sondern nachbauen zu müssen.
"Kapselung" ist nur ein Vorteil von Closures, wenn Kapselung an sich ein Vorteil ist, und kein Modulsystem oder Klassen oder ähnliches vorhandenen ist.
"static-Ersatz" ist nur ein Vorteil von Closures, wenn static-Variablen (ich schätze mal, du meinst im C-Sinn für lokale Variablen mit static-Modifier) einen Vorteil haben und Closures überhaupt ein static-Ersatz sind. --Daniel5Ko (Diskussion) 00:10, 4. Mai 2012 (CEST)[Beantworten]
Überlebensmaßnahmen sind auch nur von Vorteil, wenn man tatsächlich nicht sterben will und sie überhaupt das Überleben sichern! ;) Willst du nicht selbst Stellung nehmen bzw. eigene Vorschläge einbringen?
Welche GoF-Patterns meinst du explizit? (Das wäre doch mal eine schöne Bereicherung für den Artikel!) --greip 16:17, 5. Mai 2012 (CEST)[Beantworten]
Mögliche GoF-Patterns: Zustand (Entwurfsmuster), Strategie (Entwurfsmuster), Kommando (Entwurfsmuster), Stellvertreter (Entwurfsmuster), Abstrakte Fabrik. Die Objekte, um deren Austauschbarkeit es geht, und die ggf. noch ein bisschen Zustand haben, sind da eigentlich immer im Wesentlichen durch Closures realisierbar.
Wie dem auch sei, du fragtest nach "Vorteilen" von Closures, ich hab' versucht, darzulegen, dass das 'ne komische Frage ist. Vielleicht hilft eine etwas überzogene Analogie: Was hat die natürliche Zahl 12 denn so für Vorteile? Falls dir keine sinnvolle Antwort einfällt: fällt dir spontan eine sinnvolle Antwort darauf ein, warum eine Programmiersprache, die aus fadenscheinigen Gründen das Sprechen über 12 verbietet, seltsam ist? --Daniel5Ko (Diskussion) 02:35, 6. Mai 2012 (CEST)[Beantworten]
Allerdings ist 12 ein Teil der Menge der natürlichen Zahlen. Closures sind einfach nur eine Eigenschaft einer Programmiersprache. Und als solche müssten sie doch auch konkrete Anwendungsfälle haben, oder? (Das mit den Vorteilen war mein Fehler... ;)) Ein Anwendungsfall ist Kapselung IMO auf jeden Fall, egal ob sich daraus ein Vorteil ergibt oder nicht. --greip 13:33, 6. Mai 2012 (CEST)[Beantworten]
Wie gesagt, ergeben sich die meisten Anwendungsfälle direkt aus Problemstellungen: es fallen einfach ein paar Übersetzungsschritte weg. Beispiele (mal in JavaScript):
1) Man schreibe eine (nur mäßig nützliche, aber das ist ja nur ein Beispiel) Funktion zur numerischen Approximation der Ableitung einer übergebenen Funktion.
function d(h) { return function (f) { return function(x) { return (f(x+h)-f(x))/h; };};}
2) Wir haben Funktionen, die asynchron irgendwas machen, und ihr Ergebnis nicht per return zurückgeben, sondern durch Aufruf eines übergebenen Callbacks. Will man nun mehrere solche asynchronen Aufrufe parallel und/oder sequentiell und mit Ergebnisabhängigkeiten kombinieren, lässt sich die Logik selbst in komplizierteren Fällen fast immer übersichtlich und an einer Stelle formulieren, wenn man denn Closures hat. Trotzdem mal bloß ein simples Beispiel:
function fetchManyParallel(addresses, cb) {
    var results = [];
    for(var i = 0; i < addresses.length; i++) {
        fetch(addresses[i], function(r) { 
            results.push(r);
            if(results.length == addresses.length) {
                cb(results);
            }
        });
    }
}
Irgendwie kurz gesagt: Man setzt Closures nicht zu dem Zweck ein, den Code zu verbessern, oder weil man gemerkt hat, dass man einen "typischen Fall" von Closure-Anwendung vor sich hat, sondern deshalb, weil das Problem danach ruft. --Daniel5Ko (Diskussion) 20:32, 6. Mai 2012 (CEST)[Beantworten]

Go Lang Bspw?[Quelltext bearbeiten]

Hi. Ich würde gerne mal das Bsp. für die Sprache Go hierfür sehen. Kennt jemand zufällig den Aufbau. Angeblich soll sie das ja können. Noch bin ich aber nicht fündig geworden. :-( 67.202.78.161 23:59, 26. Aug. 2012 (CEST)[Beantworten]


Letzter Edit: Korrekte Definition?[Quelltext bearbeiten]

Der letzte Edit stimmt mich nachdenklich. Dort wird gesagt „Erreicht wird dies durch zwei verschachtelte Funktionen - die Hauptfunktion wird mit einer weiteren Funktion „abgeschlossen“, die auf die Hauptfunktion zugreift.“. Ich kenne aber auch Closures, die nicht zwingend in einer anderen Funktion stehen müssen,siehe hier. --Nightfly | Disk 14:55, 8. Mai 2013 (CEST)[Beantworten]

Die übliche Vorgehensweise dürften zwei verschachtelte Funktionen sein, auch die Beispiele zielen darauf ab. Vielleicht "Erreicht wird dies beispielsweise durch zwei verschachtelte Funktionen..."? --Mocha (Diskussion) 09:39, 10. Mai 2013 (CEST)[Beantworten]
Wer sagt denn, welches die "übliche" Vorgehenswise ist? Eine Definition macht doch nur dann Sinn, wenn sie allgemein gültig ist. Es ist keine direkte Kritik an dich bzw. euch, ich möchte nur verstehen, warum ein Closure sich zwischen den Programmiersprachen so unterschiedlich verhält.. --Nightfly | Disk 12:13, 10. Mai 2013 (CEST)[Beantworten]
Üblich: So hat es in den 70ern begonnen. Mittlerweile kommen Closures auch in Sprachen vor, die nicht a priori dafür vorbereitet wurden, also in Sprachen, wo Funktionen nicht wie normale Variablen (bzw. Objekte) behandelt werden können ("Funktion höherer Ordnung"). Daher die Unterschiede. --Mocha (Diskussion) 22:47, 10. Mai 2013 (CEST)[Beantworten]

Closures in C[Quelltext bearbeiten]

Ist das von Interesse? Es scheint einige Beschreibungen im Internet zu geben, z.B.

--Bk1 168 (D) 01:03, 21. Jun. 2014 (CEST)[Beantworten]

Defekter Weblink[Quelltext bearbeiten]

GiftBot (Diskussion) 13:31, 2. Dez. 2015 (CET)[Beantworten]

Closure in Ada[Quelltext bearbeiten]

In Ada gibt es keine Closure, auch wenn der Einzelnachweis auf eine Abhandlung verweist, wo "Closure" in der Überschrift steht. Ada erlaubt es, (mit dem access-Attribut) typsicher einen Zeiger auf ein Objekt zu benutzen, das auf dem Stapel steht (lokale Variable). Dabei erfolgt eine Prüfung spätestens zur Laufzeit, die gewährleistet, dass die Variable, die den Zeiger aufnimmt, keine längere Lebensdauer hat als das Objekt auf das der Zeiger zeigt. Dasselbe gilt auch für einen Zeiger auf ein lokales Unterprogramm. Der Versuch, eine Closure zu machen, führt also zu einer Fehlermeldung. Ada stammt aus den 80er Jahren, als Computer noch viel langsamer waren. Daher wird großen Wert auf Effizienz gelegt und wegen der schnelleren Speicherverwaltung so viel wie möglich auf dem Stapel statt auf heap/pool gespeichert. Closures passen nicht zu dieser Philosophe. Bigben.in (Diskussion) 10:08, 12. Jan. 2017 (CET)[Beantworten]

with Text_IO; use Text_IO;
procedure clostest2 is

   type Proc_Ptr is access procedure;  
   my_ptr : Proc_Ptr;

   procedure inner_Procedure is

      anzahl : Integer := 0;
  
      procedure myTestClosure is
      begin
         anzahl := anzahl + 1;
         put("Der");
         put(Integer'image(anzahl));
         put(". Aufruf des Programms");
         new_line;
      end myTestClosure;
      
   begin
      my_ptr := myTestClosure'access;  -- setzt den Zeiger auf das innere Unterprogramm
      my_ptr.all;                      -- ruft das Programm 3x auf
      my_ptr.all;
      my_ptr.all;
   end inner_Procedure;  

begin
   inner_Procedure;
end clostest2;

Beim Versuch, dieses obige Programm zu übersetzen erhält man die Fehlermeldung:

clostest2.adb:21:17: subprogram must not be deeper than access type

, weil der Zeiger my_ptr (bzw. vor allem der Zeigertyp Proc_Ptr) außerhalb des Unterprogramms deklariert ist. Man sieht, dass der Compiler hier eine Dangling Reference zu verhindern weiß.

Zum Vergleich: Folgendes Programm funktioniert:

with Text_IO; use Text_IO;
procedure clostest is

   procedure inner_Procedure is

      type Proc_Ptr is access procedure;  
      my_ptr : Proc_Ptr;
      anzahl : Integer := 0;
  
      procedure myTestClosure is
      begin
         anzahl := anzahl + 1;
         put("Der");
         put(Integer'image(anzahl));
         put(". Aufruf des Programms");
         new_line;
      end myTestClosure;
      
   begin
      my_ptr := myTestClosure'access;  -- setzt den Zeiger auf das innere Unterprogramm
      my_ptr.all;                      -- ruft das Programm 3x auf
      my_ptr.all;
      my_ptr.all;
   end inner_Procedure;  

begin
   inner_Procedure;
end clostest;

Es gibt diesen Text aus:

  Der 1. Aufruf des Programms
  Der 2. Aufruf des Programms
  Der 3. Aufruf des Programms

Der einzige Unterschied zum vorherigen Programm ist, dass der Zeigertyp und die Zeigervariable dieselbe Lebensdauer haben wie das Unterprogramm, auf das gezeigt wird.


--Bigben.in (Diskussion) 16:25, 12. Aug. 2017 (CEST)[Beantworten]


Missverständlich[Quelltext bearbeiten]

Es wird auf eine Funktion essen verwiesen, die erst später definiert wird. Was ist die Funktion essen denn hier in diesem Kontext? Später wird essen auf mutterfunktion gesetzt. Demnach ist anzahl_kuchen innerhalb von mutterfunktion geschützt. Ist das hier die Aussage?

Vielleicht beschreibt man das eher so:

Eine Funktion soll angeben, wie viele Kuchen gegessen wurden und bei jedem Aufruf die Anzahl der gegessenen Kuchen um 1 erhöhen:

  funktion kindfunktion {
    setze anzahl_kuchen = 0
    setze  anzahl_kuchen = anzahl_kuchen + 1
    gib_aus 'Ich habe #{anzahl_kuchen} Kuchen gegessen'
  }

Würde man wie im Beispiel oben diese Anzahl jedoch in der Funktion speichern, so wäre die Ausgabe bei jedem Aufruf gleich Ich habe 1 Kuchen gegessen. Denn bei jedem Aufruf wird die Anzahl erst auf 0 gesetzt und dann um 1 erhöht. Man könnte daher die anzahl_kuchen außerhalb der Funktion als globale Variable speichern:

  setze anzahl_kuchen = 0
  funktion kindfunktion {
    setze  anzahl_kuchen = anzahl_kuchen + 1
    gib_aus 'Ich habe #{anzahl_kuchen} Kuchen gegessen'
  }

Dabei kann aber auch jede andere Funktion auf die anzahl_kuchen zugreifen und sie verändern. Um die anzahl_kuchen vor diesem Zugriff zu schützen, wird das alles durch eine weitere Funktion umschlossen bzw. eingeschlossen/ abgeschlossen. Darum heißt sie auch Closure-Funktion (hier als Mutterfunktion bezeichnet):

funktion mutterfunktion {
  setze anzahl_kuchen = 0
  funktion kindfunktion {
    setze  anzahl_kuchen = anzahl_kuchen + 1
    gib_aus 'Ich habe #{anzahl_kuchen} Kuchen gegessen'
  }
  gib_zurück kindfunktion
}

Die lokale Variable anzahl_kuchen kann jetzt nur noch durch den Aufruf der Mutterfunktion verändert werden:

setze essen = rufe_auf mutterfunktion
rufe_auf essen
rufe_auf essen
rufe_auf essen

In einer objektorientierten Sprache könnte der umschlossene Teil auch durch eine Klasse abgekapselt werden.(nicht signierter Beitrag von 2001:16b8:243:4f00:247e:d3fd:b104:8e13 (Diskussion) 19. Februar 2018)

Kongruenz der Beispiele[Quelltext bearbeiten]

Der Pseudo-Code ist natürlich schon mal eine gesunde Grundlage für Allgemeinverständlichkeit.

Die große Anzahl an Beispielen halte ich prinzipiell für außerordentlich gut, gerade da wo ein Leser viel Erfahrung mit imperativen und wenig mit funktionalen Programmiersprachen hat, ist es hilfreich ein Beispiel aus seiner "Muttersprache" vorzufinden, und dieses mit Pseudo-Code und anderen Sprachen vergleichen zu können. Aber hier ergibt sich mein Kritikpunkt: Die Beispiele sind vielfach inkongruent und wenig sinnvoll (Stichwort "Apfelkuchen"). Es wirkt so als hätte man die Beispiele aus dem Kapitel "Closure" des jeweiligen Programmierhandbuchs wahllos zusammen kopiert.

Wenn die vielen Beispiele sinnvoll sein sollen, dann müssten sie meiner Meinung nach alle den gleichen (simplen und sinnvollen) Algorithmus umsetzen. Zum Beispiel den aus dem Python Beispiel. (Dort sollte man allerdings dann auch artikel-fremdem Verständnis-Ballast vermeiden wie die Liste container mit nur einem Element, an deren Stelle es auch eine normale Variable tut!)

Und damit die übrigen Kritikpunkte bezüglich unbeleckterer Leserschaft und Überfrachtung etwas entschärft werden … Wieso nicht nur den Pseudo-Code als Beispiel bezeichnen und den Abschnitt in verschiedenen Sprachen mit "Vergleich der Closure in verschiedenen Programmiersprachen" überschreiben? Dann wissen sowohl Experten als auch Laien schon nach Lektüre des Inhaltsverzeichnisses, wo sie die jeweils gewünschten Informationen finden. --217.85.172.64 15:06, 23. Mai 2021 (CEST)[Beantworten]

Zu allen Punkten: Richtig, richtig, richtig. Gruß, Friz --2001:16B8:4646:6A00:D459:97DC:AEBE:3907 14:38, 25. Dez. 2021 (CET)[Beantworten]
Ich würde den Algo noch vereinfachen, indem schon inc den Zählerstand zurück gibt und get entfällt.
Der Grund für die 1-Element-Liste war vielleicht, dass eine einfache Variable ohne nonlocal-Deklaration nicht funktioniert:
def make_counter():
    hidden_state = 0
    def inc():
        nonlocal hidden_state # Sonst UnboundLocalError in nächster Zeile.
        hidden_state += 1
        return hidden_state
    return inc

count_males = make_counter()
count_females = make_counter()
...
Komplikationen dieser Art sind ein Grund, Beispiele in vielen Sprachen zu haben, aber eben immer das gleiche. Die Verletzung von WP:WWNI ist mir bewusst. --Rainald62 (Diskussion) 16:42, 6. Mai 2022 (CEST)[Beantworten]