wann darf $_ nicht verwendet werden?????

wann darf $_ nicht verwendet werden?????

am 07.03.2006 13:01:58 von f.ballandt

Hallo Leute,

öfters bin ich schon auf die Nase gefallen mit kurzem Code.
z.B. geht:

...
while()
{
$daten.=$_;
chomp;
...

manchmal!!! schief (chomp stürzt ab).

mit:

while(my$az=)
{
$daten.=$az;
chomp($az);

gehts wieder.


while schleifen, die immer funktionierten, in denen gelegentlich kleine
Änderungen vorgenommen werden, laufen eines Tages nicht mehr. Als ob im
Schleifenkörper eine kritische Masse nicht überschritten werden darf,
damit sich $_ nicht vergißt?

Wer zaubert hier?

Gruß Frank

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 14:16:15 von Christian Lackas

* f.ballandt [2006-03-07]:

Hallo Frank,

> öfters bin ich schon auf die Nase gefallen mit kurzem Code.
> z.B. geht:
> while()
> {
> $daten.=$_;
> chomp;

bist du sicher, dass du erst die Daten in $_ kopieren willst, und dann
mögliche Zeilenenden in $_ (nicht in $daten) entfernen willst?
Normalerweise macht das das so rum:

while () { chomp; ... }

> manchmal!!! schief (chomp stürzt ab).

Was soll das heißen? Was heisst 'schiefgehen'? Was erwartest du was bei
welchem Input passieren soll und was passiert stattdestten.
Der Befehl 'chomp' kann grundsätzlich nicht abstützen. Was meinst du
damit? Deine Schleife wird beendet? Warum sollte das mit chomp
zusammenhängen?

> while schleifen, die immer funktionierten, in denen gelegentlich kleine
> Änderungen vorgenommen werden, laufen eines Tages nicht mehr. Als ob im
> Schleifenkörper eine kritische Masse nicht überschritten werden darf,
> damit sich $_ nicht vergißt?

Was du mit $_ machst, hat nichts damit zu tun, ob die Schleife
weiterläuft, oder nicht. Das liegt einzig am Status des Filehandles.

Falls du unter einem von CP/M abstammenden archaischen System arbeiten
solltest, dann schau dir doch mal 'binmode' an.

Gruß
Christian

--
Wirtschaftswissenschaft ist die einzige Disziplin, in der jedes Jahr auf
dieselben Fragen andere Antworten richtig sind.
(Danny Kaye, amerikan. Filmschauspieler, 1913-1987)
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 14:44:49 von f.ballandt

Christian Lackas schrieb:

> * f.ballandt [2006-03-07]:
>
> Hallo Frank,
>
>
>>öfters bin ich schon auf die Nase gefallen mit kurzem Code.
>>z.B. geht:
>> while()
>> {
>> $daten.=$_;
>> chomp;
>
>
> bist du sicher, dass du erst die Daten in $_ kopieren willst, und dann
> mögliche Zeilenenden in $_ (nicht in $daten) entfernen willst?

ja $_ brauche ich noch weiterhin


>>manchmal!!! schief (chomp stürzt ab).
>
>
> Was soll das heißen? Was heisst 'schiefgehen'? Was erwartest du was bei
> welchem Input passieren soll und was passiert stattdestten.

OSZI ist ein Handle auf eine auszulesende Textdatei. Nach chomp (letzte
im Debugger sichtbare Zeile) wird die sub und die davorliegende sub
vorzeitig verlassen. Mit der selben Datei, bei einem etwas anderem
Aufruf der sub in der das Ganze enthalten ist funktioniert es.



> Falls du unter einem von CP/M abstammenden archaischen System arbeiten
> solltest, dann schau dir doch mal 'binmode' an.
>
win2000, perl, v5.6.1 built for MSWin32-x86-multi-thread wie auch
perl, v5.8.6 built for cygwin-thread-multi-64int



> Gruß
> Christian
>

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 15:17:16 von Christian Lackas

* f.ballandt [2006-03-07]:

Hallo Frank,

> OSZI ist ein Handle auf eine auszulesende Textdatei.

und es ist auch garantiert, dass da nur Text und nichts anderes
drinsteht, z.B. EOF-Zeichen?

> Nach chomp (letzte im Debugger sichtbare Zeile) wird die sub und die
> davorliegende sub vorzeitig verlassen. Mit der selben Datei, bei einem
> etwas anderem Aufruf der sub in der das Ganze enthalten ist
> funktioniert es.

Dann zeig doch mal ein komplettes minimales Beispiel mit Eingabedaten,
die das ganze reproduziert. ich kann dir aber garantieren, dass es nicht
an der Verwendung von $_ oder chomp liegt.

Was für einen Debugger verwendest du? Zeig doch mal eine solche Session.

Gruß
Christian

--
Beliebtheit sollte kein Maßstab für die Wahl von Politikern sein. Wenn
es auf die Popularität ankäme, säßen Donald Duck und die Muppets längst
im Senat.
(Orson Welles, amerik. Schauspieler, Regisseur & Schriftsteller, 1915-85)

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 16:02:47 von f.ballandt

> Dann zeig doch mal ein komplettes minimales Beispiel


hab mich aufgerafft und der reihe nach die unwichtigen 1000
programmzeilen entfernt:

-----------------
ooo();
#ttt();
sub ttt
{
foreach (1,-1)
{
ooo();
}
}

sub ooo
{
open(OSZI,"< tmp.tmp") or die "Fehler beim lesen von tmp.tmp: $!";
my$daten;
while()
{
$daten.=$_;
}
close(OSZI);
print "file geschlossen";
}

------------------

das funktioniert, aber ttt() darf ich nicht aufrufen.
(Modification of a read-only value attempted at b.pl line 16(while()))

warum ??????


Frank

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 16:14:57 von Christian Lackas

* f.ballandt [2006-03-07]:

Hallo Frank,

> hab mich aufgerafft und der reihe nach die unwichtigen 1000
> programmzeilen entfernt:

das ist aber sehr zuvorkommend von dir.

> -----------------
> ooo();
> #ttt();
> sub ttt
> {
> foreach (1,-1)
> {
> ooo();
> }
> }
>
> sub ooo
> {
> open(OSZI,"< tmp.tmp") or die "Fehler beim lesen von tmp.tmp: $!";
> my$daten;
> while()
> {
> $daten.=$_;
> }
> close(OSZI);
> print "file geschlossen";
> }

Wenn ich das noch etwas einkürzen darf, dann ist dein elementares
Beispiel folgendes:

for (1) { $_ = 2 }

Und hier darf mal $_ nicht ändern, weil $_ in diesem Fall die Konstante
1 ist. Das Beispiel ändert sich auch nicht, wenn du es etwas abwandelst:

for (1) { $_ = }

Oder noch etwas näher an deinem 'minimalen' Beispiel

for (1) { while (defined $_ = ) { ... } }

Jedesmal wird versucht eine Konstant zu ändern (zu überschreiben).

> das funktioniert, aber ttt() darf ich nicht aufrufen.
> (Modification of a read-only value attempted at b.pl line 16(while()))

War das wirklich dein Problem? Warum hast du dann diese Fehlermeldung
nicht gleich angegeben? Die wäre deutlich hilfreicher gewesen als die
Umschreibung 'geht nicht' und 'chomp stürzt ab'.

Gruß
Christian

--
Auch eine Pechsträhne will gekämmt werden.
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 16:48:36 von f.ballandt

danke, muß ich morgen mal drüber nachdenken


>>das funktioniert, aber ttt() darf ich nicht aufrufen.
>>(Modification of a read-only value attempted at b.pl line 16(while()))
>
>
> War das wirklich dein Problem? Warum hast du dann diese Fehlermeldung
> nicht gleich angegeben?

die kam erst ohne 1000 zeilen dazwischen



Die wäre deutlich hilfreicher gewesen als die
> Umschreibung 'geht nicht' und 'chomp stürzt ab'.
>
> Gruß
> Christian
>

tschüß und feierabend frank

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 17:30:19 von frank

Christian Lackas wrote:

> Wenn ich das noch etwas einkürzen darf, dann ist dein elementares
> Beispiel folgendes:
>
> for (1) { $_ = 2 }
>
> Und hier darf mal $_ nicht ändern, weil $_ in diesem Fall die Konstante
> 1 ist. Das Beispiel ändert sich auch nicht, wenn du es etwas abwandelst:
>
> for (1) { $_ = }
>
> Oder noch etwas näher an deinem 'minimalen' Beispiel
>
> for (1) { while (defined $_ = ) { ... } }
>
> Jedesmal wird versucht eine Konstant zu ändern (zu überschreiben).

Hm, wie soll man dann Subroutinen schreiben, die eine Datei auslesen, so
dass man die Subroutine auch in einer Schleife aufrufen darf?

while (defined $line = ) { ... }

geht vermutlich, aber elegant ist das nicht. Wo steht eigentlich was
zum Scoping von Spezialvariablen wie $_?

Gruß, Frank
--
> ich wusste mal einen Befehl, der die Ausgabe auf stdout noch zusätzlich
> in eine Datei umlenken konnte... Bitte helft mir auf die Sprünge.
"kaffee" war es nicht.

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 18:31:38 von Bernd Schuler

Christian Lackas schrieb:
>
> Wenn ich das noch etwas einkürzen darf, dann ist dein elementares
> Beispiel folgendes:
>
> for (1) { $_ = 2 }
>
> Und hier darf mal $_ nicht ändern, weil $_ in diesem Fall die Konstante
> 1 ist. Das Beispiel ändert sich auch nicht, wenn du es etwas abwandelst:
>
> for (1) { $_ = }
>
> Oder noch etwas näher an deinem 'minimalen' Beispiel
>
> for (1) { while (defined $_ = ) { ... } }
>
> Jedesmal wird versucht eine Konstant zu ändern (zu überschreiben).

Wie es aussieht, bietet das Beispiel Raum für weitere Fragen (und
Erkenntnisgewinn).

Etwas aufgebohrt:
===================================== snip ==========================
ttt();
sub ttt
{
$_ = "init";
foreach (1,2)
{
ooo();
print "ttt in loop: $_\n";
}
print "ttt end: $_\n";
}

sub ooo
{
print "ooo start: $_\n";

# local($_); # [1]

# $_ = 3; print; # [2] -

# $_ = ; print; # [3] -

# while() { print; } # [4] -

for( 0 .. 3 ) { # [5] +
print "$_\n";
}
}
__END__
data
===================================== snip ==========================

*Zuweisung* an §_ ist in ooo() verboten, erneutes *Aliasing* jedoch möglich.

Die obigen Beispiele [2], [3], [4] sind deshalb nicht erlaubt,
wohingegen [5] funktioniert.

Darf daraus der gute Rat abgeleitet werden, die Variable $_ in
Subroutines sicherheitshalber vor Zuweisungen zu lokalisieren (siehe
[1]), da man ja nie weiss, in welchem Kontext der Aufruf erfolgte ... ?

Bernd.

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 18:43:06 von hjp-usenet2

Frank Küster wrote:
> Christian Lackas wrote:
>> for (1) { while (defined $_ = ) { ... } }
>>
>> Jedesmal wird versucht eine Konstant zu ändern (zu überschreiben).
>
> Hm, wie soll man dann Subroutinen schreiben, die eine Datei auslesen, so
> dass man die Subroutine auch in einer Schleife aufrufen darf?

»local $_;« am Anfang der Subroutine funktioniert.

Allerdings hätte ich auch geglaubt, dass »while (<>)« ein implizites
»local $_« macht, so wie »for (list)« ja auch. Es dämmert mir aber dunkel,
dass ich darauf auch schon einmal reingefallen bin.

> Wo steht eigentlich was
> zum Scoping von Spezialvariablen wie $_?

Die sind eigentlich alle global. (Und das mit den lokalen Variablen in
for-Schleifen steht in perlsyn und hat mit $_ nichts zu tun, wie ich gerade
sehe)

hp

--
_ | Peter J. Holzer | Löschung von at.usenet.schmankerl?
|_|_) | Sysadmin WSR/LUGA |
| | | hjp@hjp.at | Diskussion derzeit in at.usenet.gruppen
__/ | http://www.hjp.at/ |

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 20:38:59 von Christian Lackas

* Frank Küster [2006-03-07]:

Hallo Frank,

> Hm, wie soll man dann Subroutinen schreiben, die eine Datei auslesen, so
> dass man die Subroutine auch in einer Schleife aufrufen darf?

local $_;

> while (defined $line = ) { ... }
> geht vermutlich, aber elegant ist das nicht.

while (defined ($line=)) { ... }

> Wo steht eigentlich was zum Scoping von Spezialvariablen wie $_?

Ganz normales dynamische Gültigkeit, sowas wird in perlsub abgehandelt.
Speziell würde ich bei 'Temporary Values via local()' anfangen.

Gruß
Christian


--
Nicht für die Uni lernen wir, sondern für die Katz.
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker

Re: wann darf $_ nicht verwendet werden?????

am 07.03.2006 20:41:33 von Christian Lackas

* Bernd Schuler [2006-03-07]:

Hallo Bernd,

> Etwas aufgebohrt:

warum wieder dieses Beispiel?

> *Zuweisung* an §_ ist in ooo() verboten, erneutes *Aliasing* jedoch möglich.

Ja.

> Die obigen Beispiele [2], [3], [4] sind deshalb nicht erlaubt,
> wohingegen [5] funktioniert.

Ja, weil die for()-Schleife hier selbst mit einem impliziten local
arbeitet. Wenn du die Schleife verläßt ist ja der alte Wert von $_
wieder hergestellt.

> Darf daraus der gute Rat abgeleitet werden, die Variable $_ in
> Subroutines sicherheitshalber vor Zuweisungen zu lokalisieren (siehe
> [1]), da man ja nie weiss, in welchem Kontext der Aufruf erfolgte ... ?

Grundsätzlich ist das keine schlechte Idee.

Gruß
Christian

--
Wer flippert, sündigt nicht.
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker

Re: wann darf $_ nicht verwendet werden?????

am 08.03.2006 08:26:55 von f.ballandt

Frank Küster schrieb:

>>
>>Jedesmal wird versucht eine Konstant zu ändern (zu überschreiben).



>
> Hm, wie soll man dann Subroutinen schreiben, die eine Datei auslesen, so
> dass man die Subroutine auch in einer Schleife aufrufen darf?


warum habe ich da noch nie etwas in irgendeiner doku gelesen?
das verwirrt ja mein perlsches weltbild.
alle funktionen, die $_ etwas zuweisen muß ich jetzt als verboten
betrachten?
wo liegt der sinn?



frank



>ich wusste mal einen Befehl, der die Ausgabe auf stdout noch zusätzlich
> in eine Datei umlenken konnte... Bitte helft mir auf die Sprünge.

in perl oder der shell?

shell: tee und script

tee versaut die ausgabe, wenn nicht immer mit ganzen zeilen
(+zeilenende) gearbeitet wird (hat sich deshalb zum debuggen/loggen
meiner perlscripte nicht bewährt)

script ist leider für cygwin nicht verfügbar.

Re: wann darf $_ nicht verwendet werden?????

am 08.03.2006 09:30:00 von Christian Lackas

* f.ballandt [2006-03-08]:

Hallo Frank,

> warum habe ich da noch nie etwas in irgendeiner doku gelesen?
> das verwirrt ja mein perlsches weltbild.
> alle funktionen, die $_ etwas zuweisen muß ich jetzt als verboten
> betrachten?

ich will dich jetzt nicht noch mehr verwirren, aber das ist keine
Eigenschaft von $_, sondern von Konstanten in Perl:

for my $a (1) { $a = 2; }

Liefert exakt das gleiche Ergebnis.

Problematisch wird es erst, wenn man folgendes macht:

for my $a (1..1) { $a = 2 }

Das liegt daran, dass Perl hier intern eine Liste erzeugt, deren
Elemente dann der Reihe nach $a sind. Die Daten gehen zwar bei
Veränderung verlogen, aber man hantiert hier nicht mit Konstanten.

> wo liegt der sinn?

Der Sinn davon, dass man Konstanten nicht verändern kann?

Das Problem tritt auch noch an vielen anderen Stellen auf, z.B.

foo($blub); # geht
foo("blub"); # geht nicht

mit sowas wie

sub foo { $_[0] .= "burp" }

Konstanten an Methoden zu übergeben, die Variablen erwarten geht halt
schief. Perl hat keine strenge Typenprüfung, daher lassen sich solche
Fehler hier erst zur Laufzeit finden.
Bei $_ ist es besonders tückisch, weil man das oft verwendet, ohne es zu
merken, aber das ist nicht die Schuld dieser speziellen Variable.
Wenn man sicher sein möchte sein eigenes $_ zu haben, dann muss man
local verwenden.


Gruß
Christian

--
Wenn ein Mann einer Frau die Autotür öffnet, ist entweder die Frau neu
oder das Auto.
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker

Re: wann darf $_ nicht verwendet werden?????

am 08.03.2006 10:54:15 von f.ballandt

> Der Sinn davon, dass man Konstanten nicht verändern kann?

ja ist klar, hätte jetzt nur zu "meckern", daß for, foreach $_
weiterreicht. na ja vielleicht nutzt es ja jemand.

meine wohl immer in for(each)-schleifen liegenden probleme
kann ich also durch:

for my ...
{
...
}


lösen und nicht unbedingt erst in den folgenden subs!?
in allen subs erwarte weiterhin ich ein schreibbares $_.


>Das Problem tritt auch noch an vielen anderen Stellen auf, z.B.

> foo($blub); # geht
> foo("blub"); # geht nicht

> sub foo { $_[0] .= "burp" }

gut, so was tue ich nicht, aber gibt es vielleicht noch unsichtbarere
gefahrenbeispiele?


frank

Re: wann darf $_ nicht verwendet werden?????

am 11.03.2006 17:45:27 von frank

"f.ballandt" wrote:

> Frank Küster schrieb:
> >ich wusste mal einen Befehl, der die Ausgabe auf stdout noch zusätzlich
> > in eine Datei umlenken konnte... Bitte helft mir auf die Sprünge.
>
> in perl oder der shell?

Das war (und ist) meine Signatur. Sie hat mit dem Thema der Diskussion
nichts zu tun.

Gruß, Frank

--
> ich wusste mal einen Befehl, der die Ausgabe auf stdout noch zusätzlich
> in eine Datei umlenken konnte... Bitte helft mir auf die Sprünge.
"kaffee" war es nicht.

Re: wann darf $_ nicht verwendet werden?????

am 13.03.2006 08:04:08 von f.ballandt

> Der Sinn davon, dass man Konstanten nicht verändern kann?
>
> Das Problem tritt auch noch an vielen anderen Stellen auf, z.B.
>
> foo($blub); # geht
> foo("blub"); # geht nicht
>
> mit sowas wie
>
> sub foo { $_[0] .= "burp" }
>

warum geht dann aber


foo();
foo({key1,"vorhanden Speicher gedruckt\n"});
sub foo
{
$_[0]{key1}="nicht vorhandenen Speicher beschrieben\n"
unless defined $_[0]{key1};
print $_[0]{key1};
}


oder viel besser gefragt: Darf ich so was machen?
(Nicht nur rhetorisch, interessant für subs, die je nach dem ohne oder
mit Argumenten aufgerufen werden)

Frank

Re: wann darf $_ nicht verwendet werden?????

am 13.03.2006 09:17:33 von Christian Lackas

* f.ballandt [2006-03-13]:

Hallo Frank,

> warum geht dann aber
> foo();

das geht, weil du @_ verändern kannst, nur halt nicht unbedingt immer
dessen Elemente, wenn sie konstant sein könnten. Du könntest ein
konstantes Element, aber z.B. auch mit shift entfernen.

> foo({key1,"vorhanden Speicher gedruckt\n"});

Hier erzeugst du einen Hash, und ein solcher ist auch nie konstant (weil
Perl das nicht kann). Der Hash selbst enthält dann eine Referenz auf
eine Konstante, die Referenz selbst ist aber veränderbar (und genau das
machst du dann ja unten).

> sub foo
> {
> $_[0]{key1}="nicht vorhandenen Speicher beschrieben\n"
> unless defined $_[0]{key1};
> print $_[0]{key1};
> }
> oder viel besser gefragt: Darf ich so was machen?

Ja.

Gruß
Chrisitan

--
When there's a will to fail, obstacles can be found.
(John McCarthy, 1983)
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker