See also ebooksgratis.com: no banners, no cookies, totally FREE.

CLASSICISTRANIERI HOME PAGE - YOUTUBE CHANNEL
Privacy Policy Cookie Policy Terms and Conditions
Closure – Wikipedia

Closure

aus Wikipedia, der freien Enzyklopädie

Dieser Artikel oder Abschnitt bedarf einer Überarbeitung. Näheres ist auf der Diskussionsseite angegeben. Hilf bitte mit, ihn zu verbessern, und entferne anschließend diese Markierung.

Als Closure oder Funktionsabschluss bezeichnet man eine Programmfunktion, die beim Aufruf ihren Definitionskontext reproduziert, selbst wenn dieser Kontext außerhalb der Funktion schon nicht mehr existiert. Closures „konservieren“ also ihren Kontext.

Closures sind ein Konzept das aus den funktionalen Programmiersprachen stammt, zum ersten mal in LISP auftrat und in seinem Dialekt Scheme zum ersten mal vollständig unterstützt wurde. Daraufhin wurde es auch in allen folgenden funktionalen Programmiersprachen (etwa Haskell, Ocaml) unterstützt.

Allerdings existieren auch nicht-funktionale Programmiersprachen, die diese Funktion unterstützen. Hier wären JavaScript, Smalltalk, Python, Lua, Ruby, Groovy und Perl zu nennen, das im Weiteren zur Veranschaulichung dient. Es gibt Vorschläge, nach denen die objektorientierte Programmiersprache Java ab JDK 7 Funktionsabschlüsse unterstützen soll (siehe Weblinks).

Der Kontext eines beliebigen Code-Fragments wird unter anderem durch die zur Verfügung stehenden Symbole bestimmt:

# pragma
use strict;

# function
sub function
 {
  # function vars
  my ($var1, $var2);
   
  # code
  ...
  
  if (<condition>)
   {
    # block vars
    my ($scopy1, $scopy2);
    
    # block code
    ...
   }
  
  # code
  ...
 }

Im oben gezeigten Beispiel sind die Variablen $var1 und $var2 an jeder Stelle der Funktion gültig und sichtbar, $scopy1 und $scopy2 jedoch nur innerhalb des Blocks, in dem sie definiert wurden. Beim Verlassen dieses Bereichs (ihres Gültigkeitsbereiches oder Scopes) werden sie zusammen mit dem verlassenen Block aufgeräumt („gehen“ out of scope) und sind anschließend unbekannt. Jeder weitere Zugriff wäre ein Fehler.

Closures bieten nun die Möglichkeit, den Gültigkeitsbereich solcher Variablen über dessen offizielles Ende hinaus auszudehnen. Dazu wird im Scope einfach eine Funktion definiert, die die betreffenden Variablen verwendet:

# pragma
use strict;

# function refs
my ($c1);

# function
sub function
 {
  # function vars
  my ($var1, $var2);
   
  # code
  ...
  
  if (<condition>)
   {
    # block vars
    my ($scopy1, $scopy2);
    
    # block code
    $scopy1=10;
    $scopy2=1000;
    
    # define a closure
    $c1=sub {print "Scopies: $scopy1, $scopy2.\n"};
   }
  
  # code
  ...
 }

Das Laufzeitsystem stellt jetzt beim Aufräumen des if-Blocks fest, dass noch Referenzen auf die Blockvariablen $scopy1 und $scopy2 bestehen – die weiter gültige Variable $c1 verweist auf eine anonyme Subroutine, die ihrerseits Verweise auf die Blockvariablen enthält. $scopy1 und $scopy2 bleiben deshalb mit ihren aktuellen Werten erhalten. Weil die Funktion auf diese Weise die Variablen konserviert, wird sie zur Closure.

Mit anderen Worten kann man auch nach dem Verlassen des eigentlichen Gültigkeitsbereichs der Variablen jederzeit den Aufruf $c1->() ausführen und wird im Ergebnis immer wieder die bei der Definition der Funktion gültigen Werte der Variablen angezeigt bekommen.

Ändern kann man diese Werte nicht mehr, da die Variablen außerhalb der Closure nicht mehr verfügbar sind. Das liegt aber vor allem an der Funktionsdefinition: natürlich hätte die Closure die Werte nicht nur ausgeben, sondern auch bearbeiten oder auch aufrufendem Code wieder per Referenz zur Verfügung stellen können. In der folgenden Variante werden beispielsweise Funktionen zum Inkrementieren und Dekrementieren eingeführt:

# pragma
use strict;

# function refs
my ($printer, $incrementor, $decrementor);

# function
sub function
 {
  # function vars
  my ($var1, $var2);
  
  # code
  # ...
  
  if (0==0)
   {
    # block vars
    my ($scopy1, $scopy2);
    
    # block code
    $scopy1=10;
    $scopy2=1000;
    
    # define closures
    $printer=sub {print "Scopies: $scopy1, $scopy2.\n"};
    $incrementor=sub {$scopy1++; $scopy2++;};
    $decrementor=sub {$scopy1--; $scopy2--;};
   }
  
  # code
  # ...
 }

# call the function
&function;
# use closures
$printer->();
$incrementor->();
$printer->();
$incrementor->();
$incrementor->();
$printer->();

Closures lassen sich also beispielsweise dazu verwenden, den Zugriff auf sensible Daten zu kapseln.

Folgend ein einfaches Beispiel für einen Zähler in Python, der ohne einen (benannten) Container auskommt, der den aktuellen Zählerstand speichert.

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

Das Closure wird dann auf die folgende Weise verwendet:

>>> i,g=closure()
>>> g()
0
>>> i()
>>> i()
>>> g()
2
>>> __counter
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name '__counter' is not defined

OCaml, als funktionnelle Sprache, erlaubt das in folgender Weise :

let counter, inc, reset =
  let n = ref 0 in
  (function () -> !n),         (* counter  *)
  (function () -> n:= !n + 1), (* incrementor *)
  (function () -> n:=0 )       (* reset  *)

jetzt ist dans counter wie folgt anwendbar :

# counter();;    (* ergibt 0 *)
# inc();;
# counter();;    (* ergibt 1 *)
# inc();inc();inc();;
# counter();;    (* ergibt 4 *)
# reset();;
# counter();;    (* ergibt 0 *)
# n;;            (* n ist gekapselt *)
Unbound value n

Statt einem Integer können natürlich auf diese Weise beliebige Objekte oder Variablen beliebiger Typen gekapselt werden.

[Bearbeiten] Literatur

[Bearbeiten] Weblinks


aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - en - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu -