Problem mit "use strict"

Problem mit "use strict"

am 29.07.2006 02:53:00 von TorstenR

Hallo,

ich wollte ein einige Jahre altes Script etwas "aufräumen" und dabei
unter anderem auch strict verwenden. Das hat soweit auch geklappt, nur
genau eine Zeile bekomme ich leider nicht angepasst. Die relevante
Stelle im Code sieht wie folgt aus:

1) for (map {[(split/,/)[1,0]]} <@daten>) {
2) chomp(@$_->[0]);
3) $hash{$_->[0]}= push( @{$_->[0]},$_->[1]);
4) }

Das Script funktioniert, unter strict erhalte ich jedoch wegen Zeile 3
eine Fehlermeldung (Can't use string as an ARRAY ref while "strict refs"
in use).

Hat vielleicht jemand eine Idee, wie sich das beheben lässt?

Viele Grüße,
Torsten

Re: Problem mit "use strict"

am 29.07.2006 10:47:34 von unknown

Post removed (X-No-Archive: yes)

Re: Problem mit "use strict"

am 29.07.2006 22:24:02 von Frank Seitz

TorstenR wrote:
> Hallo,
>
> ich wollte ein einige Jahre altes Script etwas "aufräumen" und dabei
> unter anderem auch strict verwenden. Das hat soweit auch geklappt, nur
> genau eine Zeile bekomme ich leider nicht angepasst. Die relevante
> Stelle im Code sieht wie folgt aus:
>
> 1) for (map {[(split/,/)[1,0]]} <@daten>) {
> 2) chomp(@$_->[0]);
> 3) $hash{$_->[0]}= push( @{$_->[0]},$_->[1]);
> 4) }
>
> Das Script funktioniert, unter strict erhalte ich jedoch wegen Zeile 3
> eine Fehlermeldung (Can't use string as an ARRAY ref while "strict refs"
> in use).
>
> Hat vielleicht jemand eine Idee, wie sich das beheben lässt?

Grausamer Code.
Versuchs mal mit "no strict 'refs'" am Anfang des Schleifenkörpers.

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: Problem mit "use strict"

am 30.07.2006 02:48:34 von TorstenR

Hi,

> Was bitte ist '<@daten>'?

Ein Array, das unbestimmt viele Elemente der Form "Wort1,Wort2" beinhaltet.

> Ich finde den ganzen Codeblock einigermaßen unverständlich. Vielleicht
> wäre eine Erklärung hilfreich, was die genaue Funktion sein soll.

Das wüsste ich auch gerne ;)

Der Code geht weiter mit:

5) foreach (sort keys %hash) { ... }

Soweit ich das sehe wird aus dem Array @daten also in irgendeiner Form
ein Hash gebildet. Ich kann mit dem geposteten Codeblock leider auch
wenig anfangen, das hat mein Vorgänger verbockt :/ Ich hoffe, hier kann
mir jemand weiterhelfen.

Gruß,
Torsten

Re: Problem mit "use strict"

am 30.07.2006 02:49:44 von TorstenR

Hallo,

> Versuchs mal mit "no strict 'refs'" am Anfang des Schleifenkörpers.

das würde den Code leider auch nicht besser machen. Ich will das Problem
lieber "ordentlich" beheben, daher mein Posting hier.

Gruß,
Torsten

Re: Problem mit "use strict"

am 30.07.2006 06:44:44 von Frank Seitz

TorstenR wrote:
>>
>>Versuchs mal mit "no strict 'refs'" am Anfang des Schleifenkörpers.
>
> das würde den Code leider auch nicht besser machen. Ich will das Problem
> lieber "ordentlich" beheben, daher mein Posting hier.

Dann musst Du den Code komplett umschreiben, denn der arbeitet
mit Symbolic References.

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: Problem mit "use strict"

am 31.07.2006 11:54:55 von Daniel Fischer

TorstenR!

> Soweit ich das sehe wird aus dem Array @daten also in irgendeiner Form
> ein Hash gebildet. Ich kann mit dem geposteten Codeblock leider auch
> wenig anfangen, das hat mein Vorgänger verbockt :/ Ich hoffe, hier kann
> mir jemand weiterhelfen.

Ich kommentiere es mal...

1) for (map {[(split/,/)[1,0]]} <@daten>) {

@daten muss ein Array aus Elementen der Form Wort1,Wort2 sein. Das hast Du
zwar geschrieben, das geht hieraus aber auch hervor.

<@daten> ist in diesem Kontext im Prinzip so zu verstehen wie @daten ohne <>.

map {} wendet den Ausdruck in {} auf jedes Element an und Ergebnis ist
wieder eine Liste, über die die Schleife läuft. Der Ausdruck in den {}
bedeutet, dass jedes Element "a,b" am Komma getrennt werden soll, Ergebnis
ist eine Liste ("a","b"). Aus dem zweiten und dem ersten Element wird in
dieser Reihenfolge ein Array konstruiert.

Wenn also @daten am Anfang sowas wie ("a,1", "b,2") ist, enthält die
Laufvariable $_ in der Schleife nacheinander ["1", "a"] und ["2", "b"].

2) chomp(@$_->[0]);

Da die Laufvariable $_ ein Array enthält, wird hier mit @$_->[0] auf das
erste Element zugegriffen (das @ ist aber nicht notwendig). Wir erinnern
uns, das ist der Teil, der vorhin hinter dem Komma stand. Offenbar gab es
weiter vorn noch keine Gelegenheit, die Zeilenenden zu entfernen :-)

3) $hash{$_->[0]}= push( @{$_->[0]},$_->[1]);

Hier wird das erste Element dann als Key in %hash verwendet.

@{$_->[0]} benutzt das erste Element als Arrayref. Das heißt, in unserem
Beispiel entstehen hier die Arrays @1 und @2, denen mit push die Werte "a"
respektive "b" angehängt werden.

Das ganze spart den Aufwand, für jeden neuen Key in %hash erst ein Array
anzulegen, bevor man mit push Zeug rein schieben kann.

4) }

Damit sollte auch klar sein, was der Code macht: Er nimmt aus den
Eingangsdaten mit zwei durch Komma getrennten Werten "a,b" immer b als Key
in einen Hash und sammelt unter diesem Key alle Werte a, die mit b so
zusammen vorkommen.



Gruß
Daniel

Re: Problem mit "use strict"

am 31.07.2006 13:31:19 von Michael Holzt

Daniel Fischer wrote:
> 3) $hash{$_->[0]}= push( @{$_->[0]},$_->[1]);
[...]
> Das ganze spart den Aufwand, für jeden neuen Key in %hash erst ein Array
> anzulegen, bevor man mit push Zeug rein schieben kann.

Das verstehe ich jetzt nicht. Wenn der Array nicht existiert, erzeugt
push ihn halt. Mit diesem Code gibt es jedenfalls auch keinen Fehler
mehr, und ich halte ihn für gleichwertig:

push( @{ $hash{$_->[0]} }, $_->[1] );


> Damit sollte auch klar sein, was der Code macht: Er nimmt aus den
> Eingangsdaten mit zwei durch Komma getrennten Werten "a,b" immer b als Key
> in einen Hash und sammelt unter diesem Key alle Werte a, die mit b so
> zusammen vorkommen.

Also hier dann die Korrektur des Originalcodes:

for (map {[(split/,/)[1,0]]} <@daten>) {
chomp($_->[0]);
push( @{ $hash{$_->[0]} }, $_->[1] );
}

Mein Ersatzvorschlag für die Augabe:

foreach my $zeile ( @daten )
{
chomp($zeile);
my ($a, $b) = split(/,/, $zeile);
push( @{$hash{$b}}, $a);
}








>
>
>
> Gruß
> Daniel
>



--
"Erst war es ein Kernel alle halbe Jahre, zum Schluss konnte ich mit
dem Compilieren nicht mehr aufhören." (Torsten Kleinz im IRC)

Re: Problem mit "use strict"

am 31.07.2006 15:18:02 von Daniel Fischer

Michael Holzt!

> Daniel Fischer wrote:
>> 3) $hash{$_->[0]}= push( @{$_->[0]},$_->[1]);
> [...]
>> Das ganze spart den Aufwand, für jeden neuen Key in %hash erst ein Array
>> anzulegen, bevor man mit push Zeug rein schieben kann.
>
> Das verstehe ich jetzt nicht. Wenn der Array nicht existiert, erzeugt
> push ihn halt.

Das war nur eine Vermutung von mir, ich habe den Code ja nicht
geschrieben. Eventuell ist es auch Ergebnis einer langen Suche nach einem
funktionierenden Weg oder der Autor wollte den Code nur möglichst kurz
machen oder betrieb Stellensicherung o.ä. ;-)


Gruß
Daniel

Re: Problem mit "use strict"

am 01.08.2006 01:26:00 von TorstenR

Hallo,

vielen Dank für die Rückmeldungen! Das mit der Stellensicherung stimmt
genau, allerdings war mein Vorgänger damit wenig erfolgreich. Und jetzt
darf ich mich durch den Code wühlen..

Die vorgeschlagene Änderung in

push( @{ $hash{$_->[0]} }, $_->[1] );

habe ich vorgenommen, hier erhalte ich aber die exakt gleiche
Fehlermeldung ("Can't use string as an ARRAY ref while "strict refs" in
use"). strict zu lockern oder zu entfernen ist leider keine echte
Option, zumal die Ausgane bei der obigen Änderung auch nicht mehr stimmt.

Die hier gepostete Erklärung was der Code macht stimmt wohl exakt,
leider weiß ich aber nicht so recht, wie ich das nun strict-kompatibel
hinbekomme :/

Hier nochmal der gesamte relevante Codeblock:

1) for (map {[(split/,/)[1,0]]} <@daten>) {
2) chomp(@$_->[0]);
3) $hash{$_->[0]}= push( @{$_->[0]},$_->[1]);
4) }
5)
6) foreach (sort keys %hash) {
7) $msg.="$_:";
8) print map {
9) chomp $_;
10) $temp.=" $_\,";
11) @$_ = undef;
12) }@$_ ;
13) chop $temp;
14) if($temp =~ m/,/) { $temp = "$temp"; }
15) $msg.="$temp
";
16) undef($temp);
17) }

Grausamer Code, ich weiß. Und die restlichen Scripte sind nicht viel
besser :/

Der Effekt ist so, wie von Daniel beschrieben, die Ausgabe am Ende sieht
dann in etwa so aus:

KeyA: WertA1, WertA2, WertA3
KeyB: WertB1
KeyC: WertC1, WertC2

etc. (wobei zB WertA1, WertA2 und WertA3 alle den gleichen KeyA haben usw.)

Für weitere Hilfestellung wäre ich daher sehr dankbar.

Viele Grüße,
Torsten

Re: Problem mit "use strict"

am 01.08.2006 10:29:48 von Ingo Menger

TorstenR wrote:
> Hallo,
>
> vielen Dank für die Rückmeldungen! Das mit der Stellensicherung stimmt
> genau, allerdings war mein Vorgänger damit wenig erfolgreich. Und jetzt
> darf ich mich durch den Code wühlen..
>
> Die vorgeschlagene Änderung in
>
> push( @{ $hash{$_->[0]} }, $_->[1] );
>
> habe ich vorgenommen, hier erhalte ich aber die exakt gleiche
> Fehlermeldung ("Can't use string as an ARRAY ref while "strict refs" in
> use"). strict zu lockern oder zu entfernen ist leider keine echte
> Option, zumal die Ausgane bei der obigen Änderung auch nicht mehr stimm=
t
>
> Die hier gepostete Erklärung was der Code macht stimmt wohl exakt,
> leider weiß ich aber nicht so recht, wie ich das nun strict-kompatibel
> hinbekomme :/

Vielleicht:
my ($a, $b) =3D @_; # ersparen wir uns $_->[0], etc.
if (exists $hash{$a}) {
push @{$hash{$a}}, $b;
}
else { # neuer key
$hash{$a} =3D [ $b ];
}

Dieser Code vermeidet, daß Arrayreferenzen aus dem Nichts heraus zu
existieren anfangen. Ein Feature von Perl, das gern verwendet wird, um
den Code unleserlich zu machen. Hier wird jedoch im else Zweig ein
anonymes Array explizit erzeugt.

Re: Problem mit "use strict"

am 06.08.2006 18:23:57 von hjp-usenet2

On Mon, 31 Jul 2006 11:54:55 +0200, Daniel Fischer wrote:
> TorstenR!
>> Soweit ich das sehe wird aus dem Array @daten also in irgendeiner Form
>> ein Hash gebildet. Ich kann mit dem geposteten Codeblock leider auch
>> wenig anfangen, das hat mein Vorgänger verbockt :/ Ich hoffe, hier kann
>> mir jemand weiterhelfen.
>
> Ich kommentiere es mal...
>
> 1) for (map {[(split/,/)[1,0]]} <@daten>) {
>
> @daten muss ein Array aus Elementen der Form Wort1,Wort2 sein. Das hast Du
> zwar geschrieben, das geht hieraus aber auch hervor.
>
> <@daten> ist in diesem Kontext im Prinzip so zu verstehen wie @daten ohne <>.

Aber nur vielleicht. Das hängt von den exakten Werten in @daten und den
Namen der Files auf dem System ab:

If what’s within the angle brackets is neither a filehandle nor a sim‐
ple scalar variable containing a filehandle name, typeglob, or typeglob
reference, it is interpreted as a filename pattern to be globbed, and
either a list of filenames or the next filename in the list is
returned, depending on context.

-- perldoc perlop

In meinem tmp-Verzeichnis gibt

#!/usr/local/bin/perl -w
use strict;

my @daten = qw(foo ba*);

for (<@daten>) {
print "<$_>\n";
}

dementsprechend auch










aus.

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