package Perl6::Placeholders; use Filter::Simple; our $VERSION = '0.07'; my %giftwrap = ( 'sort' => sub {"{$_[0]\->(\$a,\$b)}"}, 'grep' => sub {"{$_[0]\->(\$_)}"}, 'map' => sub {"{$_[0]\->(\$_)}"}, 'sub' => sub {$_[0]}, '' => sub {$_[0]}, ); use re 'eval'; our $code = qr{ (?: [^{}]+ | \{ (??{ $code }) \} )* }x; our $placeholder = qr{ (?: $code (?: (??{ $carvar }) $code ) )+ }x; our $carvar = qr{ (?: \$\w+ (?: (?:->)? (?:\[$placeholder\]|\{$placeholder\}) )+ | \$\^\w+ ) }x; FILTER_ONLY executable => sub { s<(sub|sort|map|grep)?\s*(?=.*\$\^\w)\{($placeholder)\}> { my ($context,$code) = ($1||"",$2); my %vars; @vars{$code =~ m/(\$\^\w+)/g} = (); my $vars = join ',', sort keys %vars; my $decl = qq{my($vars)=\@_;}; $decl = "" if $code =~ /\Q$decl/; $code = qq{ sub {$decl $code } }; $code =~ s/\$\^(\w+)/\$$1/g; "$context ". $giftwrap{$context}($code); }ge; }, __END__ =head1 NAME Perl6::Placeholders - Perl 6 implicitly declared parameters for Perl 5 =head1 VERSION This document describes version 0.06 of Perl6::Placeholders, released October 7, 2005. =head1 SYNOPSIS use Perl6::Placeholders; my $add = { $^a + $^b }; # Create a sub that adds its two args print $add->(1,2), "\n"; # Call it # Use as map, grep, and sort blocks print join ",", sort { $^y <=> $^x } 1..10; print join "\n", map { $^value**2 } 1..10; print join "\n", map { $data{$_-1}.$^value**2 } 1..10; print join "\n", grep { $data{$^value} } 1..10; my $div = { $^x / $^y }; # Create a HOF that divides its two args print $div->(1,2), "\n"; # Do a division =head1 DESCRIPTION The Perl6::Placeholders module lets you try out the new Perl 6 implicit parameter specification syntax in Perl 5. Perl 6 reserves all variables of the form C<$^name> or C<@^name> or C<%^name> as "placeholders" that can be used to turn regular blocks into subroutine references. Any block containing one or more such placeholders is treated as a reference to a subroutine in which the placeholders are replaced by the appropriate number and sequence of arguments. That is, the expression: # Perl 6 code $check = { $^a == $^b**2 * $^c or die $^err_msg }; is equivalent to: # Perl 6 code $check = sub ($a, $b, $c, $err_msg) { $a == $b**2 * $c or die $err_msg }; This could then be invoked: # Perl 6 code $check.($i,$j,$k,$msg); It is also be possible to interpolate an argument list into a static expression like so: # Perl 6 code { $^a == $^b**2 * $^c or die $^err_msg }.($i,$j,$k,$msg); The placeholders are sorted UTF8-abetically before they are used to create the subroutine's parameter list. Hence the following: # Perl 6 code @reverse_sorted = sort {$^b <=> $^a} @list; works as expected. That is, it's equivalent to: @reverse_sorted = sort sub($a,$b){$b <=> $a}, @list; =head2 Declaring placeheld closures in Perl 5 The Perl6::Placeholders module allows you to use (almost) the same syntax in Perl 5. That is, the expression: # Perl 5 code use Perl6::Placeholders; $check = { $^a == $^b**2 * $^c or die $^err_msg }; is equivalent to: # Perl 5 code $check = sub { my ($a, $b, $c, $err_msg) = @_; $a == $b**2 * $c or die $err_msg; }; This could then be invoked: # Perl 5 code $check->($i,$j,$k,$msg); It is also be possible to interpolate an argument list into a static expression like so: # Perl 5 code use Perl6::Placeholders; { $^a == $^b**2 * $^c or die $^err_msg }->($i,$j,$k,$msg); Note that the placeholders are restricted to scalars (though a future release may support array and hash parameters too). The placeholders are sorted ASCIIbetically before they are used to create the subroutine's parameter list. Hence the following: # Perl 5 code use Perl6::Placeholders; @reverse_sorted = sort {$^b <=> $^a} @list; works as expected (even in earlier perls that don't support sub refs as sort specifiers!) =head1 DEPENDENCIES The module is implemented using Filter::Simple and requires that module to be installed. =head1 AUTHOR Damian Conway (damian@conway.org) =head1 MAINTAINER Luke Palmer (lrpalmer gmail com) =head1 BUGS This module is not designed for serious implementation work. It uses some relatively sophisticated heuristics to translate Perl 6 syntax back to Perl 5. It I make mistakes if your code gets even moderately tricky. Nevertheless, bug reports are most welcome. =head1 COPYRIGHT Copyright (c) 2002, Damian Conway. All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the terms of the Perl Artistic License (see http://www.perl.com/perl/misc/Artistic.html)