Spielereien mit reverse, kleines Problem
Spielereien mit reverse, kleines Problem
am 04.04.2006 21:51:35 von Christoph Buck
Hallo. Ich bin ein Perl-Neuling. Hab hier folgendes kleines Programm:
@a=<>;
foreach (@a){
$_=reverse $_;
print $_;
}
Also die Dateien von der Kommandozeile einlesen und den Inhalt rückwärts
ausgeben. Das Programm geht auch. Aber wieso geht das nicht so.
@a=<>;
foreach (@a){
print reverse $_;
}
Re: Spielereien mit reverse, kleines Problem
am 04.04.2006 22:03:02 von Lukas Mai
Christoph Buck schrob:
>
> @a=<>;
> foreach (@a){
> $_=reverse $_;
> print $_;
> }
> Also die Dateien von der Kommandozeile einlesen und den Inhalt rückwärts
> ausgeben. Das Programm geht auch. Aber wieso geht das nicht so.
>
> @a=<>;
> foreach (@a){
> print reverse $_;
> }
$ perldoc -f reverse
reverse LIST
In list context, returns a list value consisting of the
elements of LIST in the opposite order. [...]
$ perldoc -f print
print FILEHANDLE LIST
print LIST
[...]
print erzeugt also Listenkontext. reverse nimmt sich die Liste $_ (hat 1
Element), kehrt sie um, und das Ergebnis sieht unverändert aus.
Lösung:
print scalar reverse $_;
HTH, Lukas
Re: Spielereien mit reverse, kleines Problem
am 04.04.2006 22:05:21 von Wolf Behrenhoff
Christoph Buck schrieb:
> Also die Dateien von der Kommandozeile einlesen und den Inhalt rückwärts
> ausgeben. Das Programm geht auch. Aber wieso geht das nicht so.
^
Das Fragezeichen existiert für Fragen! (SCNR)
> @a=<>;
> foreach (@a){
> print reverse $_;
> }
Das Problem hier ist, dass print eine Liste erwartet und reverse sich je
nach Kontext unterschiedlich verhält. Im Listenkontext dreht es die
gesamte Liste um (die hier aber nur aus einem Element, nämlich $_,
besteht). Daher wird hier nichts verändert.
Du musst reverse in einem skalaren Kontext aufrufen, damit ein String
umgekehrt wird (genauer: die Liste, die du dem reverse gibst, wird
gejoint und dann von hinten nach vorne zurückgegeben).
Also muss es heißen
print scalar reverse $_;
oder einfach nur
print scalar reverse;
Wolf
Re: Spielereien mit reverse, kleines Problem
am 05.04.2006 09:11:59 von f.ballandt
> @a=<>;
> foreach (@a){
> $_=reverse $_;
> print $_;
> }
> Also die Dateien von der Kommandozeile einlesen und den Inhalt rückwärts
> ausgeben. Das Programm geht auch.
bei mir nur, wenn in der ersten zeile
$a[0]=<>;
steht. Ist das bei Euch anders?
Zu diesem Thema hätte ich noch eine weitere Frage (siehe auch das Thema:
wann darf $_ nicht verwendet werden????? vom 7.3.2006):
warum geht:
@a=(2,3,4);
foreach (@a){
$_=reverse $_;
print $_;
}
und folgendes nicht?
foreach ((2,3,4)){
$_=reverse $_;
print $_;
}
die $_= ... zeile bringt Modification of a read-only value
Gruß Frank
Re: Spielereien mit reverse, kleines Problem
am 05.04.2006 11:31:26 von Wolf Behrenhoff
f.ballandt schrieb:
>> @a=<>;
>> foreach (@a){
>> $_=reverse $_;
>> print $_;
>> }
>> Also die Dateien von der Kommandozeile einlesen und den Inhalt rückwärts
>> ausgeben. Das Programm geht auch.
>
> bei mir nur, wenn in der ersten zeile
>
> $a[0]=<>;
>
> steht. Ist das bei Euch anders?
Ja. $a[0]=<>; ruft <> in skalarem Kontekt auf und liest folglich eine
Zeile (bzw. bis $/). Bei @a=<>; wird <> in Listenkontekt aufgerufen und
liest magisch eine ganze Datei ein, die auf Kommandozeile übergeben wurde.
Bemerkung: Mit "den Inhalt rückwärts ausgeben" meint der OP, dass jede
einzelne Zeile der Eingabe rückwärts ausgegeben werden soll.
> Zu diesem Thema hätte ich noch eine weitere Frage (siehe auch das Thema:
> wann darf $_ nicht verwendet werden????? vom 7.3.2006):
>
> warum geht:
>
> @a=(2,3,4);
> foreach (@a){
> $_=reverse $_;
> print $_;
> }
Weil du hier mit $_=reverse $_; der Reihe nach die Variablen $a[0] bis
$a[2] änderst.
> und folgendes nicht?
>
> foreach ((2,3,4)){
> $_=reverse $_;
> print $_;
> }
>
> die $_= ... zeile bringt Modification of a read-only value
Weil du hier versuchst, den KONSTANTEN 2,3 und 4 neue Werte zuzuweisen.
Das geht natürlich nicht. War das im anderen Thread nicht klar geworden?
Wolf
Re: Spielereien mit reverse, kleines Problem
am 05.04.2006 15:39:35 von f.ballandt
>>@a=(2,3,4);
>>foreach (@a){
>> $_=reverse $_;
>> print $_;
>>}
>
>
> Weil du hier mit $_=reverse $_; der Reihe nach die Variablen $a[0] bis
> $a[2] änderst.
>
>
Das for(each) wird mir ja immer suspekter. Das selbst
foreach my$b (@a){
$b=reverse $b;
#print $b;
}
mir mein @a "zerstört" ...
Da kann ja nur noch
foreach(1..@a)
erlaubt werden, wobei diese konstruktion bei unerlaubten
Schreibversuchen nicht immer
Modification of a read-only value
bringt, sondern manchmal erst zur Laufzeit scheinbar unerklärlich abstürzt.
Frank
Re: Spielereien mit reverse, kleines Problem
am 05.04.2006 16:04:20 von Frank Seitz
f.ballandt wrote:
> Das for(each) wird mir ja immer suspekter. Das selbst
>
> foreach my$b (@a){
> $b=reverse $b;
> #print $b;
> }
>
> mir mein @a "zerstört" ...
Ja, das ist eine auch für mein Empfinden leicht bizarre
Eigenschaft von foreach. Aber so ist foreach nunmal definiert.
Als Perler weiß man das.
Die Lösung besteht darin, den Wert zu kopieren:
foreach (@a)
{
my $b = $_; # Wert kopieren
# irgendwas zerstörerisches mit der Kopie tun
}
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: Spielereien mit reverse, kleines Problem
am 05.04.2006 21:00:14 von Slaven Rezic
Frank Seitz writes:
> f.ballandt wrote:
>
> > Das for(each) wird mir ja immer suspekter. Das selbst
> >
> > foreach my$b (@a){
> > $b=reverse $b;
> > #print $b;
> > }
> >
> > mir mein @a "zerstört" ...
>
> Ja, das ist eine auch für mein Empfinden leicht bizarre
> Eigenschaft von foreach. Aber so ist foreach nunmal definiert.
> Als Perler weiß man das.
>
> Die Lösung besteht darin, den Wert zu kopieren:
>
> foreach (@a)
> {
> my $b = $_; # Wert kopieren
> # irgendwas zerstörerisches mit der Kopie tun
> }
>
Wobei das auch nur eine flache Kopie erstellt. Wenn man es mit
verschachtelten Strukturen zu tun hat, sollte man lieber klonen:
use Storable qw(dclone);
for (@a) {
my $b = dclone $_;
}
Aber das gilt ja für praktisch jede Programmiersprache.
Gruß,
Slaven
--
Slaven Rezic - slaven rezic de
Lost in your Tk widget tree? Try
http://user.cs.tu-berlin.de/~eserte/src/perl/Tk-WidgetDump/
Re: Spielereien mit reverse, kleines Problem
am 06.04.2006 02:08:30 von Maluku
Christoph Buck schrieb:
> Hallo. Ich bin ein Perl-Neuling. Hab hier folgendes kleines Programm:
>
>
> @a=<>;
> foreach (@a){
> $_=reverse $_;
> print $_;
> }
> Also die Dateien von der Kommandozeile einlesen und den Inhalt rückwärts
> ausgeben. Das Programm geht auch. Aber wieso geht das nicht so.
Ganze Datei rückwärts:
print scalar reverse do {undef $/;<>};
Zeilenweise rückwärts
print map $_=reverse,<>;
Genauso, zeilenweise, aber für interaktive shell
print scalar reverse while (<>);
Oder besser mit \n am ende des Strings: (Dann wird es aber mehrzeilig)
Ganze Datei:
chomp($_=do {undef $/;<>});
print reverse($_)."\n";
Zeilenweise umdrehen:
print map {chomp;$_=reverse."\n"} <>;
interactiv:
while (<>) {
chomp;
print scalar reverse."\n"
}
--
$_='';s%%`^.*`s;.*;uhtnmo;;a>lha~a>inu~a>fmk~a>rou~a>duM~a>b tl~s;&&&&&&;
!d1!l2!b3!i4!f5!r6q(?);e;Z``}a>&&&`sub# "1#{#"_=shift#;s^"2^"3#^;``;~`
return #"_#}``^!&&`"1(#""2)#\.`Z%x;s~Z~print~g;s/#/\\/g;
s/`(.)(.+?)`(.+?)`/s$1$2$1$3$1g\;/gsx;s;&;(.);g;y^"^$^;print ;
Re: Spielereien mit reverse, kleines Problem
am 06.04.2006 09:29:55 von f.ballandt
Guten Morgen NG,
>>Die Lösung besteht darin, den Wert zu kopieren:
>>
>>foreach (@a)
>>{
>> my $b = $_; # Wert kopieren
>> # irgendwas zerstörerisches mit der Kopie tun
>>}
>>
>
>
> Wobei das auch nur eine flache Kopie
?????
erstellt. Wenn man es mit
> verschachtelten Strukturen zu tun hat, sollte man lieber klonen:
>
ich vermute die Problematik mit Referenzen ist hier gemeint?
Eine Kopie einer Referenz zeigt immer noch auf das selbe Objekt!?
und das
> my $b = dclone $_;
kopiert auch die referenzierten Objekte?
Re: Spielereien mit reverse, kleines Problem
am 06.04.2006 09:51:37 von Frank Seitz
Slaven Rezic wrote:
> Frank Seitz writes:
>>
>>Die Lösung besteht darin, den Wert zu kopieren:
>>
>>foreach (@a)
>>{
>> my $b = $_; # Wert kopieren
>> # irgendwas zerstörerisches mit der Kopie tun
>>}
>
> Wobei das auch nur eine flache Kopie erstellt. Wenn man es mit
> verschachtelten Strukturen zu tun hat, sollte man lieber klonen:
>
> use Storable qw(dclone);
>
> for (@a) {
> my $b = dclone $_;
> }
>
> Aber das gilt ja für praktisch jede Programmiersprache.
Was Du ansprichst, kommt bei Referenzen ins Spiel.
Die Besonderheit des foreach-Konstrukts ist
noch etwas anderes:
| the "foreach" loop index variable is an implicit alias
| for each item in the list that you're looping over.
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