Jemand zu Hause?
2021-10-27T07:35:39 biancaGuten Morgen!
Angenommen ich habe eine sub in der es eine Variable $back gibt. Nun möchte ich, dass return 0 gefeuert wird sobald $back sich ändert, um mir Quellcode zu sparen. Gibt es das in Perl >= 5.30.2?
perlfunc tie (etwas umständlich) oder komfortabler mit dem Modul
Variable::Magic. Komfortabler deswegen, weil Du nur für das "interessante" Ereignis Code schreiben musst, während du bei tie (oder dem zugehörigen Core-Modul
Tie::Scalar) eine Klasse für alle Zugriffe auf $back erstellen musst. Gleich das erste Code-Stück in der Synopsis von Variable::Magic enthält ein Beispiel für eine Aktion beim Setzen einer Variablen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
#!/usr/bin/perl use warnings; use strict; sub func1 { my $back = shift; if ($back == 1) { print "\$back is true.\n"; return 0; } print "Doing something else.\n"; } sub controlBack { my $count = shift; if ($count < 10) { return 0; } else { return 1; } } # Defining start-settings for MainLoop: my $running = 1; my $count = 0; my $back = 0; # Running the MainLoop: while ($running) { $back = controlBack($count); func1($back); $count++; if ($count > 20) { $running = 0; } } print "Program ends.\n";
Tk oder
SDL im Spiel ist, dann möchte ich ergänzen:
Tk::Entry die Referenz auf eine Variablen als -textvariable angibst, dann ist das eigentliche Ereignis die Benutzereingabe - und die Änderung der Variablen ist eine Konsequenz daraus. Da ist es besser, ein Tk-Ereignis zu benutzen und nicht eins auf die Variable draufzuschrauben. Bei einer Benutzereingabe in Tk::Entry hat man dafür entweder einen
Tk::Button, mit dem der Benutzer die Eingabe abschließt, oder wenn man darauf nicht warten will, KeyPress-Ereignisse, so wie man's bei einem
Tk::Text-Widget macht.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#!/usr/bin/perl use strict; use warnings; use 5.010; my $test = unterprog(); say "Erg.: ".(defined $test ? $test : ''); sub unterprog { my $back = 0; # hier möchte ich eine Art Handler platzieren: handler_variable ($back ne '0') { # hier passiert noch mehr return $back; } # hier folgt jetzt viel Code # und bei jedem Kommando kann es zu Fehlern kommen # und immer wenn das passiert soll quasi ein return # ausgeführt werden # z. B.: unlink('diese_datei_gibt_es_aber_nicht') or $back = "$! in ".__LINE__; # bitte nicht auf das Beispiel antworten, # das ist wie vesagt nur ein BEISPIEL # um das selbe Ergebnis ohne den Handler # zu erreichen müsste ich schreiben: unlink('diese_datei_gibt_es_aber_nicht') or do { $back = "$! in ".__LINE__; # wir nehmen an, dass hier mehr passiert # als nur diese Zuweisung return $back; }; return "Ende erreicht mit \$back='$back'"; }
perlfunc eval und
perlfunc die sowie mit vielen CPAN-Modulen, die das ganze weniger fehleranfällig machen, der aktuelle Favorit ist
Try::Tiny, oder ab Perl 5.34 das "eingebaute" try/catch.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
#!/usr/bin/perl use strict; use warnings; use 5.010; use autodie; # Perl core Modul use Try::Tiny; my $test = unterprog(); say "Erg.: ".(defined $test ? $test : ''); sub unterprog { try { # Nun kann man auch selbst Fehlerereignisse auslösen: $ARGV[0] or die "Nur wahre Argumente, bitte!"; # hier folgt jetzt viel Code # und bei jedem Kommando kann es zu Fehlern kommen # und immer wenn das passiert soll quasi ein return # ausgeführt werden # z. B.: unlink('diese_datei_gibt_es_aber_nicht'); # bitte nicht auf das Beispiel antworten, # das ist wie vesagt nur ein BEISPIEL } # hier möchte ich eine Art Handler platzieren: catch { # hier passiert noch mehr return $_; }; }
autodie verwendet. Das ändert das Verhalten von Systemschnittstellen (also denen, die im Fehlerfall undef zurückgeben und den Fehler in $! liefern) so, dass statt dessen das ein Fehlerereignis ausgelöst wird. Deswegen habe ich noch ein Beispiel hinzugefügt, wie das aussieht, wenn Du selbst einen Fehler auslösen willst. Wenn Du das Programm ohne Argumente (oder mit einer Null als Argument) aufrufst, dann schlägt das die zu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
try { # Nun kann man auch selbst Fehlerereignisse auslösen: $ARGV[0] or die "Nur wahre Argumente, bitte!"; my $testvariable_fuer_testfehler; my $btest = $testvariable_fuer_testfehler + 3; # hier folgt jetzt viel Code # und bei jedem Kommando kann es zu Fehlern kommen # und immer wenn das passiert soll quasi ein return # ausgeführt werden # z. B.: unlink('diese_datei_gibt_es_aber_nicht'); # bitte nicht auf das Beispiel antworten, # das ist wie vesagt nur ein BEISPIEL }
strictures die Warnungen in fatale Fehler umwandeln (oder auch mit
warnings, aber dazu muss man sich gut in den Warnungs-Kategorien auskennnen).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#!/usr/bin/perl use warnings; use strict; my $a = 5; my $b = 0; try { print $a / $b; } catch { print "Error: Division by zero.\n"; } # Dies macht doch dasselbe: if ($b != 0) { print $a / $b; } else { print "Error: Division by zero.\n"; }
2021-11-14T13:32:46 hlubenowDann wolltest Du (bianca) im Prinzip also nur eine normale if-Abfrage?
Tipp zum Debugging