2012 hatte ich einen Vortrag ausgearbeitet, der hieß "Vom Spaghetti-Code zur wartbaren Software". Ich hatte viel zu viel Material gesammelt. Den 2. Teil der Sammlung beinhaltet dieser Vortrag. Und einige neu gesammelte Dinge sind natürlich auch dabei.
perl -e 'use Devel::Peek; Dump 1 == 1'
und
perl -e 'use Devel::Peek; Dump 0 == 1'
Devel::Peek schaut in den Bauch einer Perl-Datenstruktur.
SV - Scalar value Flags IOK -> int gültig NOK -> numeric gültig POK -> pointer auf String gültig READONLY -> 0 == 1 = 1 geht eben nicht zu schreiben IV = 1 -> int ist 1 NV = 1 -> numeric ist 1 PV -> es liegt ein string auf Adresse 0x... mit dem Wert "1" mit \0 abgeschlossen CUR = 1 -> Der string hat eine Länge von 1 LEN = 1 -> Die gesamte Datenstruktur hat eine Länge von 8 Bytes
Für viele, die aus anderen Programmiersprachen kommen, ist schon mal völlig unklar, wie ein Scalar gleichzeitig mehrere gültige Werte (String, Numeric, Integer) beinhalten kann.
"https://metacpan.org/module/Scalar::MultiValue" ist ein Modul, mit dem man das aktiv machen kann.
|| && and or
macht das nicht. Hier wird der rechte Teil der Anweisung nicht boolsch evaluiert.
Deswegen ergibt
50 && 100
100 und nicht nur einen wahren Boolean.
Dual-Value numerisch verwenden
$boolean = !! $any; $numeric = 0 + $boolean; $string = q{} . $boolean; 0 + !! 'bla' 0 + !! ( $result && $result->event )
my $is_y = $x eq 'y' ? 1 : 0; print $is_y;
An der Schnittstelle "Numeric output" konvertieren.
my $is_y = $x eq 'y'; print 0 + $is_y;
Jedes Element kommt als $_ (Alias) der Reihe nach im map-Block an.
Das Ergebnis der letzten Anweisung ist der Wert,
welcher weitergereicht wird.
@destination = map { my $name = "${_}suffix"; $name; } @source; @destination = map { "${_}suffix" } @source;
@destination = map { $_ if defined; } undef, 2; # is: q{}, 2
Das Ergebnis der letzten Anweisung wird boolsch verarbeitet
- wahr: Element wird weitergeleiet.
- falsch: Element wird nicht weitergeleitet.
@destination = grep { $_ < 10; } @source;
@destination = map { $_ < 10 ? $_ # 1 Element weiterleiten : (); # 0 Elemente weiterleiten } @source;
%destination = map { defined ? ( $_ => undef ) # 2 Elemente weiterleiten : (); # 0 Elemente weiterleiten } @source;
Es sammelt wieder ein.
$string = join ', ', map { m{ ( \S+ ) }xmsg; } ( 'foo bar', 'baz', ); # foo, bar, baz
map { print "$_\n"; } @array for my $element (@array) { print "$element\n"; }
my @destination; for my $element (@source) { push @destination, $element x 2; } my @destination = map { $element x 2; } @source;
my @destination; for my $element (@source) { push @destination, { $element => shift @source }; } my @destination; while ( my ($key, $value) = splice @source, 0, 2 ) { push @destination, {$key, $value}; }
@destination = map { "$_\n"; } grep { length; } grep { defined; } @source;
@destination = map { defined && length ? "$_\n" : (); } @source;
Der Begriff taucht im Netz meist in Verbindung mit Perl auf, wie z.B. hier: http://www.ims.uni-stuttgart.de/~zinsmeis/Perl/material/ho_referenzen_040123.pdf
$ref = \@array; # arrayref $ref = [ 1 .. 10 ]; $ref = \( 1 .. 10 ); # \10
"code ${ \( $obj->method ) } in string" "code @{ [ $obj->method ] } in string"
$obj->method $obj->$string $obj->$coderef $obj->${ \"get_$name" } $obj->${ \( call_a_sub(...) ) }
my $chars = '.,[{'; my $string = "Weiter mit $chars foo."; $is_match = $string =~ m{ \QWeiter mit\E }xms; $is_match = $string =~ m{ \s+ \Q$chars\E \s+ }xms;
\Q => quotemeta \L => lc \l => lcfist \U => uc \u => ucfirst \E => Ende
'abc' x 2; # abcabc ( 'abc' ) x 2 # ( 'abc', 'abc');
$index = index 'aa bb cc', 'bb'; # 3 $index = rindex 'aa bb cc', 'bb'; # 3 $substr = substr 'aa bb cc', 3, 2; # 'bb' $substr = substr 'aa bb cc', -5, 2; # 'bb' $string ~~ [ qw( a b c ) ]; no warnings qw(numeric); $numeric = -'123.456-'; # -123.456
require 5.010; # version check # not use 5.010 for features require PackageName; do { expr1; expr2; }; do 'include.pl'; shift shift @ARGV shift @_ eval { expr1; expr2; } eval $string;
die 'Error'; # Error at [file] line [line]. die "Error\n"; # Error die 'Error', "\n"; # Error die; # Died at [file] line [line]. die "\n"; # \n
confess 'Error', 123; # Error123 at [file] line [line]. # \tPackage::sub(parameterlist) at [file] line [line] confess 'Error', "\n"; # Error # at [file] line [line].
use Carp qw(confess); use Moose; # imports confess
# ok my $bytes = read_file( 'foo/bar/filename', binmode => ':raw', ); # not ok my $unicode = read_file( 'foo/bar/filename', binmode => ':encoding(cp1252)', );
use Path::Class qw(file); my $unicode = file( qw( foo bar filename ) ) ->slurp( iomode => '< :encoding(cp1252)' );
use Path::Class qw(dir file); my $unicode = file( dir('./')->subdir( qw( foo bar ) )->absolute, 'filename', ) ->slurp( iomode => '< :encoding(cp1252)' );
use Path::Class::Rule; my @html_filenames = Path::Class::Rule ->new ->file ->name( qw( *.htm *.html ) ) ->all( $dir );
use syntax qw(method function); fun foo ($parm) { return $parm; } method bar ($param) { return $self->baz($param); }
Designertauglich und mit W3C-Validator validierbar.
... <title></title> ... <tr class="z-result"> <td class="z-name">dummy name</td>
use HTML::Zoom; my $zoom = HTML::Zoom ->from_file('example.html');
$zoom = $zoom ->replace_content( title => 'Example' ) ->select('.z-result') ->repeat([ map { my $result_ref = $_; sub { return $_->replace_content( '.z-name' => $result_ref->{name}, ) } } @{$results_ref} ]);
print $zoom->to_html;
siehe Verzeichnis "example" in https://metacpan.org/release/Data-Page-Pagination