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