Acme::Pythonic - Python whitespace conventions for Perl
use Acme::Pythonic; # this semicolon yet needed sub exp_mod: use integer my ($i, $j, $n) = @_ my $r = 1 while $j: if $j % 2: $r = ($i*$r) % $n $j >>= 1 $i = ($i**2) % $n return $r
Acme::Pythonic is a source filter that brings Python whitespace conventions to Perl.
This module is thought for those who embrace contradictions. A humble aid for walkers of the Whitespace Matters Way in their pursuit of highest realization, only attained with SuperPython.
This is the Acme::Pythonic version of the example in perlsyn:
OUTER: for my $wid in @ary1: INNER: for my $jet in @ary2: next OUTER if $wid > $jet $wid += $jet
Labeled blocks work as well:
my $k = 7 FOO: --$k last FOO if $k < 0 redo FOO
Note that if we put a label in the line before in a control structure indentation matters. This would be a non-equivalent reformat of the example above:
OUTER: for my $wid in @ary1: # NOT WHAT WE WANT INNER: for my $jet in @ary2: # GOOD, ALIGNED next OUTER if $wid > $jet $wid += $jet
Since the first for is indented with respect to OUTER: we get a labeled block containing a for loop, instead of a labeled for.
for
OUTER:
Labels can be composed just of upper-case letters. That was decided so that list operators can be chained:
my @st = map: $_->[0] sort: $a->[1] <=> $b->[1] map: [$_, $foo{$_}] keys %foo
and &-prototyped subroutines can be used like this:
&
sub mygrep (&@): my $code = shift my @result foreach @_: push @result, $_ if &$code return @result @array = mygrep: my $aux = $_ $aux *= 3 $aux += 1 $aux % 2 reverse 0..5
Nevertheless support for this has to be improved, see LIMITATIONS.
do/while
Acme::Pythonic tries to detect loop modifiers after a do BLOCK. Thus
do: do_something() do_something_else() while $condition
is seen as a do/while, whereas
do: do_something() do_something_else() while $condition: handle_some_stuff()
is not.
To be able to have an empty block we provide pass:
pass
sub abstract_method: pass
This works:
foreach my $foo @array: do_something_with $foo
However in is supported in case you find the following more readable
in
foreach my $foo in @array: do_something_with $foo
This keyword can be used if there's no variable to its left too, which means we are dealing with $_ as usual:
$_
foreach in @array: s/foo/bar/
but can't be used when the loop acts as a modifier:
print foreach in @array # ERROR
As in Python, you can break a logical line in several physical lines using a backslash at the end:
my $total = total_products() + \ total_delivery() + \ total_taxes()
and in that case the indentation of those additional lines is irrelevant.
Unlike Python, we ignore backslashes that end a line in a comment:
my $a = 1 # this comment ends in a backslash, no problem \
There's no technical reason for this, only it does not belong to the whitespace conventions we are trying to mimick.
If a line ends in a comma or arrow (=>) it is conceptually joined with the following:
=>
my %authors = (Perl => "Larry Wall", Python => "Guido van Rossum")
As in Python, comments can be intermixed there:
my %hello = (Catalan => 'Hola', # my mother tongue English => 'Hello)
Keywords followed by code in the same line are not supported. This would be valid in Python:
not
if $n % 2: $n = 3*$n + 1 else: $n /= 2
but it does not work in Acme::Pythonic. The reason for this is that it would be hard to identify the colon that closes the expression without parsing Perl, consider for instance:
if keys %foo::bar ? keys %main:: : keys %foo::: print "foo\n"
On the other hand, to use a subroutine with prototype (&) you need to add the trailing semicolon in its own line by now:
(&)
sub foo (&): pass foo: pass ;
That's a pity, improving this is in the TODO list.
You can pass a debug flag to Acme::Pythonic like this:
debug
use Acme::Pythonic debug => 1;
In debug mode the module prints to standard output the code it has generated and substitutes everything with a dummy 1;, so nothing gets executed. This way the resulting source can be inspected.
1;
The module tries to generate human readable code following perlstyle. Blank lines and comments are preserved.
This happens before Filter::Simple undoes the blanking out of PODs, strings, and regexps. Thus, those parts will be seen as $;s in a row ($; is \034 by default.)
$;
\034
This module uses a regexp approach and the superb help of Filter::Simple. The regexp part of this means it is broken from the start, though I've tried hard to make it as robust as I could. Bug reports will be very welcome, just drop me a line!
Damian Conway gave his full blessing if I wanted to write a module like this based on his unpublished Language::Pythonesque. The code that handles indentation is inspired by his.
Also, Dr. Conway is the author of Filter::Simple, which aids a lot blanking out PODs, strings, etc. so you can munge the source with certain confidence. Without Filter::Simple this module would be infinitely more broken.
perlfilter, Filter::Simple, SuperPython.
Xavier Noria (FXN), <fxn@cpan.org>
Copyright (C) 2004 by Xavier Noria
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.2 or, at your option, any later version of Perl 5 you may have available.
To install Acme::Pythonic, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Acme::Pythonic
CPAN shell
perl -MCPAN -e shell install Acme::Pythonic
For more information on module installation, please visit the detailed CPAN module installation guide.