Ein bischen Spaß muss sein: Quiz zu for

Begonnen von RichardCZ, 29 März 2020, 20:25:55

Vorheriges Thema - Nächstes Thema

RichardCZ

Quiz 1: Was gibt das print $x aus? 4 oder 5?

my $x = 4;

for my $x (1..5) {
     $x;
}

print $x;  #  4 oder 5 ?


Quiz 2: Was gibt das print $x aus? 4 oder 5?

my $x = 4;

for  $x (1..5) {
     $x;
}

print $x;  #  4 oder 5 ?


Quiz 3: Wie sieht @list aus? [1,2,3,4,5] oder [2,4,6,8,10]?

use Data::Dumper;

my @list = (1..5);

for my $x (@list) {
     $x *= 2;
}

print Dumper(\@list);


Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

CoolTux

Quiz 3:

2 4 6 8 10


Und die anderen beiden gehen nicht  ;D
ZitatUseless use of private variable in void context
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

RichardCZ

Zitat von: CoolTux am 29 März 2020, 20:43:54
Und die anderen beiden gehen nicht  ;D
"Useless use of private variable in void context"

Wenn Du auch eigenmächtig ein "use warnings" dranflanschst...

Antwort auf Q3 ist richtig. Überrascht das niemanden?
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

CoolTux

Zitat von: RichardCZ am 29 März 2020, 21:40:49
Wenn Du auch eigenmächtig ein "use warnings" dranflanschst...

Antwort auf Q3 ist richtig. Überrascht das niemanden?

Nö. Steht doch da was er macht  ;)
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

RichardCZ

Zitat von: CoolTux am 29 März 2020, 21:56:41
Nö. Steht doch da was er macht  ;)

Aha.

Dann

my @list = (1..5);
my $x = $list[1];
$x *= 2;


habe ich @list geändert oder nicht?

Wenn nicht - wieso ändert dann eine Modifikation von $x im for besagtes @list?
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

CoolTux

Hier ändert sich list nicht. Auf die Frage kenne ich leider die Antwort nicht. Willst Du auflösen oder warten?
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

RichardCZ

Zitat von: CoolTux am 29 März 2020, 22:16:32
Hier ändert sich list nicht. Auf die Frage kenne ich leider die Antwort nicht. Willst Du auflösen oder warten?

Ich warte noch.  ;D

Weil ehrlich gesagt - wen das Verhalten in for nicht überrascht ... der hat entweder for komplett oder noch gar nicht begriffen.

Und das ist doch ein interessantes Spannungsfeld. Spaß muss sein.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

CoolTux

Ich versuche mal wieder zu geben was ich glaube verstanden zu haben.

In jeder Iteration der for Schleife erstellt Perl einen Alias anstelle eines Werts. Mit anderen Worten, wenn ich Änderungen am Iterator vor nehme, werden diese Änderungen auch in den Elementen des Arrays angezeigt.

Habe ich das korrekt verstanden?
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

SCMP77

#8
Zitat von: RichardCZ am 29 März 2020, 23:12:02Weil ehrlich gesagt - wen das Verhalten in for nicht überrascht ... der hat entweder for komplett oder noch gar nicht begriffen.

Ich habe es jetzt weder ausprobiert noch in der Doku von Perl nachgelesen.

Perl arbeitet dort offenbar mit einer unsichtbaren Referenz. $x scheint in Wirklichkeit eine Referenz zu sein, die auf das durch for ausgewählte Listenelement verweist.

Für jemanden, der sich selten mit Perl beschäftigt (wie ich), ist natürlich schon überraschend und wenn man das nicht weiß, wird man hier ganz schön lange suchen müssen. So etwas fördert bei mir jedenfalls nicht die (nicht vorhandene) Zuneigung zu Perl.

Entsprechendes gibt es auch in Java für Objekte, aber dort weiß man: Bei Zuweisungen von Objekten egal welcher Art, arbeitet man  immer mit Referenzen. Wenn man mehrer Objekte in einer Liste hat und man verändert das Element, das durch einen for-Ausdruck ausgewählt wurde, ändert man ebenfalls das Objekt der Liste!

Manche halten das für eine gewisse Inkonsequenz von Java, denn bei den Grundtypen verhält es sich anders als bei Objekten. An dieser Stelle ist C++ sauberer, aber das führt bei C++ auch wieder leicht dazu, dass Objekte unnötig häufig dupliziert werden, wenn man mit einer Referenz arbeiten will, muss man sie entsprechend als Referenz auch darstellen. Gerade bei der Übergabe von Instanzen einer Klasse an Methoden wird das recht häufig vergessen. Da kann es dann passieren, dass man größere Objekte kopiert, ohne es zu wissen. Jedenfalls habe ich früher bei Coderevues so etwas sehr häufig gefunden. Ich denke, das war der Grund, weshalb man das bei Java anders gelöst hatte, man kannte seine Pappenheimer.

Raspberry Pi 3 Model B mit Rasbian, SolvisMax, AVM DECT 200, Sonoff mit Tasmota geflasht

RichardCZ

Da ich (richtige) Lösungen nunmehr auch via PM bekomme (übrigens weil Leute hier nicht reinschreiben können), hier die Auflösung:

Q1: liefert 4
Q2: liefert auch 4

!!!

for verhält sich gemäß Dokumentation (https://perldoc.perl.org/perlsyn.html#For-Loops) so, weil die Schleifenvariable (in diesem Fall also das $x)

erstens immer lokal ist (egal ob my oder nicht, deswegen sollte man das my immer dazuschreiben)
zweitens den Wert aus der Liste nicht kopiert, sondern eine Referenz darauf bildet

ergo:

Zitat von: SCMP77 am 30 März 2020, 08:47:01
Perl arbeitet dort offenbar mit einer unsichtbaren Referenz. $x scheint in Wirklichkeit eine Referenz zu sein, dass auf das durch for ausgewählte Listenelement verweist.

Korrekt. Genau genommen ist das eine implizite, lokalisierte Referenz.

Zu dem o.g. man sollte immer my dazuschreiben, ein wenig grep und tamtam:


00_THZ.pm:    for  $parsingelement  (@$parsingrule) {
36_WMBUS.pm:    for $dataBlock ( @$dataBlocks ) {
36_WMBUS.pm:    for $dataBlock ( @$dataBlocks ) {
73_MPD.pm:     for $i (0 .. $#title)
73_MPD.pm:  for $i (0 .. $#artist)
89_HEATRONIC.pm:  for $i (0 .. $length-3)
89_HEATRONIC.pm:  for $i (0 .. $length-3)
WMBus.pm:    for $dataBlock ( @$dataBlocks ) {


Früher oder später wird perlcritic da bitterlich weinen.

Ach ja, und man sollte for und nicht foreach schreiben... da fällt mir ein ... oh "holy sh*t":



00_DFPlayerMini.pm:  foreach $file (@allfiles) {
00_DFPlayerMini.pm:       foreach $r (grep /^File_ADVERT/, keys %{$hash->{READINGS}}) {
00_DFPlayerMini.pm:        foreach $r (grep /^File_[^A]/, keys %{$hash->{READINGS}}) {
00_DFPlayerMini.pm:    foreach $key (keys %equalizerTexts) {
00_DFPlayerMini.pm:    foreach $key (keys %statusStorageTexts) {
00_SIGNALduino.pm:      foreach $searchpattern (@{$search}) # z.B. [1, -4]
00_SIGNALduino.pm:              #foreach $patt_id (keys %$patternList) {
00_SIGNALduino.pm:              foreach $id (@{$hash->{msIdList}}) {
00_SIGNALduino.pm:              foreach $id (@{$hash->{muIdList}}) {
00_SIGNALduino.pm:      foreach $id (@{$hash->{mcIdList}}) {
00_SIGNALduino.pm:      foreach $id (keys %ProtocolListSIGNALduino)
00_SIGNALduino.pm:      foreach $id (keys %ProtocolListSIGNALduino)
00_SIGNALduino.pm:      foreach $id (@IdList)
00_THZ.pm:  foreach $indice(@numbers) {
10_EnOcean.pm:    foreach $element (@listID, @freeID) {
10_EnOcean.pm:    foreach $element (keys %count) {
10_EnOcean.pm:    foreach $element (@listID, @freeID) {
10_EnOcean.pm:    foreach $element (keys %count) {
10_HXBDevice.pm:  foreach $hash (@devarray) {
10_ZWave.pm:    foreach $classname (split(" ", $s1)) {
10_ZWave.pm:    foreach $classname (split(" ", $s2)) {
14_CUL_TCM97001.pm:#  foreach $x (@a) {
14_CUL_TCM97001.pm:         foreach $x (@a) {
14_CUL_TCM97001.pm:        foreach $x (@a) {
14_CUL_TCM97001.pm:        foreach $x (@a) {
14_SD_WS_Maverick.pm:  #foreach $key (keys %models) {
23_ALL4027.pm:  foreach $line (@lines)
32_WifiLight.pm:    foreach $key (keys %defs)
32_WifiLight.pm:    foreach $key (keys %defs)
32_withings.pm:      foreach $readingsdate (@dates) {
34_ESPEasy.pm:    } # foreach $attr
34_ESPEasy.pm:  } # foreach $subtype
41_OREGON.pm:  foreach $i (@res){
42_SYSMON.pm:        foreach $d (@dataThroughput) {
46_SmartPi.pm:        foreach $dataset (@{$decode_json->{datasets}}) {
46_SmartPi.pm:                foreach $phase (@{$dataset->{phases}}) {
46_SmartPi.pm:                        foreach $value (@{$phase->{values}}) {
46_TRX_WEATHER.pm:  foreach $i (@res){
49_SSCam.pm:      foreach $fn (sort keys %{$data{webCmdFn}}) {
49_SSCam.pm:      foreach $fn (sort keys %{$data{webCmdFn}}) {
49_SSCam.pm:                        foreach $pkey (keys%{$dat}) {
49_SSCam.pm:                        foreach $pkey (@unique) {
57_CALVIEW.pm:                  foreach $event (@{$extDevHash->{CHANGED}}) {
70_BRAVIA.pm:                foreach $key ( keys %{ $_ }) {
70_BRAVIA.pm:              foreach $key ( keys %{ $_ }) {
70_BRAVIA.pm:              foreach $key ( keys %{ $_ }) {
70_BRAVIA.pm:              foreach $key ( keys %{ $_ }) {
70_BRAVIA.pm:              foreach $key ( keys %{ $_ }) {
70_BRAVIA.pm:              foreach $key ( keys %{ $_ }) {
70_NEUTRINO.pm:                         foreach $line (@ans)  {
70_NEUTRINO.pm:                         foreach $line (@ans)  {
70_NEUTRINO.pm:                         foreach $line (@ans)  {
70_NEUTRINO.pm:                         foreach $line (@ans)  {
71_YAMAHA_AVR.pm:    foreach $item (@commands)
71_YAMAHA_MC.pm:        foreach $dev (@dev_list) {
71_YAMAHA_MC.pm:    foreach $item (@commands) {
72_FB_CALLLIST.pm:        foreach $index (@list)
72_FB_CALLLIST.pm:            foreach $line (@item_list)
76_SMAPortal.pm:  foreach $i (1..$maxhours-1) {
76_SMAPortal.pm:          foreach $i (0..$maxhours-1) {                                # keine Anzeige bei Null Ertrag bzw. in der Nacht , Typ pcvo & diff haben aber immer Daten in der Nacht
76_SMAPortal.pm:      foreach $i (0..$maxhours-1) {
76_SMAPortal.pm:  foreach $i (0..$maxhours-1) {
79_BDKM.pm:            foreach $i ((0,1)) {
79_BDKM.pm:            foreach $weekday (qw(Mo Tu We Th Fr Sa Su)) {
88_HMCCU.pm:            foreach $a (sort keys %attrlist) {
88_HMCCU.pm:            foreach $a (sort keys %attrlist) {
88_HMCCU.pm:                    foreach $a (sort keys %attrlist) {
88_HMCCU.pm:                    foreach $a (sort keys %attrlist) {
89_VCLIENT.pm:  foreach $cmd (keys %set_hash){
93_DbRep.pm:      foreach $row ( @rows ) {
93_DbRep.pm:      foreach $row ( @rows ) {
93_DbRep.pm: foreach $tablename (@tablenames) {
93_DbRep.pm: foreach $tablename (@tables) {
93_DbRep.pm:                     foreach $inhalt(@ar) { $a .= $dbh->quote($inhalt).","; }
93_DbRep.pm:  foreach $tablename (@tablenames) {
93_RFHEM.pm:                            foreach $extevent (@{$extDevHash->{CHANGED}}) { #für jedes event des externen device / dort geänderte readings
93_RFHEM.pm:                            foreach $extevent (@{$extDevHash->{CHANGED}}) { #für jedes event des externen device / dort geänderte readings
93_RFHEM.pm:                                    foreach $event (@myevents) { # mit jedme event aus rhfme attribut
95_YAAHM.pm:          foreach $fline (@lines){
95_YAAHM.pm:        foreach $fline (@lines){
95_YAAHM.pm:        foreach $line (@lines){
98_alarmclock.pm:                        foreach $line (@lines)
98_alarmclock.pm:                    foreach $fline (@lines)
98_archetype.pm:    foreach $room (
98_DOIF.pm:        foreach $j (split(" ",$hash->{timers}{$i})){
98_DOIF.pm:        foreach $j (split(" ",$hash->{timers}{$i})) {
98_DOIF.pm:    foreach $device ("$dev->{NAME}","") {
98_DOIF.pm:      foreach $device ("$dev->{NAME}","") {
98_DOIF.pm:    foreach $device ("$dev->{NAME}","") {
98_DOIFtools.pm:      foreach $i (sort keys %da) {
98_help.pm:  foreach $l (@text) {
98_HTTPMOD.pm:        foreach $num (@{$hash->{".readingParseList"}}) {
98_Modbus.pm:    foreach $nextObj (sort Modbus_compObjKeys keys %readList) {
98_MSwitch.pm:    foreach $seq ( keys %{$delays} )
98_MSwitch.pm:                          foreach $seq ( sort{$b <=> $a} keys %{$log} )
98_MSwitch.pm:                                 "$name:  foreach  $_  | count - $count" );
98_MSwitch.pm:  foreach $seq ( sort{$b <=> $a} keys  %{$log} )
98_MSwitch.pm:          foreach $seq ( sort keys  %{$log} )
98_MSwitch.pm:          foreach $seq ( sort keys  %{$log} )
98_readingsWatcher.pm:  foreach $deviceName (devspec2array("readingsWatcher!="))
98_readingsWatcher.pm:  foreach  $deviceName (@devs)
98_readingsWatcher.pm:  } # foreach $deviceName
98_Text2Speech.pm:    foreach $devname (devspec2array("TYPE=PRESENCE")) {
AttrTemplate.pm:    foreach $entry (sort keys %templates) {


Die CPAN module, die das machen, lassen wir unter den Tisch fallen.

Zitat
Für jemanden, der sich selten mit Perl beschäftigt (wie ich), ist natürlich schon überraschend und wenn man das nicht weiß, wird man hier ganz schön lange suchen müssen. So etwas fördert bei mir jedenfalls nicht die (nicht vorhandene) Zuneigung zu Perl.

Deswegen bringe ich das ja. Es ist sicher für viele überraschend, aber sobald man sich vergegenwärtigt, dass das unter die Spezifikation des Verhaltens von for fällt, löst sich die scheinbare Inkonsistenz in Wohlgefallen auf: Man glaubte nur die Spezifikation von for zu kennen.

Von daher ist das mit den Zuneigungen schon ok, wir haben alle unsere individuellen Vorlieben. Meine vorhandene explizite Abneigung gegen Java ist ja schliesslich der Grund warum ich hier und nicht bei OpenHAB bin.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

Wzut

#10
Zitat von: RichardCZ am 30 März 2020, 09:35:22
Ach ja, und man sollte for und nicht foreach schreiben... da fällt mir ein ... oh "holy sh*t":
das wirst du in einem extra Kapitel auch nochmal näher beleuchten müssen, ich liebe foreach komme aber nur 1x in der Blacklist damit vor ? ? ?
Edit : ach es geht nicht um foreach sondern das fehlende my ....
BTW: und dann verrate doch auch noch an passender Stelle den Perlcritic Trick mit --verbose 11 für die jenigen die das Buch nicht haben :)
 
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

CoolTux

Zitat von: Wzut am 30 März 2020, 09:44:03
das wirst du in einem extra Kapitel auch nochmal näher beleuchten müssen, ich liebe foreach komme aber nur 1x in der Blacklist damit vor ? ? ?
BTW: und dann verrate doch auch noch an passender Stelle den Perlcritic Trick mit --verbose 11 für die jenigen die das Buch nicht haben :)


Ich gehe davon aus weil Du foreach nur einmal über ein Array laufen lassen hast.
Bei einem Hash scheint es ok zu sein.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

RichardCZ

Zitat von: Wzut am 30 März 2020, 09:44:03
Edit : ach es geht nicht um foreach sondern das fehlende my ....

Es geht um beides und for my ist sogar kürzer als foreach  ;)
Das man immer "my" verwenden sollte, erwähnt PBP auf Seite 108 - 110 auch. Grund wie oben, bzw. wie folgt:

my $element;              # Hier denke ich ganz brav zu sein und meine Variable deklariert zu haben
for $element (@menge) {   # Hier denke ich, bzw. jemand anderes der den Code liest das obige $element zu verwenden - was falsch ist
<blah>
}
my $ergebnis = $element * 5; # hier denke ich mir auch irgendwas, aber 5 * undef ist immer noch undef


Dass man for und nicht foreach verwenden sollte ergibt sich aus der o.g. Dokumentation (https://perldoc.perl.org/perlsyn.html#For-Loops) und auch PBP schlägt das vor. Ich zitiere aus der Perl Doku:

ZitatThe foreach keyword is actually a synonym for the for keyword, so you can use either.

Wer sich bei diesem Satz auf das Wort either und nicht auf das Wort synonym festbeisst (und dabei auch mal übersieht was ein Synonym für was ist), hat das mit den best practices noch nicht komplett verinnerlicht.
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.

CoolTux

Ist es generell zu empfehlen statt foreach for zu nehmen? Auch bei Hash zum Beispiel?
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

RichardCZ

Zitat von: CoolTux am 30 März 2020, 10:14:40
Ist es generell zu empfehlen statt foreach for zu nehmen? Auch bei Hash zum Beispiel?

Bei allem. Immer. Ich schreibe noch einen separaten Thread zum Thema (gleiche Geschichte für andere Keywords).
Witty House Infrastructure Processor (WHIP) is a modern and
comprehensive full-stack smart home framework for the 21st century.