Lexikalischer Scope - nächste Folge
Lexikalischer Scope - nächste Folge
am 20.10.2006 18:39:22 von Ferry Bolhar
Hallo,
folgendes Programm
use warnings;
use strict;
while (my $input = ) {
my $sum = abs $input;
print add() . "\n";
sub add {
return $sum + $sum;
}
}
Die Funktion add() wird im lexikalischen Scope der while-Schleife
deklariert, folglich sollte immer dasselbe (lexikalische) $sum angesprochen
werden.
Man bekommt beim Kompilieren auch keinen Fehler; gibt man nach dem
ersten Prompt z.B. 33 ein, wird auch richtig 66 ausgegeben und danch wieder
gepromptet. Nur dann kann man eingeben, was man will, man bekommt
weiterhin immer nur 66 zurück! Vor und nach dem Funktionsaufruf hat $sum
aber sehr wohl den eingegebenen Wert.
Also trotz des gleichen lexikalischen Scopes nicht dieselbe Variable???
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 20.10.2006 19:00:47 von Ingo Menger
Ferry Bolhar schrieb:
> Hallo,
>
> folgendes Programm
>
> use warnings;
> use strict;
>
> while (my $input =3D ) {
> my $sum =3D abs $input;
> print add() . "\n";
>
> sub add {
> return $sum + $sum;
> }
> }
>
> Die Funktion add() wird im lexikalischen Scope der while-Schleife
> deklariert, folglich sollte immer dasselbe (lexikalische) $sum angesproch=
en
> werden.
Ich wußte garnicht, daß diese Syntax geht.
Ist dann wohl ungefähr äquivalent zu
out $add;
...
$add =3D sub { $sum + $sum } unless defined $add;
man closure
Re: Lexikalischer Scope - nächste Folge
am 20.10.2006 19:34:48 von Frank Seitz
Ferry Bolhar wrote:
> use warnings;
> use strict;
>
> while (my $input = ) {
> my $sum = abs $input;
> print add() . "\n";
>
> sub add {
> return $sum + $sum;
> }
> }
>
> Die Funktion add() wird im lexikalischen Scope der while-Schleife
> deklariert, folglich sollte immer dasselbe (lexikalische) $sum angesprochen
> werden.
Falsch: Die Variable $sum geht am Ende des While-Blocks aus dem Scope,
womit ihre Lebenszeit endet. Beim nächsten Durchlauf gibt es
ein neues Exemplar. add() bindet nur die erste Instanz.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächsteFolge
am 20.10.2006 22:23:49 von hjp-usenet2
On 2006-10-20 16:39, Ferry Bolhar wrote:
> Hallo,
>
> folgendes Programm
>
> use warnings;
> use strict;
>
> while (my $input = ) {
> my $sum = abs $input;
> print add() . "\n";
>
> sub add {
> return $sum + $sum;
> }
> }
>
> Die Funktion add() wird im lexikalischen Scope der while-Schleife
> deklariert, folglich sollte immer dasselbe (lexikalische) $sum angesprochen
> werden.
>
> Man bekommt beim Kompilieren auch keinen Fehler; gibt man nach dem
> ersten Prompt z.B. 33 ein, wird auch richtig 66 ausgegeben und danch wieder
> gepromptet. Nur dann kann man eingeben, was man will, man bekommt
> weiterhin immer nur 66 zurück! Vor und nach dem Funktionsaufruf hat $sum
> aber sehr wohl den eingegebenen Wert.
>
> Also trotz des gleichen lexikalischen Scopes nicht dieselbe Variable???
So ist es. Beim ersten Schleifendurchlauf ist das von "my $sum" erzeugte
$sum und das in der sub add verwendete das gleiche. Beim zweiten
Durchlauf existiert aber noch eine Referenz auf das alte $sum (nämlich
in der sub, die ja wie alle subs global ist und nicht mit dem Verlassen
des Schleifenkörpers zerstört wird), daher erzeugt "my $sum" eine neue
Variable. $sum in der sub bezieht sich aber immer noch auf das alte
$sum. Beim dritten Durchlauf ist die im zweiten Durchlauf verwendete
unbenützt und kann recycelt werden. Das sieht man schön, wenn man sich
die Adressen ausgeben lässt:
#!/usr/bin/perl
use warnings;
use strict;
while (my $input = ) {
my $sum = abs $input;
print "\$sum is at ", \$sum, "\n";
print add() . "\n";
sub add {
print "\$sum is at ", \$sum, "\n";
return $sum + $sum;
}
}
yoyo:~/tmp 22:14 104% ./foo
12
$sum is at SCALAR(0x8164e7c)
$sum is at SCALAR(0x8164e7c)
24
13
$sum is at SCALAR(0x814d920)
$sum is at SCALAR(0x8164e7c)
24
14
$sum is at SCALAR(0x814d920)
$sum is at SCALAR(0x8164e7c)
24
15
$sum is at SCALAR(0x814d920)
$sum is at SCALAR(0x8164e7c)
24
Das wollte ich schon im alten Thread demonstrieren, indem ich die
Ãnderung
#!/usr/bin/perl
use warnings;
use strict;
while (my $input = ) {
my $sum = abs $input;
print "\$sum is at ", \$sum, "\n";
my $add = sub {
print "\$sum is at ", \$sum, "\n";
return $sum + $sum;
};
print &$add() . "\n";
}
vorschlug. Darauf ist aber IIRC keiner eingegangen.
hp
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächste Folge
am 20.10.2006 23:06:08 von Frank Seitz
Peter J. Holzer wrote:
> On 2006-10-20 16:39, Ferry Bolhar wrote:
>>
>>Also trotz des gleichen lexikalischen Scopes nicht dieselbe Variable???
>
> So ist es. Beim ersten Schleifendurchlauf ist das von "my $sum" erzeugte
> $sum und das in der sub add verwendete das gleiche. Beim zweiten
> Durchlauf existiert aber noch eine Referenz auf das alte $sum (nämlich
> in der sub, die ja wie alle subs global ist und nicht mit dem Verlassen
> des Schleifenkörpers zerstört wird), daher erzeugt "my $sum" eine neue
> Variable. $sum in der sub bezieht sich aber immer noch auf das alte
> $sum. Beim dritten Durchlauf ist die im zweiten Durchlauf verwendete
> unbenützt und kann recycelt werden.
Für die Logik der Sache ist es unerheblich, ob Perl intern Speicher
recycled. Logisch ist es bei jedem Durchlauf eine neue Variable.
Was Du schilderst sind Implementierungsdetails, auf die die
Programmierung keinen Bezug nehmen darf.
GrüÃe
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächsteFolge
am 21.10.2006 14:52:18 von hjp-usenet2
On 2006-10-20 21:06, Frank Seitz wrote:
> Peter J. Holzer wrote:
>> On 2006-10-20 16:39, Ferry Bolhar wrote:
>>>
>>>Also trotz des gleichen lexikalischen Scopes nicht dieselbe Variable???
>>
>> So ist es. Beim ersten Schleifendurchlauf ist das von "my $sum" erzeugte
>> $sum und das in der sub add verwendete das gleiche. Beim zweiten
>> Durchlauf existiert aber noch eine Referenz auf das alte $sum (nämlich
>> in der sub, die ja wie alle subs global ist und nicht mit dem Verlassen
>> des Schleifenkörpers zerstört wird), daher erzeugt "my $sum" eine neue
>> Variable. $sum in der sub bezieht sich aber immer noch auf das alte
>> $sum. Beim dritten Durchlauf ist die im zweiten Durchlauf verwendete
>> unbenützt und kann recycelt werden.
>
> Für die Logik der Sache ist es unerheblich, ob Perl intern Speicher
> recycled. Logisch ist es bei jedem Durchlauf eine neue Variable.
Danke, ich wollte das eigentlich noch dazuschreiben, habe es dann aber
unterlassen.
> Was Du schilderst sind Implementierungsdetails, auf die die
> Programmierung keinen Bezug nehmen darf.
Die Programmierung nicht, aber die Erklärung - sonst wäre die nächste
Frage sicher "warum ändert sich die Adresse nach dem zweiten Durchlauf
nicht mehr?" gewesen.
hp
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächste Folge
am 23.10.2006 09:07:39 von Ferry Bolhar
Frank Seitz:
> Falsch: Die Variable $sum geht am Ende des While-Blocks aus dem Scope,
> womit ihre Lebenszeit endet.
Ja, am _Ende_. Die Funktion add() ist aber _im_ Block
definiert und wird auch _innerhalb_ des Blocks aufgerufen.
> Beim nächsten Durchlauf gibt es
> ein neues Exemplar. add() bindet nur die erste Instanz.
Wo steht das?
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 23.10.2006 09:26:20 von Ferry Bolhar
Frank Seitz:
> Logisch ist es bei jedem Durchlauf eine neue Variable.
Nein, das ist nicht logisch, zumindest nicht, wenn man die
Definition "lexikalischer Scope" in perlsub heranzieht. Denn
dort steht sinngemäß: wird eine lexikalische Variable in
einem Schleifenkopf definiert, dann ist sie innerhalb des
gesamten Schleifenkörpers (und somit auch innerhalb
darin definierter Funktionen) sichtbar. Und für das erste
mal stimmt das ja auch. Wenn also, wie Peter schreibt,
für die Variable bei jedem Durchlauf der Schleife eine
neue Instanz angelegt wird, so wäre zu erwarten, dass das
auch für die Variable in der Funktion (die ja per Definition
_dieselbe_ lexikalische Variable ist, da sie sich im selben
Block befindet) zutrifft.
Ich dürfte da auf ein Verhalten gestoßen sein, dass in
einer ziemlichen Grauzone liegt - ich habe nirgendwo
in der Doku (auch nicht in den diversen O'Reilly Perl-
Büchern) etwas darüber gefunden, dass Variablen in
Funktionen beim ersten mal übernommen werden und
dann nicht mehr.
> Was Du schilderst sind Implementierungsdetails, auf die die
> Programmierung keinen Bezug nehmen darf.
Das ist richtig, aber es ist für das Verständnis hilfreicher.
Ich beginne jetzt zumindest mal zu verstehen, _was_
passiert, wenngleich ich immer noch nicht verstehe, _warum_
und das Verhalten für mich nicht nachvollziehbar ist.
Dennoch danke an Euch für die Antworten,
Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 23.10.2006 09:45:20 von Frank Seitz
Ferry Bolhar wrote:
> Frank Seitz:
>>
>>Falsch: Die Variable $sum geht am Ende des While-Blocks aus dem Scope,
>>womit ihre Lebenszeit endet.
>
> Ja, am _Ende_.
Wobei Ende hier das Ende jedes Schleifendurchlaufs meint,
nicht den Zeitpunkt des Verlassens der while-Schleife,
falls Du das annimmst.
> Die Funktion add() ist aber _im_ Block
> definiert und wird auch _innerhalb_ des Blocks aufgerufen.
Sonst würde add() die Variable nicht sehen. Ansonsten
macht die Definition einer Subroutine innerhalb eines Blocks
keinen Unterschied, die sind in Perl sowieso grundsätzlich global,
aber das ist ein anderer Punkt.
>>Beim nächsten Durchlauf gibt es
>>ein neues Exemplar. add() bindet nur die erste Instanz.
>
> Wo steht das?
In der Perl-Doku wüsste ich jetzt keine Stelle. Das ist
Informatik-Grundwissen. Stichworte: Scope und Lifetime von
Variablen.
Dass das Verhalten so abstrus erscheint, liegt nur
daran, dass Dein Code abstrus ist.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächste Folge
am 23.10.2006 10:20:55 von Frank Seitz
Ferry Bolhar wrote:
> Ich dürfte da auf ein Verhalten gestoßen sein, dass in
> einer ziemlichen Grauzone liegt - ich habe nirgendwo
> in der Doku (auch nicht in den diversen O'Reilly Perl-
> Büchern) etwas darüber gefunden, dass Variablen in
> Funktionen beim ersten mal übernommen werden und
> dann nicht mehr.
Weiteres wichtiges Stichwort in dem
Zusammenhang: Closure.
Wenn Du die drei genannten Stichwörter (Scope, Liftime
und Closure) nachliest und die betreffenden Konzepte
verstanden hast, wird Dir klar, warum das alles so ist.
Perl verhält sich da, so weit ich es überblicke,
absolut korrekt und sauber.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächsteFolge
am 23.10.2006 12:50:21 von hjp-usenet2
On 2006-10-23 07:26, Ferry Bolhar wrote:
> Frank Seitz:
>> Logisch ist es bei jedem Durchlauf eine neue Variable.
>
> Nein, das ist nicht logisch, zumindest nicht, wenn man die
> Definition "lexikalischer Scope" in perlsub heranzieht.
Frank meint mit "logisch" hier "konzeptionell", nicht "intuitiv
verständlich". "Logisch", d.h., von einem abstrakten Standpunkt aus, ist
es jedesmal eine neue Variable. Der Perl-Interpreter optimiert aber die
Folge "alte Variable freigeben, neue Variable erzeugen" raus, deshalb
ist es praktisch die gleiche Variable, wenn sie freigegeben hätte
werden können (d.h., keine Referenz mehr darauf existierte).
Das ist ähnlich wie wenn Du in C ein
p = malloc(n);
free(p);
p = malloc(n);
machst. Vom Standpunkt der Sprachdefinition von C aus, bekommst Du einen
anderen Speicherbereich und auf den alten kannst Du nicht mehr
zugreifen. Je nachdem, wie free und malloc implementiert sind (und was
Du vorher gemacht hast), kann es aber durchaus sein, dass Du den
gleichen Speicherbereich wieder bekommst.
> Denn dort steht sinngemäÃ: wird eine lexikalische Variable in einem
> Schleifenkopf definiert, dann ist sie innerhalb des gesamten
> Schleifenkörpers (und somit auch innerhalb darin definierter
> Funktionen) sichtbar. Und für das erste mal stimmt das ja auch. Wenn
> also, wie Peter schreibt, für die Variable bei jedem Durchlauf der
> Schleife eine neue Instanz angelegt wird, so wäre zu erwarten, dass
> das auch für die Variable in der Funktion (die ja per Definition
> _dieselbe_ lexikalische Variable ist, da sie sich im selben Block
> befindet) zutrifft.
Nein, denn die Funktion wird ja nur *einmal* erzeugt, nicht bei jedem
Schleifendurchlauf neu (Wer kommt überhaupt auf die Idee, benannte
Funktionen innerhalb einer Schleife zu definieren ...). Deswegen habe
ich ja extra (schon zweimal) das Beispiel mit der anonymen sub gepostet
um zu zeigen, dass es funktioniert, weil die anonyme sub (konzeptionell,
nicht unbedingt praktisch) jedesmal eine andere ist. (Mir ist nicht
ganz klar, warum der Unterschied besteht - ich habe den Verdacht, dass
das eher eine Nebenwirkung als ein gewünschtes Verhalten ist).
> Ich dürfte da auf ein Verhalten gestoÃen sein, dass in
> einer ziemlichen Grauzone liegt - ich habe nirgendwo
> in der Doku (auch nicht in den diversen O'Reilly Perl-
> Büchern) etwas darüber gefunden, dass Variablen in
> Funktionen beim ersten mal übernommen werden und
> dann nicht mehr.
perldoc perlref:
Access to lexicals that change over type--like those in the "for" loop
above--only works with closures, not general subroutines.
("over type" scheint mir ein Tippfehler zu sein, soll wohl "over time" heiÃen).
hp
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächsteFolge
am 23.10.2006 13:01:26 von hjp-usenet2
On 2006-10-23 07:45, Frank Seitz wrote:
> Ferry Bolhar wrote:
>> Frank Seitz:
>>>Beim nächsten Durchlauf gibt es ein neues Exemplar. add() bindet nur
>>>die erste Instanz.
>>
>> Wo steht das?
>
> In der Perl-Doku wüsste ich jetzt keine Stelle. Das ist
> Informatik-Grundwissen. Stichworte: Scope und Lifetime von
> Variablen.
Die Konzepte sind Grundwissen. Wie die jetzt in Perl genau angewandt
werden, ist aber durchaus perl-spezifisch. Das Zeug ist m.E. auch alles
irgendwo dokumentiert (zumindest habe ich noch jedes "seltsame
Verhalten" irgendwo beschrieben gefunden), wenn auch etwas verstreut.
Was aber nicht verwunderlich ist, denn "was Ferry (oder hjp) seltsam
findet" ist kein allgemein brauchbares Kapitel einer Perl-Doku. Das
Verhalten ist bei Closures beschrieben wo es inhaltlich hinpasst (wenn
ich auf finde, dass Closures nach perlsub gehören und nicht nach
perlref, aber wenigstens ist in perlsub ein Hinweis auf die richtige
Stelle).
> Dass das Verhalten so abstrus erscheint, liegt nur
> daran, dass Dein Code abstrus ist.
Da kann ich nicht widersprechen :-).
hp
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächste Folge
am 23.10.2006 16:09:51 von Ferry Bolhar
Frank Seitz:
> Weiteres wichtiges Stichwort in dem
> Zusammenhang: Closure.
Hm, hm. Sind Closures nicht unbenannte Funktionen, die
erst zur Laufzeit erzeugt und nur über Codereferenzen
angesprochen werden? Das trifft auf meine add() Funktion
ja nicht zu.
Bei einer Closure wäre mir das Verhalten verständlicher.
> Wenn Du die drei genannten Stichwörter (Scope, Liftime
> und Closure) nachliest und die betreffenden Konzepte
> verstanden hast, wird Dir klar, warum das alles so ist.
Ich weiß nicht so recht...
> Perl verhält sich da, so weit ich es überblicke,
> absolut korrekt und sauber.
Das bezweifle ich ja nicht, ich wüßte nur gerne, _warum_
es sich so verhält. Aber wenn man von einem closure-
ähnlichem Verhalten ausgeht - der Wert einer lexikalischen
Variable wird in der Closure (= Funktion) einmal übernommen
und dann darin "eingefroren", wird es klarer.
Danke für deine Erklärung, und
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 23.10.2006 16:41:27 von Ferry Bolhar
Peter J. Holzer:
Vielen Dank für deine Erklärung!
> my $add = sub {
> print "\$sum is at ", \$sum, "\n";
> return $sum + $sum;
> };
>
> print &$add() . "\n";
> }
>
> vorschlug. Darauf ist aber IIRC keiner eingegangen.
Ich tu's jetzt: es geht auch mit
*add = sub {
..
};
print add()."\n";
dh., mit einer benannten Subroutine. Was meine Vermutung
bestätigt, dass das Besondere an einer Closure nicht deren
Anonymität ist, sondern der _Zeitpunkt_ (und damit das
lexikalische Verhalten), zu dem sie definiert wird.
sub add {$sum...}
ist eine _Deklaration_, die der _Compiler_ verarbeitet.
Es wird für $sum im Scratchpad _einmal_ ein Eintrag angelegt.
Wird - wie im Fall einer Schleife - dieser Eintrag geändert,
so muss eine Art "Clone" erfolgen - der neue Eintrag wird
für die Schleifenvariable verwendet, der alte (mit dem alten
Wert) weiterhin für die definierte Subroutine.
Ein
*add = sub{$sum...}; bzw.
$add = sub{$sum...};
ist eine _Laufzeit_anweisung. Hier werden die Werte von
außerhalb definierten lexikalischen Variablen zum Zeitpunkt
der Zuweisungsausführung übernommen. Geschieht dies
daher in einer Schleife, erfolgt die Übernahme bei jedem
Schleifendurchlauf mit den dann aktuellen Werten.
Das von dir zitierte
"Access to lexicals that change over type--like those in the "for" loop
above--only works with closures, not general subroutines."
wird damit klar, wenn man "general subroutines" mit "at compile-
time declared subroutines" bezeichnet.
Hab' ich es jetzt verstanden?
Schönen Dank für deine Geduld und Hilfe,
Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 23.10.2006 16:46:19 von Ferry Bolhar
Frank Seitz:
> Dass das Verhalten so abstrus erscheint, liegt nur
> daran, dass Dein Code abstrus ist.
Zugegeben. Aber ich finde, gerade durch solche Abstrusitäten
lernt man eine Sprache. Wenn man die einmal versteht, dann
bereitet einem "normaler" Code auch kein Kopfzerbrechen
mehr.
Und auf den bis 5.8.8 bestehenden Bug, dass ein
my $x;
our $x;
im selben Scope auch mit "use warnings" nicht reklamiert
wird, bin ich eben genau durch solchen "abstrusen" Code
gekommen.
Danke für deine Hilfe!
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächsteFolge
am 23.10.2006 16:53:37 von Daniel Fischer
Ferry Bolhar!
> Zugegeben. Aber ich finde, gerade durch solche Abstrusitäten
> lernt man eine Sprache. Wenn man die einmal versteht, dann
> bereitet einem "normaler" Code auch kein Kopfzerbrechen
> mehr.
Also, wenn ich ein reales Projekt bearbeite und bei einer schwer lesbaren
Codestelle denke "hey, das ist ja wie jenes abstruse Snippet von Ferry",
dann sagt das aber nichts gutes über das Projekt aus :-)
Gruß
Daniel
Re: Lexikalischer Scope - nächsteFolge
am 23.10.2006 17:33:26 von hjp-usenet2
On 2006-10-23 14:41, Ferry Bolhar wrote:
> Peter J. Holzer:
> Vielen Dank für deine Erklärung!
>
>> my $add = sub {
>> print "\$sum is at ", \$sum, "\n";
>> return $sum + $sum;
>> };
>>
>> print &$add() . "\n";
>> }
>>
>> vorschlug. Darauf ist aber IIRC keiner eingegangen.
>
> Ich tu's jetzt: es geht auch mit
>
> *add = sub {
> ..
> };
> print add()."\n";
>
> dh., mit einer benannten Subroutine.
Darüber kann man streiten. Aber Du hast den Unterschied zwischen
*add = sub {} und sub add {} im Folgenden dann eh klar gemacht.
> Was meine Vermutung bestätigt, dass das Besondere an einer Closure
> nicht deren Anonymität ist, sondern der _Zeitpunkt_ (und damit das
> lexikalische Verhalten), zu dem sie definiert wird.
Ja. Die Verwendung des Begriffs "Closure" in Perl für anonyme
Subroutinen ist ja auch nicht richtig. Im allgemeinen bezeichnet man als
Closure eine Funktion, die Zugriff auf (nicht-statische) Variablen in
einem umgebenden Scope hat. Das ist in Perl halt nur bei anonymen Subs
zuverlässig) der Fall (aus den von Dir angegeben Gründen), daher wird in
Perl "anonym" und "closure" gerne in einen Topf geworfen, obwohl das in
Wirklichkeit orthogonale Konzepte sind.
> Hab' ich es jetzt verstanden?
Ich denke schon.
hp
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächste Folge
am 23.10.2006 18:18:31 von Frank Seitz
Peter J. Holzer wrote:
> On 2006-10-23 14:41, Ferry Bolhar wrote:
>>
>>Was meine Vermutung bestätigt, dass das Besondere an einer Closure
>>nicht deren Anonymität ist, sondern der _Zeitpunkt_ (und damit das
>>lexikalische Verhalten), zu dem sie definiert wird.
>
> Ja. Die Verwendung des Begriffs "Closure" in Perl für anonyme
> Subroutinen ist ja auch nicht richtig. Im allgemeinen bezeichnet man als
> Closure eine Funktion, die Zugriff auf (nicht-statische) Variablen in
> einem umgebenden Scope hat. Das ist in Perl halt nur bei anonymen Subs
> zuverlässig) der Fall (aus den von Dir angegeben Gründen), daher wird in
> Perl "anonym" und "closure" gerne in einen Topf geworfen, obwohl das in
> Wirklichkeit orthogonale Konzepte sind.
Ich will's mal so ausdrücken:
Kennzeichnend für eine Closure ist, dass sie ihren
Variablenkontext zum Zeitpunkt ihrer Definition einfriert
und beim Aufruf reproduziert. Ob die betreffende Funktion
benannt oder unbenannt ist oder ob ihre Definition zur
Compilezeit oder zur Laufzeit erfolgt, ist durch den
Begriff nicht festgelegt.
GrüÃe
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächste Folge
am 23.10.2006 18:23:03 von Frank Seitz
Ferry Bolhar wrote:
> sub add {$sum...}
>
> ist eine _Deklaration_, die der _Compiler_ verarbeitet.
> Es wird für $sum im Scratchpad _einmal_ ein Eintrag angelegt.
> Wird - wie im Fall einer Schleife - dieser Eintrag geändert,
> so muss eine Art "Clone" erfolgen - der neue Eintrag wird
> für die Schleifenvariable verwendet, der alte (mit dem alten
> Wert) weiterhin für die definierte Subroutine.
Verstehe ich offen gestanden nicht.
> Ein
>
> *add = sub{$sum...}; bzw.
> $add = sub{$sum...};
>
> ist eine _Laufzeit_anweisung. Hier werden die Werte von
> außerhalb definierten lexikalischen Variablen zum Zeitpunkt
> der Zuweisungsausführung übernommen. Geschieht dies
> daher in einer Schleife, erfolgt die Übernahme bei jedem
> Schleifendurchlauf mit den dann aktuellen Werten.
Eine Closure bindet Variable, keine Werte.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächsteFolge
am 23.10.2006 19:17:06 von hjp-usenet2
On 2006-10-23 16:18, Frank Seitz wrote:
> Peter J. Holzer wrote:
>> On 2006-10-23 14:41, Ferry Bolhar wrote:
>> Ja. Die Verwendung des Begriffs "Closure" in Perl für anonyme
>> Subroutinen ist ja auch nicht richtig. Im allgemeinen bezeichnet man als
>> Closure eine Funktion, die Zugriff auf (nicht-statische) Variablen in
>> einem umgebenden Scope hat.
[...]
> Ich will's mal so ausdrücken:
> Kennzeichnend für eine Closure ist, dass sie ihren
> Variablenkontext zum Zeitpunkt ihrer Definition einfriert
> und beim Aufruf reproduziert. Ob die betreffende Funktion
> benannt oder unbenannt ist oder ob ihre Definition zur
> Compilezeit oder zur Laufzeit erfolgt, ist durch den
> Begriff nicht festgelegt.
Ja, danke. Das ist verständlicher als mein Versuch.
hp
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächste Folge
am 24.10.2006 08:24:53 von Ferry Bolhar
Daniel Fischer:
> Also, wenn ich ein reales Projekt bearbeite und bei einer schwer lesbaren
> Codestelle denke "hey, das ist ja wie jenes abstruse Snippet von Ferry",
> dann sagt das aber nichts gutes über das Projekt aus :-)
"Schwer lesbar" bzw. "abstrus" geben IMHO subjektive
Eindrücke wieder. Was für den einen "abstrus" ist, kann für
den anderen ganz normaler Code sein. Gerade Perl mit seinen
Sigils fällt da besonders gut rein - für jemanden, der Perl nicht
kennt, wirkt eine Anweisung wie
*{$package.'::'.$name} = \&{$subname};
schnell mal abstrus. Weiß man, was dahinter steckt, sieht
das Ganze schon viel freundlicher aus.
In "realem" Code (vor allem in Code, den andere auch lesen
müssen ;-) würde ich natürlich auch versuchen, auf "Abstrusitäten"
jeder Art zu verzichten (und tue das auch). Aber zum Lernen
und Ausprobieren sind sie gerade richtig, denn wenn man erst
mal verstanden hat, was in "abstrusem" Code abläuft, dann wird
man "normalen" Code umso besser verstehen.
Und letztlich führen gerade solche "Abstrusitäten" (dh., Code,
von dem vor allem die Entwickler von Software nicht erwartet
haben, dass er je programmiert wird, der aber dennoch
funktionieren müsste) sehr oft dazu, dass Fehler im Verhalten
von Programmen entdeckt werden.
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 24.10.2006 08:40:30 von Ferry Bolhar
Frank Seitz:
> Verstehe ich offen gestanden nicht.
Ich verstehe es so:
Beim ersten Aufruf wird - wie bei einer Closure - an add()
die Variable $sum weitergeben. Die Variable außerhalb und
innerhalb der Funktion enthalten denselben Wert - und auf
den wird durch Code an zwei Stellen zugegriffen, daher ist
der Referenzzähler der Variable (bzw. ihres Wertes) auf 2
gesetzt.
Beim nächsten Schleifendurchlauf soll einen neue Variable
angelegt werden. Da aber der Referenzzähler der alten
auf 2 gesetzt ist, dh., auch noch von anderem Code als von
der Schleife darauf zugegriffen wird (eben von der Funktion),
muss für die Schleife eine neue Variableninstanz (und das ab
dann bei jedem Schleifendurchlauf) erzeugt werden.
Vor bzw. beim ersten Schleifendurchlauf:
$sum RefCnt = 2 (ein $sum für Schleife und Funktion)
Ab dem zweiten Schleifendurchlauf:
$sum RefCnt = 1 ($sum für Schleife)
$sum RefCnt = 1 ($sum für Funktion)
Somit bleibt - ähnlich wie bei einer Closure - der Wert der
alten Variable "eingefroren".
>> ist eine _Laufzeit_anweisung. Hier werden die Werte von
>> außerhalb definierten lexikalischen Variablen zum Zeitpunkt
>> der Zuweisungsausführung übernommen. Geschieht dies
>> daher in einer Schleife, erfolgt die Übernahme bei jedem
>> Schleifendurchlauf mit den dann aktuellen Werten.
>
> Eine Closure bindet Variable, keine Werte.
Das habe ich auch nicht behauptet. Ich sprach von einer
_Übernahme_ der Werte von außerhalb definierten lexika-
lischen Variablen. Anders gesagt: der Vorgang des "Einfrierens"
läuft bei jedem Schleifendurchlauf mit den dann aktuellen
Variablen_Werten_ erneut ab.
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 24.10.2006 12:16:37 von Frank Seitz
Ferry Bolhar wrote:
[Refcounts]
Die Interna habe ich mir nicht angesehen, ich
stelle mir das aber auch so vor.
> Somit bleibt - ähnlich wie bei einer Closure - der Wert der
> alten Variable "eingefroren".
Wieso "ähnlich wie bei einer Closure"?
Das ist eine Closure.
>>Eine Closure bindet Variable, keine Werte.
>
> Das habe ich auch nicht behauptet. Ich sprach von einer
> _Übernahme_ der Werte von außerhalb definierten lexika-
> lischen Variablen. Anders gesagt: der Vorgang des "Einfrierens"
> läuft bei jedem Schleifendurchlauf mit den dann aktuellen
> Variablen_Werten_ erneut ab.
Es werden keine Werte übernommen, sondern die jeweilige
Variable wird - wie oben - an die generierte Funktion
(Closure) gebunden. Nur eben zur Laufzeit.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächste Folge
am 24.10.2006 12:23:16 von Frank Seitz
Ferry Bolhar wrote:
[Refcounts]
Die Interna habe ich mir nicht angesehen, ich
stelle mir das aber auch so vor.
> Somit bleibt - ähnlich wie bei einer Closure - der Wert der
> alten Variable "eingefroren".
Wieso "ähnlich wie bei einer Closure"?
Das ist eine Closure.
>>Eine Closure bindet Variable, keine Werte.
>
> Das habe ich auch nicht behauptet. Ich sprach von einer
> _Übernahme_ der Werte von außerhalb definierten lexika-
> lischen Variablen. Anders gesagt: der Vorgang des "Einfrierens"
> läuft bei jedem Schleifendurchlauf mit den dann aktuellen
> Variablen_Werten_ erneut ab.
Es werden keine Werte übernommen, sondern die jeweilige
Variable wird - wie oben - an die generierte Funktion
(Closure) gebunden. Nur eben zur Laufzeit.
Beachte: Bei jedem Schleifendurchlauf wird eine
neue Funktion generiert.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächsteFolge
am 24.10.2006 17:21:57 von hjp-usenet2
On 2006-10-24 06:24, Ferry Bolhar wrote:
> Daniel Fischer:
>> Also, wenn ich ein reales Projekt bearbeite und bei einer schwer
>> lesbaren Codestelle denke "hey, das ist ja wie jenes abstruse Snippet
>> von Ferry", dann sagt das aber nichts gutes über das Projekt aus :-)
>
> "Schwer lesbar" bzw. "abstrus" geben IMHO subjektive
> Eindrücke wieder. Was für den einen "abstrus" ist, kann für
> den anderen ganz normaler Code sein. Gerade Perl mit seinen
> Sigils fällt da besonders gut rein - für jemanden, der Perl nicht
> kennt, wirkt eine Anweisung wie
>
> *{$package.'::'.$name} = \&{$subname};
>
> schnell mal abstrus.
Das ist allerdings (meiner Meinung nach) nicht wegen der Sigils
"abstrus", sondern wegen der Manipulation der Symboltabelle zur
Laufzeit. Das ist manchmal durchaus sinnvoll, aber ein recht deftiger
Eingriff in das Laufzeitverhalten, das nicht irgendwo in der Mitte von
"harmlosem" Code versteckt werden sollte.
hp (der kein besonderer Freund von Sigils ist)
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächste Folge
am 24.10.2006 17:38:57 von Ingo Menger
Ferry Bolhar wrote:
> Gerade Perl mit seinen
> Sigils fällt da besonders gut rein - für jemanden, der Perl nicht
> kennt, wirkt eine Anweisung wie
>
> *{$package.'::'.$name} =3D \&{$subname};
>
> schnell mal abstrus.
Auch für jemanden, der Perl kennt.
> Weiß man, was dahinter steckt, sieht
> das Ganze schon viel freundlicher aus.
Ich möchte lieber gar nicht daran denken, was dahinter stecken könnte
...
> In "realem" Code (vor allem in Code, den andere auch lesen
> müssen ;-) würde ich natürlich auch versuchen, auf "Abstrusitäten"
> jeder Art zu verzichten (und tue das auch). Aber zum Lernen
> und Ausprobieren sind sie gerade richtig, denn wenn man erst
> mal verstanden hat, was in "abstrusem" Code abläuft, dann wird
> man "normalen" Code umso besser verstehen.
Naja, jedem Tierchen sein Pläsierchen, sag ich mal.
Ich persönlich habe, als ich zu der Stelle der perldoc kam, wo das
*-Zeug erklärt wird, beschlossen, daß ich so was nie brauchen werde
und deshalb nicht wissen muß.
Re: Lexikalischer Scope - nächsteFolge
am 24.10.2006 18:18:40 von Daniel Fischer
Ferry Bolhar!
> *{$package.'::'.$name} = \&{$subname};
>
> schnell mal abstrus. Weiß man, was dahinter steckt, sieht
> das Ganze schon viel freundlicher aus.
Code, der mit use strict nicht erlaubt ist, ist per definitionem abstrus.
Gruß
Daniel
Re: Lexikalischer Scope - nächste Folge
am 24.10.2006 19:56:57 von Slaven Rezic
Daniel Fischer writes:
> Ferry Bolhar!
>
> > *{$package.'::'.$name} = \&{$subname};
> >
> > schnell mal abstrus. Weiß man, was dahinter steckt, sieht
> > das Ganze schon viel freundlicher aus.
>
> Code, der mit use strict nicht erlaubt ist, ist per definitionem abstrus.
>
Wie generiert ihr denn ansonsten Getter/Setter?
Gruß,
Slaven
--
Slaven Rezic - slaven rezic de
Visualize Makefiles with GraphViz:
http://user.cs.tu-berlin.de/~eserte/src/perl/GraphViz-Makefi le/
Re: Lexikalischer Scope - nächste Folge
am 24.10.2006 20:03:34 von Frank Seitz
Daniel Fischer wrote:
> Ferry Bolhar!
>>
>>*{$package.'::'.$name} = \&{$subname};
>>
>>schnell mal abstrus. Weiß man, was dahinter steckt, sieht
>>das Ganze schon viel freundlicher aus.
>
> Code, der mit use strict nicht erlaubt ist, ist per definitionem abstrus.
Dann wäre Perls Importmechanismus abstrus und beinah sämtlicher
Code der auf Symboltabellen operiert. Ich finde es nicht
gut, dass use strict diesen Fall anmeckert und frage mich jedes
einzige Mal, was man sich dabei gedacht hat. Eine andere Form,
einen Zugriff auf einen Typeglob mit variablen Anteilen
(oben $package und $name) auszudrücken, wüsste ich nicht.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächste Folge
am 25.10.2006 13:00:22 von Ferry Bolhar
Frank Seitz:
>> Somit bleibt - ähnlich wie bei einer Closure - der Wert der
>> alten Variable "eingefroren".
>
> Wieso "ähnlich wie bei einer Closure"?
> Das ist eine Closure.
Nein. Eine Closure wird erst zur Laufzeit, wenn sie
zugewiesen wird, compiliert. In einem Konstrukt wie
while (my $input = ) {
my $sum = abs $input;
print add();
sub add {
$sum + $sum;
}
}
wird add() mit dem anderen Code gemeinsam kompiliert.
Daher war das Verhalten des "Einfrierens" der beim ersten
mal übergebenen Werte für mich ja auch nicht sofort nach-
vollziehbar. Peter hat das anhand der Referenzcounter
der Variablen erst (für mich :-) verständlich gemacht.
> Es werden keine Werte übernommen, sondern die jeweilige
> Variable wird - wie oben - an die generierte Funktion
> (Closure) gebunden. Nur eben zur Laufzeit.
Eben. Und in meinem (obigen) Code ist das nicht der Fall.
> Beachte: Bei jedem Schleifendurchlauf wird eine
> neue Funktion generiert.
Wobei ich annehmen würde, das Perl den kompilierten Code
cacht und beim "Neu generieren" nur die aktullen Werte der
lexikalischen Variable einsetzt (aus Effizienzgründen). Aber das
ist ein implementierungs-spezifisches Detail.
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 25.10.2006 14:05:04 von Christian Winter
Ferry Bolhar schrieb:
> Frank Seitz:
>
>>> Somit bleibt - ähnlich wie bei einer Closure - der Wert der
>>> alten Variable "eingefroren".
>> Wieso "ähnlich wie bei einer Closure"?
>> Das ist eine Closure.
>
> Nein. Eine Closure wird erst zur Laufzeit, wenn sie
> zugewiesen wird, compiliert.
Wo steht das?
-Christian
Re: Lexikalischer Scope - nächste Folge
am 25.10.2006 15:16:23 von Ferry Bolhar
Ich schrieb:
> folgendes Programm
[...]
Ein letzter Hinweis noch dazu:
wenn man den Code selbst ebenfalls als "sub" deklariert
und dann aufgerufen hätte, also
sub mainsub {
> while (my $input = ) {
> my $sum = abs $input;
> print add() . "\n";
>
> sub add {
> return $sum + $sum;
> }
> }
}
mainsub();
hätte Perl passenderweise die Meldung
Variable "$sum" will not stay shared...
ausgegeben, die das Verhalten um einiges klarer macht.
Eigenartigerweise tut es das nur, wenn der Code, der
die Unterfunktion (hier: add()) aufruft, selbst innerhalb
einer Funktion läuft. Bug oder Feature?
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 25.10.2006 15:48:41 von Frank Seitz
Ferry Bolhar wrote:
> Ein letzter Hinweis noch dazu:
>
> wenn man den Code selbst ebenfalls als "sub" deklariert
> und dann aufgerufen hätte, also
>
> sub mainsub {
> > while (my $input = ) {
> > my $sum = abs $input;
> > print add() . "\n";
> >
> > sub add {
> > return $sum + $sum;
> > }
> > }
> }
> mainsub();
>
> hätte Perl passenderweise die Meldung
>
> Variable "$sum" will not stay shared...
>
> ausgegeben, die das Verhalten um einiges klarer macht.
> Eigenartigerweise tut es das nur, wenn der Code, der
> die Unterfunktion (hier: add()) aufruft, selbst innerhalb
> einer Funktion läuft. Bug oder Feature?
Ich finde, es ist ein Feature, dass Perl das Problem (Stichwort:
abstruse Programmierung) zumindest innerhalb eines
Subroutine-Scope erkennt. Warum Perl es im Scope eines
while-Blocks nicht erkennt (oder nicht als Problem bewertet),
weiß ich nicht. Für mich ist es auf den ersten Blick dasselbe.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächste Folge
am 25.10.2006 16:03:26 von Frank Seitz
Ferry Bolhar wrote:
> Frank Seitz:
>>
>>Wieso "ähnlich wie bei einer Closure"?
>>Das ist eine Closure.
>
> Nein. Eine Closure wird erst zur Laufzeit, wenn sie
> zugewiesen wird, compiliert.
Mir stellt sich dieselbe Frage wie Christian Winter.
> while (my $input = ) {
> my $sum = abs $input;
> print add();
> sub add {
> $sum + $sum;
> }
> }
[...]
>>Es werden keine Werte übernommen, sondern die jeweilige
>>Variable wird an die generierte Funktion
>>(Closure) gebunden. Nur eben zur Laufzeit.
>
> Eben. Und in meinem (obigen) Code ist das nicht der Fall.
Doch. Der Mechanismus ist in beiden Fällen der gleiche.
>>Beachte: Bei jedem Schleifendurchlauf wird eine
>>neue Funktion generiert.
>
> Wobei ich annehmen würde, das Perl den kompilierten Code
> cacht und beim "Neu generieren" nur die aktullen Werte der
> lexikalischen Variable einsetzt (aus Effizienzgründen). Aber das
> ist ein implementierungs-spezifisches Detail.
Nein, das macht Perl mit Sicherheit nicht, denn dann
wäre es keine Closure.
Zum dritten Mal: Eine Closure bindet Variable, keine Werte.
Folgender Code macht es vielleicht klarer:
#!/usr/local/bin/perl -w
use strict;
my ($f,$ref);
{
my $n = 7;
$ref = \$n;
$f = sub { print "$n\n"};
$f->();
}
$$ref = 8;
$f->();
__END__
7
8
Dasselbe Spiel kannst Du auch mit Deinem ursprünglichen
add() machen.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächste Folge
am 25.10.2006 18:18:03 von Ferry Bolhar
Christian Winter:
>> Nein. Eine Closure wird erst zur Laufzeit, wenn sie
>> zugewiesen wird, compiliert.
>
> Wo steht das?
Na, wenn ich Frank richtig verstanden habe, in seinem
Posting:
> Beachte: Bei jedem Schleifendurchlauf wird eine
> neue Funktion generiert
Das kann ja wohl nur zur Laufzeit sein, oder?
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 25.10.2006 18:43:23 von Ferry Bolhar
Frank Seitz:
>> Nein. Eine Closure wird erst zur Laufzeit, wenn sie
>> zugewiesen wird, compiliert.
>
> Mir stellt sich dieselbe Frage wie Christian Winter.
Wie du selbst geschrieben hast:
>>>Beachte: Bei jedem Schleifendurchlauf wird eine
>>>neue Funktion generiert.
Da eine Schleife erst zur Laufzeit durchlaufen wird, wird
auch die entsprechende Funktion (Closure) erst dann
generiert, oder nicht?
> Doch. Der Mechanismus ist in beiden Fällen der gleiche.
Nicht ganz. Bei Closures wird eine lexikalische Variable
zur Laufzeit, wenn die Closure erzeugt und die Referenz
darauf an einen Skalar oder Typeglob zugewiesen wird,
mit dem dann gerade befindlichen Wert übernommen. Dass
man den, wie du weiter unten gezeigt hast, über eine Referenz
von "außen" ändern kann, ändert ja am Prinzip selber nichts.
OK, ich habe begriffen, was du zeigen wolltest, dass tat-
sächlich Variable, die man nachträglich über Referenzen
ändern kann, übernommen werden, und keine nicht ver-
ändernbaren Werte.
Eine benannte Funktion wird kompiliert, wenn das übrige
Programm kompiliert wird. Zu diesem Zeitpunkt haben
allfällige Variable ($sum in meinem Beispiel) ja noch keinen
Wert. Es wird also, um bei deiner Diktion zu bleiben, eine
"leere" Variable übernommen. Zur Laufzeit wird diese Variable
mit einem Wert versehen, der auch innerhalb der Funktion existiert.
Wird der lexikalischen Variable dann ein anderer Wert zugewiesen,
erfolgt praktisch ein "Splitting" - aus einer Variable sind plötzlich
zwei geworden, und Perl weist darauf ja auch mit seiner "will not
stay shared" Meldung (von der ich jetzt erst eigentlich richtig
begreife, was sie aussagt und unter welchen Umständen sie ausge-
geben wird) darauf hin. Und dieses "Splitting" gibt es bei Closures,
die erst zur Laufzeit kompiliert werden, nicht. _Das_ ist der
Unterschied.
Unklar ist mir noch - jetzt geht's wieder um Implementierungs-
fragen - woher Perl weiß, wann es dieses Splitting machen muss.
Möglicherweise hat es etwas mit dem auch bei Typeglobs ver-
wendeten FAKE-Mechanismus zu tun - wird ein Typeglob einem
Skalar zugewiesen
$x = *y;
so enthält der Skalar zunächst tatsächlich den Typeglob, der
Wert ist aber als FAKE gekennzeichnet. Wird später der
Typeglob im Skalar modifiziert, zB.
*{$x}{CODE} = sub {...};
so wird er vom ursprünglichen Typeglob abgespalten und es
entsteht ein neuer, veränderter Typeglob. FAKE ist hier also
etwas ähnliches wie ein Copy-On-Reference-Mechanismus
im Memory-Management - mehrere Komponenten greifen
auf ein- und denselben Speicher lesend zu; sobald eine
Komponente den Speicher modifiert, erhält sie vorher eine
private Kopie und kann auf den ursprünglichen, gemeinsamen
Speicher nicht mehr zugreifen.
Ich könnte mir denken, dass der Compiler beim Zugriff auf eine
lexikalische Variable, die in einem anderen (äußeren) Scope
deklariert wurde, diese ebenfalls als "FAKE" markiert.
Änderungen an einer Variable führen dann zu einem Splitting.
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächsteFolge
am 25.10.2006 19:15:09 von hjp-usenet2
On 2006-10-25 16:18, Ferry Bolhar wrote:
> Christian Winter:
>>> Nein. Eine Closure wird erst zur Laufzeit, wenn sie
>>> zugewiesen wird, compiliert.
>>
>> Wo steht das?
>
> Na, wenn ich Frank richtig verstanden habe, in seinem
> Posting:
>
>> Beachte: Bei jedem Schleifendurchlauf wird eine
>> neue Funktion generiert
>
> Das kann ja wohl nur zur Laufzeit sein, oder?
Ja, aber mit "generiert" meinte Frank vermutlich nicht "compiliert". Es
würde mich wundern, wenn die Funktion tatsächlich jedesmal neu
compiliert wird. Es wird wohl nur ein neuer Kontext für den bereits
compilierten Code erzeugt.
hp
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächste Folge
am 26.10.2006 07:38:00 von Christian Winter
Ferry Bolhar schrieb:
> Christian Winter:
>
>>> Nein. Eine Closure wird erst zur Laufzeit, wenn sie
>>> zugewiesen wird, compiliert.
>> Wo steht das?
>
> Na, wenn ich Frank richtig verstanden habe, in seinem
> Posting:
>
>> Beachte: Bei jedem Schleifendurchlauf wird eine
>> neue Funktion generiert
>
> Das kann ja wohl nur zur Laufzeit sein, oder?
Nope, das kann auch durch Kopieren erfolgen.
Viele Grüße
-Christian
Re: Lexikalischer Scope - nächste Folge
am 26.10.2006 09:52:08 von Frank Seitz
Ferry Bolhar wrote:
>>>Nein. Eine Closure wird erst zur Laufzeit, wenn sie
>>>zugewiesen wird, compiliert.
>
> Wie du selbst geschrieben hast:
>
>>>>Beachte: Bei jedem Schleifendurchlauf wird eine
>>>>neue Funktion generiert.
Generieren heißt nicht unbedingt kompilieren.
Und Closures entstehen nicht notwendig zur Laufzeit.
Denn es geht auch anders:
my $ref;
{
my $n = 7;
$ref = \$n;
sub f { print "$n\n"}
f;
}
$$ref = 8;
f;
__END__
7
8
f() ist hier eine Closure, die nicht zur Laufzeit,
sondern zur Compilezeit entsteht. Der Code
verhält sich exakt genauso wie dieser:
my ($f,$ref);
{
my $n = 7;
$ref = \$n;
$f = sub { print "$n\n"};
$f->();
}
$$ref = 8;
$f->();
__END__
7
8
> Wird der lexikalischen Variable dann ein anderer Wert zugewiesen,
> erfolgt praktisch ein "Splitting" - aus einer Variable sind plötzlich
> zwei geworden,
Wie kommst Du darauf? Bei der Zuweisung passiert garnichts.
Neue Variable entstehen, wenn ein Block betreten wird, und dieser
lokale Variable definiert. Dieselben Variablen werden
vernichtet, wenn der Block verlassen wird. Es sei denn, sie
werden anderweitig referenziert, z.B. durch eine Closure.
> und Perl weist darauf ja auch mit seiner "will not
> stay shared" Meldung (von der ich jetzt erst eigentlich richtig
> begreife, was sie aussagt und unter welchen Umständen sie ausge-
> geben wird) darauf hin.
Ich sehe das so: Perl weist mit der Meldung darauf hin,
dass wenn die äußere Variable erstmalig aus dem Scope gegangen ist,
die innere Subroutine nur noch mit dieser - für die Außenwelt
verstorbenen - Variable weiterarbeitet, also als Closure fungiert.
Das ist ziemlich sicher nicht das, was intendiert ist,
also gibt es die Meldung.
> Und dieses "Splitting" gibt es bei Closures,
> die erst zur Laufzeit kompiliert werden, nicht. _Das_ ist der
> Unterschied.
Bei einer dynamisch erzeugten Closure gibt es obigen Effekt
nicht, da die Funktionen ja immer passend zu den äußeren
Variableninstanzen erzeugt werden. Da geschieht also ziemlich sicher
das, was intendiert ist, also gibt es keine Meldung.
> Unklar ist mir noch - jetzt geht's wieder um Implementierungs-
> fragen - woher Perl weiß, wann es dieses Splitting machen muss.
[Perl-Interna]
Es ist sicherlich schwer, abstrakte Konzepte aus den
Perl-Interna herzuleiten, das kann leicht in die Irre führen.
Ich mache das deshalb garnicht. Teilweise denken und
argumentieren wir wohl auf unterschiedlichen Ebenen.
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächste Folge
am 26.10.2006 11:44:28 von Ingo Menger
Frank Seitz wrote:
> Ferry Bolhar wrote:
> > ausgegeben, die das Verhalten um einiges klarer macht.
> > Eigenartigerweise tut es das nur, wenn der Code, der
> > die Unterfunktion (hier: add()) aufruft, selbst innerhalb
> > einer Funktion läuft. Bug oder Feature?
>
> Ich finde, es ist ein Feature, dass Perl das Problem (Stichwort:
> abstruse Programmierung) zumindest innerhalb eines
> Subroutine-Scope erkennt. Warum Perl es im Scope eines
> while-Blocks nicht erkennt (oder nicht als Problem bewertet),
> weiß ich nicht. Für mich ist es auf den ersten Blick dasselbe.
Ack. Allerdings könnte man perl vorwerfen, daß er die Definition
einer benannten sub unterhalb der obersten Ebene warnungslos erlaubt
und somit Bolhar'sche Mißverständnisse geradezu provoziert. Ich kann
mir denken, daß das deshalb klaglos geht, weil ja auch eval "sub foo
{...}" gehen muß wenn es irgendwo in den Tiefen aufgerufen wird.
Re: Lexikalischer Scope - nächste Folge
am 26.10.2006 12:30:23 von Frank Seitz
Ingo Menger wrote:
> Frank Seitz wrote:
>>Ferry Bolhar wrote:
>>
>>>ausgegeben, die das Verhalten um einiges klarer macht.
>>>Eigenartigerweise tut es das nur, wenn der Code, der
>>>die Unterfunktion (hier: add()) aufruft, selbst innerhalb
>>>einer Funktion läuft. Bug oder Feature?
>>
>>Ich finde, es ist ein Feature, dass Perl das Problem (Stichwort:
>>abstruse Programmierung) zumindest innerhalb eines
>>Subroutine-Scope erkennt. Warum Perl es im Scope eines
>>while-Blocks nicht erkennt (oder nicht als Problem bewertet),
>>weiß ich nicht. Für mich ist es auf den ersten Blick dasselbe.
>
> Ack. Allerdings könnte man perl vorwerfen, daß er die Definition
> einer benannten sub unterhalb der obersten Ebene warnungslos erlaubt
> und somit Bolhar'sche Mißverständnisse geradezu provoziert. Ich kann
> mir denken, daß das deshalb klaglos geht, weil ja auch eval "sub foo
> {....}" gehen muß wenn es irgendwo in den Tiefen aufgerufen wird.
Sowas soll bitte auch gehen:
{
my $n = 1;
sub zaehl
{
return $n++;
}
}
Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
Re: Lexikalischer Scope - nächste Folge
am 26.10.2006 12:47:28 von Christian Winter
Frank Seitz schrieb:
> Ingo Menger wrote:
>> Frank Seitz wrote:
>>> Ferry Bolhar wrote:
>>>
>>>> ausgegeben, die das Verhalten um einiges klarer macht.
>>>> Eigenartigerweise tut es das nur, wenn der Code, der
>>>> die Unterfunktion (hier: add()) aufruft, selbst innerhalb
>>>> einer Funktion läuft. Bug oder Feature?
>>>
>>> Ich finde, es ist ein Feature, dass Perl das Problem (Stichwort:
>>> abstruse Programmierung) zumindest innerhalb eines
>>> Subroutine-Scope erkennt. Warum Perl es im Scope eines
>>> while-Blocks nicht erkennt (oder nicht als Problem bewertet),
>>> weiß ich nicht. Für mich ist es auf den ersten Blick dasselbe.
>>
>> Ack. Allerdings könnte man perl vorwerfen, daß er die Definition
>> einer benannten sub unterhalb der obersten Ebene warnungslos erlaubt
>> und somit Bolhar'sche Mißverständnisse geradezu provoziert. Ich kann
>> mir denken, daß das deshalb klaglos geht, weil ja auch eval "sub foo
>> {....}" gehen muß wenn es irgendwo in den Tiefen aufgerufen wird.
>
> Sowas soll bitte auch gehen:
>
> {
> my $n = 1;
> sub zaehl
> {
> return $n++;
> }
> }
Und geht ja auch. Ist ja sogar als Feature in perlsub aufgeführt
(=> Persistent Private Variables). In OO-Zeiten sollte sowas zwar
eigentlich unnötig sein, aber damit lassen sich immerhin einige
Aspekte der fehlenden Kapselung in Perl abfangen. Die Krux ist nur,
dass Perl hier nicht unterscheidet ob der Block standalone ist oder
zu einer Schleife gehört.
Das ganze ist eigentlich gar nicht so unlogisch, nur nach meinem
Empfinden unterdokumentiert. Ich vermisse schon ewig die
Möglichkeit, "perldoc perlscope" tippen und genau solche Frage-
stellungen nachlesen zu können.
-Christian
Re: Lexikalischer Scope - nächste Folge
am 27.10.2006 08:46:38 von Ferry Bolhar
Frank Seitz:
> Generieren heißt nicht unbedingt kompilieren.
Sondern (bezogen auf diese Situation)?
> Und Closures entstehen nicht notwendig zur Laufzeit.
> Denn es geht auch anders:
>
> my $ref;
> {
> my $n = 7;
> $ref = \$n;
> sub f { print "$n\n"}
> f;
> }
> $$ref = 8;
> f;
> __END__
> 7
> 8
>
> f() ist hier eine Closure, die nicht zur Laufzeit,
> sondern zur Compilezeit entsteht.
Das kommt darauf an, wie man "Closure" definiert. Das, was du
hier schreibst, steht jedenfalls im Widerspruch zu perlref:
"Access to lexicals that change over time--like those in the "for" loop
above--only works with closures, not general subroutines. In the gen-
eral case, then, named subroutines do not nest properly, although
anonymous ones do."
> Der Code
> verhält sich exakt genauso wie dieser:
Ja - aber wenn du den ganzen Code in eine eigene sub packst
und diese am Schluss aufrust, kommt wieder die "will not stay
shared" Meldung (die IMHO auch in deinem Beispiel kommen
müsste).
>> Wird der lexikalischen Variable dann ein anderer Wert zugewiesen,
>> erfolgt praktisch ein "Splitting" - aus einer Variable sind plötzlich
>> zwei geworden,
>
> Wie kommst Du darauf? Bei der Zuweisung passiert garnichts.
> Neue Variable entstehen, wenn ein Block betreten wird, und dieser
> lokale Variable definiert. Dieselben Variablen werden
> vernichtet, wenn der Block verlassen wird. Es sei denn, sie
> werden anderweitig referenziert, z.B. durch eine Closure.
Technisch gesehen erfolgt tatsächlich eine Art Splitting, weil die
lexkalische Variable zunächst nur im Scratchpad des äußeren
Blocks angelegt wird, innerhalb der Funktion wird nur eine Art
Verweis auf die äußere angelegt. Peter hat das mit Ausdumpen
der Variablen (und ihrer Speicheradressen) ja schon gezeigt:
zuerst ist es eine Variable mit einem Referenzcount von 2 (dh.,
sie wird von zwei Codestellen - außerhalb und innerhalb der
Funktion - referenziert). Nach der ersten Änderung der äußeren
Variable sind es plötzlich zwei unterschiedliche Variable (mit
unterschiedlichen Speicheradressen) mit einem Referenzcount
von je 1. Das habe ich mit "Splitting" gemeint, und das passiert
tatsächlich erst bei der zweiten Zuweisung außerhalb der
Funktion.
> > und Perl weist darauf ja auch mit seiner "will not
> > stay shared" Meldung (von der ich jetzt erst eigentlich richtig
> > begreife, was sie aussagt und unter welchen Umständen sie ausge-
> > geben wird) darauf hin.
>
> Ich sehe das so: Perl weist mit der Meldung darauf hin,
> dass wenn die äußere Variable erstmalig aus dem Scope gegangen ist,
> die innere Subroutine nur noch mit dieser - für die Außenwelt
> verstorbenen - Variable weiterarbeitet, also als Closure fungiert.
> Das ist ziemlich sicher nicht das, was intendiert ist,
^^^^^^^
Was ist das für ein Wort?
> Es ist sicherlich schwer, abstrakte Konzepte aus den
> Perl-Interna herzuleiten, das kann leicht in die Irre führen.
Es hilft (mir), diese abstrakten Konzepte besser zu verstehen.
Eine Art "reverse Engineering".
> Ich mache das deshalb garnicht. Teilweise denken und
> argumentieren wir wohl auf unterschiedlichen Ebenen.
Ja, da hast du recht, das wird's wohl sein.
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 27.10.2006 09:05:33 von Ferry Bolhar
Ingo Menger:
> Ack. Allerdings könnte man perl vorwerfen, daß er die Definition
> einer benannten sub unterhalb der obersten Ebene warnungslos erlaubt
> und somit Bolhar'sche Mißverständnisse geradezu provoziert.
Danke für die Blumen, falls das welche gewesen sein sollen...
Ich weiß nicht, ob das wirklich nur "meine" Mißverständnisse
sind - frag' mal in deiner Umgebung Freunde oder Kollegen,
die Perl gut kennen, ob sie dir erklären können, was die
"Variable will not stay shared" Meldung besagt und wann
und unter welchen Umständen genau sie auftritt (bzw. lass
sie dir Code schreiben können, durch den sie ausgegeben
wird). Ich habe das bei uns im Haus gemacht mit dem
Ergebnis, dass von 11 Befragten gerade mal einer (ziemlich)
genau erklären konnten, was die Meldung besagt.
Es mag allerdings sein, dass unter 11 Perl-Programmieren
sich zehn nicht weiter dafür interessieren - ich bin halt dann
der elfte, der ein solches Verhalten genauer hinterfragt...
Durch solche "Mißverständnisse" werden oft Fehler in
Code (und noch häufiger in Doku!) entdeckt, das kann
doch oft ganz nützlich sein, oder nicht?
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 27.10.2006 09:17:39 von Ferry Bolhar
Christian Winter:
>> Sowas soll bitte auch gehen:
>>
>> {
>> my $n = 1;
>> sub zaehl
>> {
>> return $n++;
>> }
>> }
>
> Und geht ja auch.
Ja? Was geht da? Was beweist (oder beweist nicht)
dieser Code? Die Funktion zaehl wird ja gar nicht
aufgerufen.
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 27.10.2006 11:10:46 von Ingo Menger
Ferry Bolhar wrote:
> Ingo Menger:
>
> > Ack. Allerdings könnte man perl vorwerfen, daß er die Definition
> > einer benannten sub unterhalb der obersten Ebene warnungslos erlaubt
> > und somit Bolhar'sche Mißverständnisse geradezu provoziert.
>
> Danke für die Blumen, falls das welche gewesen sein sollen...
Sicher. Ich empfinde Deine Beiträge immer als (teilweise auch
amüsante) Bereicherungen bzw. Anregungen eines faustischen Menschen,
der wissen will, was Perl im Innersten zusammenhält.
> Ich weiß nicht, ob das wirklich nur "meine" Mißverständnisse
> sind - frag' mal in deiner Umgebung Freunde oder Kollegen,
> die Perl gut kennen, ob sie dir erklären können, was die
> "Variable will not stay shared" Meldung besagt
Nun ist das (closures, etc.) aber auch ein sehr spezielles Gebiet von
Perl und Programmierung allgemein.
> Es mag allerdings sein, dass unter 11 Perl-Programmieren
> sich zehn nicht weiter dafür interessieren
Ich denke, daß unter 20 Programmierern (nicht nur Perl, sondern aller
Sprachen, die closures kennen) höchstens einer ist, der weiß, was
closures sind und wozu man sie braucht. Und dies selbst dann, wenn er
sie häufig benutzt, so hat man beispielsweise in der Java-Swing
Programmierung häufig welche.
Apropos, wenn ich das jetzt richtig verstanden habe, müßte Dein Code
genauso arbeiten, wenn Du statt der Subroutine folgendes geschrieben
hättest:
eval "sub add { ... }" unless defined &add;
Re: Lexikalischer Scope - nächste Folge
am 27.10.2006 11:53:16 von Christian Winter
Ferry Bolhar schrieb:
> Christian Winter:
>
>>> Sowas soll bitte auch gehen:
>>>
>>> {
>>> my $n = 1;
>>> sub zaehl
>>> {
>>> return $n++;
>>> }
>>> }
>> Und geht ja auch.
>
> Ja? Was geht da? Was beweist (oder beweist nicht)
> dieser Code? Die Funktion zaehl wird ja gar nicht
> aufgerufen.
Der Code beweist, dass eine in einem Block definierte Sub Zugriff
auf die Lexicalen Variablen des Scopes hat, und die auch innerhalb
der Sub verändert werden können (wenn man zaehl aufruft:).
Wogegen ein erneutes Betreten des Blocks eine neue Variable $n
in dessen Kontext generiert, während die Sub weiter ihre alte
Version mit sich rumschleift:
my $round = 0;
BOESERBLOCK: {
my $n = 1;
sub zaehl { print $n++,$/ };
}
zaehl();
zaehl();
goto BOESERBLOCK if( ++$round < 2 );
Viele Grüße
-Christian
Re: Re: Lexikalischer Scope - nächste Folge
am 27.10.2006 13:16:44 von Daniel Fischer
Ingo Menger!
> Ich denke, daß unter 20 Programmierern (nicht nur Perl, sondern aller
> Sprachen, die closures kennen) höchstens einer ist, der weiß, was
> closures sind und wozu man sie braucht.
Tu was dagegen! Schreib ein Buch! "Effizienter programmieren mit Closures"
oder sowas. Untertitel "Bequemer leben auch ohne Lisp". :-)
Das mit dem Verhältnis 1:19 stimmt so grob über den Daumen für die
Programmierer, die ich persönlich kenne, auch. Es gibt vermutlich (nicht
genug Kontakte vorhanden) Abweichungen in beide Richtungen, wo Closures
ein prominentes Feature der Sprache sind (oder wo es ein prominentes
Feature der Sprache gibt, das "closure" heißt, siehe LPC, hehe.) Oder bei
Java-Programmierern. Oder bei Web-Entwicklern, die nur Javascript kennen,
das ja auch Closures beherrscht...
Gruß
Daniel
Re: Re: Lexikalischer Scope - nächste Folge
am 27.10.2006 15:53:38 von Ferry Bolhar
Daniel Fischer:
>> Ich denke, daß unter 20 Programmierern (nicht nur Perl, sondern aller
>> Sprachen, die closures kennen) höchstens einer ist, der weiß, was
>> closures sind und wozu man sie braucht.
>
> Tu was dagegen! Schreib ein Buch! "Effizienter programmieren mit Closures"
> oder sowas. Untertitel "Bequemer leben auch ohne Lisp". :-)
Naja... ich hab' vor vielen Jahren mal, als Perl bei uns
"gesellschaftsfähig"
wurde, eine Abhandlung über Symboltabellen, Typeglobs und Referenzen
geschrieben, und habe sie dann später sogar noch ins POD-Format
gebracht ('perlglobtut'). Das könnte man ja für die Themen Scopes,
Lokalisierung und Closures u.U. auch tun.
Deine Idee ist also nicht neu, wenngleich ich noch nicht unter die Buch-
autoren gegangen bin...
Ich habe die Erfahrung gemacht, dass mittlerweile ohnehin das meiste
mehr oder weniger verborgen in der Perl-Doku vorhanden ist. Man
muss nur wissen, wo man danach sucht. Die Qualität der Doku gewinnt
mit jeder Perl-Version dazu, sonst hätte ich mir seinerzeit (da hatten wir
gerade eine der ersten 5-er Version - 5.001 oder so - eingesetzt) die
Arbeit nicht gemacht. Damals war es in der Doku um dieses Thema
noch ziemlich traurig bestellt. Heute findet man in perlsub, perlmod und
perlref schon das Meiste darüber, aber eben ziemlich "zerstückelt". Es
fehlt ein ganzheitliches Konzept, und ich denke, das ist wohl einer der
Gründe, dass O'Reilly mit der Veröffentlichung von Büchern über Perl
so weit kommen konnte...
> Oder bei Web-Entwicklern, die nur Javascript kennen, das ja auch
> Closures beherrscht...
Ja, obwohl ich ehrlich gesagt beim JavaScript-Programmieren noch
keinen Bereich gefunden habe, wo ich das gebraucht hätte.
PS: Falls Interesse an perlglobtut besteht, kann ich es gerne posten -
allerdings ist es mit einer Größe von 84 Blocks ziemlich groß.
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächste Folge
am 27.10.2006 16:15:55 von Ingo Menger
Daniel Fischer wrote:
> Ingo Menger!
>
> > Ich denke, daß unter 20 Programmierern (nicht nur Perl, sondern aller
> > Sprachen, die closures kennen) höchstens einer ist, der weiß, was
> > closures sind und wozu man sie braucht.
>
> Tu was dagegen! Schreib ein Buch! "Effizienter programmieren mit Closures"
Hehe. Du meinst, "Effizient programmieren, ineffizient ausführen"?
Re: Lexikalischer Scope - nächsteFolge
am 27.10.2006 17:07:38 von hjp-usenet2
On 2006-10-27 11:16, Daniel Fischer wrote:
> Ingo Menger!
>> Ich denke, daà unter 20 Programmierern (nicht nur Perl, sondern aller
>> Sprachen, die closures kennen) höchstens einer ist, der weiÃ, was
>> closures sind und wozu man sie braucht.
>
> Tu was dagegen! Schreib ein Buch! "Effizienter programmieren mit Closures"
> oder sowas. Untertitel "Bequemer leben auch ohne Lisp". :-)
Da ist dem Ingo leider der Mark Jason Dominus zuvorgekommen :-).
> Das mit dem Verhältnis 1:19 stimmt so grob über den Daumen für die
> Programmierer, die ich persönlich kenne, auch. Es gibt vermutlich (nicht
> genug Kontakte vorhanden) Abweichungen in beide Richtungen, wo Closures
> ein prominentes Feature der Sprache sind (oder wo es ein prominentes
> Feature der Sprache gibt, das "closure" heiÃt, siehe LPC, hehe.)
Pike (ein LPC-Nachfolger) wäre nach LISP und Perl auch die dritte
Sprache gewesen, die mir einfällt, wenn von Closures die Rede ist.
> Oder bei Java-Programmierern.
Java kennt Closures? Da schau her, hat sich ja was getan, seit ich mich
das letzte mal mit Java beschäftigt habe ...
hp
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächsteFolge
am 27.10.2006 18:29:11 von Daniel Fischer
Peter J. Holzer!
> Java kennt Closures? Da schau her, hat sich ja was getan, seit ich mich
> das letzte mal mit Java beschäftigt habe ...
Ja siehst Du, genau das hat der Ingo ja vermutet ;-)
In Java kann man sich mit einem Objekt behelfen. Im Grunde sind die ganzen
Interatoren usw. Closures. Der einzige Unterschied zwischen Java-Closures
und Closures in manchen anderen Sprachen ist, dass in Java Methoden keine
First-Class-Objekte sind und man deshalb eben immer das umgebende Objekt
übergeben muss. Man kann die ja sogar on the fly erzeugen, so wie z.B. in
Perl oder Python:
Runnable generateIntPrinter(final int x) {
return new Runnable() { public void run() { System.out.println(x); } };
}
Gruß
Daniel
Re: Lexikalischer Scope - nächste Folge
am 28.10.2006 02:14:58 von Slaven Rezic
"Ferry Bolhar" writes:
> Daniel Fischer:
>
[...]
>
> > Oder bei Web-Entwicklern, die nur Javascript kennen, das ja auch
> > Closures beherrscht...
>
> Ja, obwohl ich ehrlich gesagt beim JavaScript-Programmieren noch
> keinen Bereich gefunden habe, wo ich das gebraucht hätte.
>
Noch nie mit der GoogleMaps-API gearbeitet?
--
Slaven Rezic - slaven rezic de
BBBike - route planner for cyclists in Berlin
WWW version: http://www.bbbike.de
Perl/Tk version for Unix and Windows: http://bbbike.sourceforge.net
Re: Lexikalischer Scope - nächste Folge
am 30.10.2006 12:42:21 von Ingo Menger
Peter J. Holzer wrote:
> On 2006-10-27 11:16, Daniel Fischer wrote:
> > Ingo Menger!
> >> Ich denke, daß unter 20 Programmierern (nicht nur Perl, sondern aller
> >> Sprachen, die closures kennen) höchstens einer ist, der weiß, was
> >> closures sind und wozu man sie braucht.
> >
> > Tu was dagegen! Schreib ein Buch! "Effizienter programmieren mit Closur=
es"
> > oder sowas. Untertitel "Bequemer leben auch ohne Lisp". :-)
>
> Da ist dem Ingo leider der Mark Jason Dominus zuvorgekommen :-).
Wieso leider? MJD kann garantiert besser schreiben als ich. Und er
weiß auch mehr.
> > Oder bei Java-Programmierern.
>
> Java kennt Closures? Da schau her, hat sich ja was getan, seit ich mich
> das letzte mal mit Java beschäftigt habe ...
Das muß ziemlich lange her sein, denn "anonymous inner classes" (so
heißen closures dort) gibt es in Java schon recht lange.
Re: Lexikalischer Scope - nächste Folge
am 30.10.2006 13:15:08 von Christian Winter
Ferry Bolhar schrieb:
[...named closure im while-block...]
Als Update für alle, die im Thread mitgemischt oder -gelurkt haben:
Ich habe zu dem Thema auf p5p zwei Patches eingereicht, einer für
perlref, der schon in bleadperl eingeflossen ist, und einer für perlfaq,
der in der nächsten Zeit synchronisiert wird.
In perlref habe ich mir den vieldiskutierten Abschnitt "Access to
lexicals that change over type" vorgenommen:
------------------------------------------------------------ --------
Access to lexicals that change over time--like those in the C loop
above, basically aliases to elements from the surrounding lexical
scopes-- only works with anonymous subs, not with named subroutines.
Generally said, named subroutines do not nest properly and should only
be declared in the main package scope.
This is because named subroutines are created at compile time so their
lexical variables get assigned to the parent lexicals from the first
execution of the parent block. If a parent scope is entered a second
time, its lexicals are created again, while the nested subs still
reference the old ones.
Anonymous subroutines get to capture each time you execute the C
operator, as they are created on the fly. If you are accustomed to using
nested subroutines in other programming languages with their own private
variables, you'll have to work at it a bit in Perl. The intuitive
coding of this type of thing incurs mysterious warnings about "will not
stay shared" due to the reasons explained above.
For example, this won't work:
sub outer {
my $x = $_[0] + 35;
sub inner { return $x * 19 } # WRONG
return $x + inner();
}
A work-around is the following:
sub outer {
my $x = $_[0] + 35;
local *inner = sub { return $x * 19 };
return $x + inner();
}
Now inner() can only be called from within outer(), because of the
temporary assignments of the anonymous subroutine. But when it does,
it has normal access to the lexical variable $x from the scope of
outer() at the time outer is invoked.
------------------------------------------------------------ ---------
Ich denke, dass die wichtigen Punkte so ein wenig klarer rauskommen.
In perlfaq7 habe ich den Abschnitt "What is a closure?" geändert, der
in einigen Formulierungen definitiv falsch war:
------------------------------------------------------------ ---------
I is a computer science term with a precise but
hard-to-explain meaning. Usually, closures are implemented in Perl as
anonymous subroutines with lasting references to lexical variables
outside their own scopes. These lexicals magically refer to the
variables that were around when the subroutine was defined (deep
binding).
Closures are most often used in programming languages where you can
have the return value of a function be itself a function, as you can
in Perl. Note that some languages provide anonymous functions but are
not capable of providing proper closures: the Python language, for
example. For more information on closures, check out any textbook on
functional programming. Scheme is a language that not only supports
but encourages closures.
Here's a classic non-closure function-generating function:
sub add_function_generator {
return sub { shift() + shift() };
}
$add_sub = add_function_generator();
$sum = $add_sub->(4,5); # $sum is 9 now.
The anonymous subroutine returned by add_function_generator() isn't
technically a closure because it refers to no lexicals outside its own
scope. Using a closure gives you a I with some
customization slots left out to be filled later.
sub make_adder {
my $addpiece = shift;
return sub { shift() + $addpiece };
}
$f1 = make_adder(20);
$f2 = make_adder(555);
Now C<&$f1($n)> is always 20 plus whatever $n you pass in, whereas
C<&$f2($n)> is always 555 plus whatever $n you pass in. The $addpiece
in the closure sticks around.
Closures are often used for less esoteric purposes. For example, when
you want to pass in a bit of code into a function:
my $line;
timeout( 30, sub { $line = } );
Contrast this with the following make_adder() function, in which the
returned anonymous function contains a reference to a lexical variable
hypothetical timeout() function to access the lexical variable
$line back in its caller's scope.
Another use for a closure is to make a variable I to a
named subroutine, e.g. a counter that gets initialized at creation
time of the sub and can only be modified from within the sub.
This is sometimes used with a BEGIN block in package files to make
sure a variable doesn't get meddled with during the lifetime of the
package:
BEGIN {
my $id = 0;
sub next_id( ++$id );
}
This is discussed in more detail in L, see the entry on
I.
------------------------------------------------------------ ---------
Viele Grüße
-Christian
Re: Lexikalischer Scope - nächsteFolge
am 30.10.2006 14:07:54 von hjp-usenet2
On 2006-10-30 11:42, Ingo Menger wrote:
> Peter J. Holzer wrote:
>> On 2006-10-27 11:16, Daniel Fischer wrote:
>> >> Ich denke, daà unter 20 Programmierern (nicht nur Perl, sondern aller
>> >> Sprachen, die closures kennen) höchstens einer ist, der weiÃ, was
>> >> closures sind und wozu man sie braucht.
>> >
>> > Tu was dagegen! Schreib ein Buch! "Effizienter programmieren mit Closures"
>> > oder sowas. Untertitel "Bequemer leben auch ohne Lisp". :-)
>>
>> Da ist dem Ingo leider der Mark Jason Dominus zuvorgekommen :-).
>
> Wieso leider?
Man beachte den Fröhlichkeitsanzeiger.
> MJD kann garantiert besser schreiben als ich. Und er weià auch mehr.
Ganz ernsthaft: Ja, MJD kann gut schreiben, und "Higher Order Perl" ist
ein sehr empfehlenswertes Buch, das gut den Untertitel "Bequemer leben
auch ohne Lisp" tragen könnte - auch wenn man wohl einige Zeit braucht,
bis man die notwendigen Hirnverknotungen tatsächlich als "bequemer"
ansieht.
>> > Oder bei Java-Programmierern.
>>
>> Java kennt Closures? Da schau her, hat sich ja was getan, seit ich mich
>> das letzte mal mit Java beschäftigt habe ...
>
> Das muà ziemlich lange her sein, denn "anonymous inner classes" (so
> heiÃen closures dort) gibt es in Java schon recht lange.
Ca. 1999, wenn ich mich recht erinnere. An Inner Classes kann mich noch
vage erinnern, die waren damals recht neu. Mit Closures habe ich sie
irgendwie nicht in Verbindung gebracht. Erst als ich Daniels
Beispielcode gesehen habe, ist der Groschen gefallen.
hp
--
_ | Peter J. Holzer | > Wieso sollte man etwas erfinden was nicht
|_|_) | Sysadmin WSR | > ist?
| | | hjp@hjp.at | Was sonst wäre der Sinn des Erfindens?
__/ | http://www.hjp.at/ | -- P. Einstein u. V. Gringmuth in desd
Re: Lexikalischer Scope - nächste Folge
am 31.10.2006 09:21:27 von Ferry Bolhar
Christian Winter:
> Als Update für alle, die im Thread mitgemischt oder -gelurkt haben:
> Ich habe zu dem Thema auf p5p zwei Patches eingereicht, einer für
Wie hast du das gemacht?
> perlref, der schon in bleadperl eingeflossen ist,
Was ist "bleadperl"?
Vielen Dank jedenfalls für deine Mühe! Dadurch ist jetzt einiges
klarer - hätte es das schon vorher gegeben, hätte ich mir diesen
Thread sparen können...
LG, Ferry
--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at
Re: Lexikalischer Scope - nächsteFolge
am 31.10.2006 10:53:13 von martin
Ferry Bolhar wrote:
> Christian Winter:
>> Als Update f?r alle, die im Thread mitgemischt oder -gelurkt haben:
>> Ich habe zu dem Thema auf p5p zwei Patches eingereicht, einer f?r
>
> Wie hast du das gemacht?
Ich denke mal, er hat eine Nachricht in der Perl5-Porters Mailingliste
("p5p") veroeffentlicht.
>> perlref, der schon in bleadperl eingeflossen ist,
>
> Was ist "bleadperl"?
"The bleeding edge" - die aktuelle Entwicklungsversion von Perl aus dem
Resource Control System.
cu,
Martin
--
| Martin Vorlaender | OpenVMS rules!
VMS is today what | work: mv@pdv-systeme.de
Microsoft wants | http://www.pdv-systeme.de/users/martinv/
Windows NT 8.0 to be! | home: martin@radiogaga.harz.de