=head2 Perl 6 Idioms, and Idiomatic Perl 6 =head4 (Butterflies of the world, alight!) Perl is a richly expressive language, with a warm and playful community. When someone crafts a succinct way to solve a common problem, the Perl community often adopts that solution's phrasing as a idiom. (Other-times, the community recoils in horror and proposes a less obtuse phrasing.) Perl 6 adds many elements to the language, and not just keywords; there are metaoperators, clean exceptions, new contexts, better interpolation, frugal OO, and much more. Those additions were shaped by patterns of Perl 5 use (with an eye to future uses), so at least one should scratch some itch you have long ignored. The new bits aren't required, but we like the shiny, so be prepared for a slew of new idioms soon after L. Most Perl 6 idioms will not just be translated versions of familiar Perl 5 idioms; they will use new features where appropriate, and may seem unfamiliar at first. If you regularly use any of the Perl 5 idioms below, you can expect to grok its new form soon after you embrace Perl 6 itself. Idiomatic Perl 6 should feel just as Perlish as Perl 5, once you get used to it. After all, it is all B. =head2 Conventions =head4 (Details, details) Definitions (corrupted^W adapted for computer languages): =over 4 =item Idiom A phrase B to be used to express an idea. =item Idiomatic Expressed as the language's B users would state it. =back In most examples below, the code is shown in four versions: =over 4 =item 1. Non-idiomatic Perl 5, =item 2. then made idiomatic. =item # =item 3. Perl 5 idiom, naively translated into Perl 6, =item 4. then made idiomatic. =back Any versions past #4 are to show L. Notice how the code gets clearer or more concise as it goes from 1 to 4. =head2 Idiom ==> Word =head4 (Movin' on up) Some Perl 5 idioms were so useful and conceptually concise, that they became Perl 6 "words" in their own right. These words take the form of new built-in operators, functions, and methods. # Pick a random array element $z = $array[ int(rand scalar(@array)) ]; $z = $array[ rand @array ]; # $z = @array[ rand*@array ]; $z = @array.pick; # Loop over the keys (indexes) of an array for ( my $i=0; $i<@array; $i++ ) {...} for my $i ( 0 .. $#array ) {...} # for 0 .. @array.end -> $i {...} for @array.keys -> $i {...} # Whole number division ( ($x - ($x % 3) ) / 3 ) int( $x / 3 ) # Int( $x / 3 ) $x div 3 # Integer division op # Print the count of the elements of an array. say scalar @array; say 0+@array; # say 0+@array; # Identical in Perl 6 say +@array; # + forces the new "numeric" context say @array.elems; # .elems method is more explicit. # Do something every 5th time if ( ($x/5) == int($x/5) ) {...} if ( !($x % 5) ) {...} # if !($x % 5) {...} if $x %% 5 {...} # %% means "is evenly divisible by" # Do something $n times, counting up to $n-1 for ( $_=0; $_ < $n; $_++ ) {...} for ( 0 .. ($n-1) ) {...} # for 0 ..^ $n {...} for ^$n {...} # ^9 means 0 ..^ 9, or 0..8 Bare method calls are *always* methods on C<$_>, eliminating Perl 5's confusion on which functions default to C<$_>. Other defaults have been tweaked to move from something-else-I-must-remember to obvious. # Split on whitespace @words = split /\s+/, $_; @words = split; # Default is useful, but not intuitive # @words = .split(/\s+/); # split() now has no default pattern @words = .words; # The old default split is now a method # Split a string into individual characters. @chars = map { substr $word, $_, 1 } 0..length($word); @chars = split '', $word; # Split on nothingness # @chars = $word.split(''); @chars = $word.comb; # Default is to "keep everything" # Infinite loop for (;;) {...} # Spoken with a 'C' accent while (1) {...} # while 1 {...} loop {...} # No limit given, so endless by default Some idioms that became words were already words in Perl 5, if you used the appropriate module. # Return the unique elements from a list, in original order my %s, @r; for @a { push @r, $_ if !$s{$_}; $s{$_}++; } return @r; my %s; return grep { !$s{$_}++ } @a; # or List::MoreUtils::uniq # my %s; return grep { !%s{$_}++ }, @a; return @a.uniq; # Add up all list elements my $sum = 0; for my $num (@a) { $sum += $num } my $sum; $sum += $_ for @a; # or List::Util::sum # my $sum = @a.reduce(*+*); my $sum = [+] @a; # [op] applies op to entire list =head2 Idiom ==> Idiom =head4 (The song remains the same) Some idioms remain the same, modulo required syntax changes. @alpha = 'A' .. 'Z'; @a = qw{ able baker charlie }; %meta = ( foo => 'bar', baz => 'quz' ); @squares = map { $_ * $_ }, @a; @starts_with_number = grep { /^\d/ }, @a; Didn't those all look familiar? Sure, parenthesis are no longer needed on list assignment, and qw{} now has a an angle-bracket shortcut, but those are optional, and don't really change the gist of the idioms. Add that comma after the map|grep block, and these Perl 5 idioms still stand strong in Perl 6. Perl 5's "magic diamond" idiom still exists, just spelled more sanely (and less diamond-ly). # Process each line from STDIN or from command-line files. for my $file (@ARGV) { open FH, $file; while () {...} } while (<>) {...} # Null filehandle is magical # for @*ARGFILES.lines {...} for lines() {...} # lines() defaults to $fh = $*ARGFILES =head2 Idiom 5 ==> Idiom 6 =head4 (The more things change, the more they remain the same) Some idioms have taken new form, when the idea behind the original idiom found better expression through new language elements. # Hash initialization to constant my %h; for (@a) { $h{$_} = 1 } my %h = map { $_ => 1 } @a; # my %h = map { $_ => 1 }, @a; my %h = @a X=> 1; # Hash initialization for enumeration my %h; for (0..$#a) { $h{ $a[$_] } = $_ } my $c; my %h = map { $_ => ++$c } @a; # my $c; my %h = map { $_ => ++$c }, @a; my %h = @a Z=> 1..*; my %h = @a.pairs».invert; # if zero based # Hash initialization from parallel arrays my %h; for (@a) { $h{$_} = shift @b } my %h; @h{@a} = @b; # my %h; %h{@a} = @b; my %h = @a Z=> @b; # Swap two variables my $temp = $x; $x = $y; $y = $temp; ( $x, $y ) = ( $y, $x ); ( $x, $y ) = $y, $x; # ( $x, $y ) .= reverse; # .= makes reverse into a "mutating" method # Tastes great on array swaps, too! @a[ $j, $k ] .= reverse; # Rotate array left by 1 element my $temp = shift @a; push @a, $temp; push @a, shift @a; # @a.push: @a.shift; @a .= rotate; # Create an object my $pet = new Dog; my $pet = Dog->new; # my $pet = Dog.new; my Dog $pet .= new; # $pet *always* isa Dog; Compiler can optimize! Combining transformation with selection was an advanced idiom in Perl 5. The new return values for C provide a bite-sized idiom. # Three copies of elements > 5 @z = map { ($_) x 3 } grep { $_ > 5 } @y; # map,grep @z = map { $_ > 5 ? ($_) x 3 : () } @y; # map as grep # @z = map { $_ > 5 ?? ($_) xx 3 !! Nil }, @y; @z = @y.map: { $_ xx 3 if $_ > 5 }; # !if == Empty list @z = ($_ xx 3 if $_ > 5 for @y); # List comprehension That fifth form is a L, popular in functional languages, and in our L. =head2 Sentence|Paragraph ==> Idiom =head4 (The territory becomes the map) Some larger code blocks can now be expressed so concisely that they become idioms in their own right. # Random integer between 3 and 7 inclusive do { $z = int rand 8 } until $z >= 3; $z = 3 + int rand 5; # $z = 3 + Int(5.rand); $z = (3..7).pick; # Count by 3 in an infinite loop for ( my $i = 1; ; $i++ ) { my $n = 3 * $i; ... } for ( my $n = 3; ; $n += 3 ) {...} # loop ( my $n = 3; ; $n += 3 ) {...} for 3, * + 3 ... * -> $n {...} # `...` is the "sequence" operator for 3, 6, 9 ... * -> $n {...} # `...` can infer from example list # Loop over a range, excluding the start and end points for my $i ( $start .. $limit ) { next if $i == $start or $i == $limit; ... } for my $i ( ($start+1) .. ($limit-1) ) {...} # for ($start+1) .. ($limit-1) -> $i {...} for $start ^..^ $limit -> $i {...} =head2 Predictions =head4 (Gaze into my crystal ball) (Still writing this part) Predictions for how idiomatic Perl 6 will be influenced by other design elements, after Christmas Coders get a much earlier intro to exceptions, via open(), so they are more likely to design using exceptions! More use of slicing, since single-element hash|array access is just a degenerate form of multiple-element access. ».methods for parallelism with set-at-a-time thinking lazy lists more mixing of procedural&OO&functional paradigms due to code blocks and OO being "cheaper" DSL modules just to talk more sanely about your problem. =cut