cs 105 perl completing the toolbox
play

CS 105 Perl: Completing the Toolbox Curtis Dunham March 4, 2013 - PowerPoint PPT Presentation

CS 105 Perl: Completing the Toolbox Curtis Dunham March 4, 2013 Curtis Dunham CS 105 Perl: Completing the Toolbox Agenda autodie with open Inspecting scalars perl -c Unary coercion Topicalization ~~ Unique list idiom Schwartzian


  1. CS 105 Perl: Completing the Toolbox Curtis Dunham March 4, 2013 Curtis Dunham CS 105 Perl: Completing the Toolbox

  2. Agenda autodie with open Inspecting scalars perl -c Unary coercion Topicalization ~~ Unique list idiom Schwartzian Transform Using // for defaults and memoization Code references and closures Curtis Dunham CS 105 Perl: Completing the Toolbox

  3. open review We’ve covered opening files for reading and writing: open my $reader, ’<’, "file" or die... open my $writer, ’>’, "output" or die... The names of the file handles are not special; they are merely chosen for pedagogical value. Curtis Dunham CS 105 Perl: Completing the Toolbox

  4. open and pipes open can be used to run programs that we can read from via pipes or to run programs that we can write to via pipes. # read from another program open my $reader, ’-|’, "/path/to/command" or die... # write to another program open my $writer, ’|-’, "/path/to/command" or die... To supplement perldoc -f open , consider perldoc perlopentut for more complete coverage of the power of open with good explanations. Curtis Dunham CS 105 Perl: Completing the Toolbox

  5. autodie Checking the return values of every open can be very tedious and repetitive. The autodie pragma handles this responsibility automatically. use autodie; open my $f, ’<’, "filename"; # this is ok... # because autodie will... # automatically die in case of failure. autodie is similar to warnings in that it is lexical with many knobs you can adjust. See perldoc autodie . Curtis Dunham CS 105 Perl: Completing the Toolbox

  6. Filehandle references are handy Since Perl is reference counted, we can depend on variable scoping to automatically close files. use IO::Handle; use autodie; { open my $file, ’>’, ’outputFile’; $file->say(’Blarg, I say.’); # ... } # $file out of scope and therefore closed! Note that to use the IO::Handle methods on the file object, you will need to load that module. Curtis Dunham CS 105 Perl: Completing the Toolbox

  7. Another cute open feature Perl allows a filehandle to actually refer to a scalar (e.g. for output buffering or reading from slurped data). use IO::Handle; use autodie; our $dump; { open my $file, ’>’, \$dump; $file->say(’Blarg into a scalar’); # ... } # use $dump at some point... Curtis Dunham CS 105 Perl: Completing the Toolbox

  8. What type of reference is this? Given some arbitrary scalar, how can you tell if it is a reference? What type of a reference is it? Is it an object (a blessed reference)? Is it some other type of reference? Perl provides the ref function to help answer these questions. ref will return false if the scalar is not a reference. If the reference is blessed, ref will return the package (i.e. class) name. Otherwise, the type of reference will be returned (as a string): e.g. SCALAR , ARRAY , and so on (see the documentation for further details). Curtis Dunham CS 105 Perl: Completing the Toolbox

  9. Is this reference blessed? The Scalar::Util module (part of the Perl core; i.e. it “comes with” Perl) includes the function blessed . use Scalar::Util qw(blessed); $obj = bless [], "Foo"; $class = blessed $obj; # "Foo" blessed will return undef if the scalar is not a blessed reference (e.g. an unblessed reference or some other scalar value). Curtis Dunham CS 105 Perl: Completing the Toolbox

  10. reftype You might want to know what type of reference is in a scalar regardless of whether it’s blessed or not. Scalar::Util has a function for this, too: reftype . Curtis Dunham CS 105 Perl: Completing the Toolbox

  11. perl -c You can use perl -c to do a syntax check on your program without running it. % perl -c broken-script syntax error at broken-script line 6, near "print" broken-script had compilation errors. % Curtis Dunham CS 105 Perl: Completing the Toolbox

  12. Unary coercions # numeric my $number = 0 + $whatever; # string my $string = ’’ . $whatever; # boolean my $bool = !! $whatever; Curtis Dunham CS 105 Perl: Completing the Toolbox

  13. Unary coercion in hash key brackets $words{lc}++; # ’lc’. oops. $words{+lc}++; # evaluate lc (function!) # normally not necessary $words{$obj->method(’foo’) - 10} = baz(); Curtis Dunham CS 105 Perl: Completing the Toolbox

  14. Truth Trickery Sometimes we would like a zero value to still be interpreted as true in a boolean context (perhaps in the sense of “success”). These values evaluate to 0 in a numeric context, but aren’t one of the five false values. $a = ’0e0’; $b = ’0e’; $c = ’0.0’; $d = ’0 but true’; # chatty Curtis Dunham CS 105 Perl: Completing the Toolbox

  15. Using given for topicalization given implicitly sets $_ to its argument. given ($important) { s/_+//g; say; } This code won’t modify $important , but it allows us to do something with it with both brevity and safety. Curtis Dunham CS 105 Perl: Completing the Toolbox

  16. given -less when You can use the magic of when ( ~~ and more) in a for loop, too! my $count; my $v = 0; for (@a) { when($v) { ++$v } say "Nope, not that one."; } say "Made it to $v"; This only works when not specifying an iteration variable (i.e. using default $_ ). The when block has an implicit next at the end. Curtis Dunham CS 105 Perl: Completing the Toolbox

  17. ~~ is the operator behind the curtain Many of you have already used ~~ without realizing it! In a given / when construct, the left-hand operand is provided by given and the right-hand operand is provided by the when . Curtis Dunham CS 105 Perl: Completing the Toolbox

  18. Explicit use of ~~ ~~ is the smart match operator (new in Perl 5.10). It is a kitchen-sink style polymorphic operator that determines whether the two operands “match” in some dwimmy way. Here are some of its default behaviors: $a ~~ undef # true if $a is undef $a ~~ /$b/ # same as =~ @a ~~ /$b/ # grep /$b/, @a %a ~~ /$b/ # grep /$b/, keys %a $a ~~ @b # grep { $a ~~ $_ } @b %a ~~ %b # hash keys identical This is just a small subset of all the behaviors ~~ has. The perlsyn page lists all of its behaviors. Curtis Dunham CS 105 Perl: Completing the Toolbox

  19. Getting unique elements in a list my %uniq; undef @uniq{ @items }; my @uniques = keys %uniq; # makes a nice little subroutine sub uniq { my %u; undef @u{@_}; return keys %u; } Curtis Dunham CS 105 Perl: Completing the Toolbox

  20. Schwartzian Transform The Schwartzian Transform is a Perl sorting idiom devised by Randal Schwartz. Sometimes we want to sort a list of things by some arbitrary function of the elements. This can be troublesome if the function is very expensive–say, computationally, or if involves I/O in some way. Randal’s solution is to create a list of anonymous arrays, where each original list element is paired with the value that will be used for sorting. # first step of Schwartzian Transform @x = map { [ $_, -s $_ ] } @files; Curtis Dunham CS 105 Perl: Completing the Toolbox

  21. Schwartzian Transform Continued @x = map { [ $_, -s $_ ] } @files; So now we have an array of 2-tuples (file name and file size, stored in anonymous arrays) that we want to sort using the second element of the tuple. @y = sort { $a->[1] <=> $b->[1] } @x; Now our data is sorted, but our data is stuck in that messy thing. Let’s rescue it. @z = map { $_->[0] } @y; # @z is our sorted list of files! Curtis Dunham CS 105 Perl: Completing the Toolbox

  22. Schwartzian Transform: All Together Now We just stick the code samples together in reverse order, eliminating the temporary arrays. @sorted_files = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, -s $_ ] } @files; Once you get past the punctuation (I understand this is still a stumbling block for some of you), it’s actually quite simple. We keep the sorting data with the data to be sorted so that we only compute it once. Then we remove that extra data when we no longer need it. Curtis Dunham CS 105 Perl: Completing the Toolbox

  23. || revisited The or operator ( || , or or for a very low precedence version of the same) is a good way to inject a default. sub new { my $class = shift; my %params = @_; bless { _foo => $params{foo} || 10, _bar => $params{bar} || ’bar’, _baz => $params{baz} || [ qw(a b c) ], }, $class; } Curtis Dunham CS 105 Perl: Completing the Toolbox

  24. // is better here The // (“defined-or”) operator works like || except that it uses a definedness test rather than truth. use v5.10; sub new { my $class = shift; my %params = @_; bless { _foo => $params{foo} // 10, _bar => $params{bar} // ’bar’, _baz => $params{baz} // [ qw(a b c) ], }, $class; } Curtis Dunham CS 105 Perl: Completing the Toolbox

  25. Another use for || and // Sometimes we might use a hash as a “cache” for some computation, but we want to load it lazily (on demand). This idiom is common in this case: my $a = $foo{$val} //= foo($val); Assignment is right-associative, so the statement evaluates like this: my $a = ($foo{$val} //= foo($val)); If a value exists in the hash, we can just use it; otherwise we can use the function foo to compute the value, store it in the hash, and also put it in $a . Curtis Dunham CS 105 Perl: Completing the Toolbox

Recommend


More recommend