[ANN] Acme::Pythonic 0.33
From: Xavier Noria (fxn_at_hashref.com)
Date: 06/28/04
- Next message: ypetinot: "Re: How to use 2 DIFFERENT VERSIONS of the SAME MODULE in the same perl program ?"
- Previous message: Peter J. Acklam: "Re: Need > 15 digits precision without big performance hit"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 28 Jun 2004 07:32:55 -0700
Acme::Pythonic 0.33 is out. Since the last announcement changes has
been done mostly to the documentation of the module:
0.33
- Minor documentation improvements.
- The section about labels was rewritten.
- Added Acme::Dot to SEE ALSO.
0.32 Sat Jun 19 16:09:44 2004
- Added OVERVIEW to POD.
- Minor documentation enhancements.
0.31 Sat Jun 12 14:58:32 2004
- Test::More required version relaxed to 0.45.
- Perl required version relaxed to 5.8.0.
-- fxn
NAME
Acme::Pythonic - Python whitespace conventions for Perl
SYNOPSIS
use Acme::Pythonic; # this semicolon yet needed
sub delete_edges:
my $G = shift
while my ($u, $v) = splice(@_, 0, 2):
if defined $v:
$G->delete_edge($u, $v)
else:
my @e = $G->edges($u)
while ($u, $v) = splice(@e, 0, 2):
$G->delete_edge($u, $v)
DESCRIPTION
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.
OVERVIEW
Acme::Pythonic provides *grosso modo* these conventions:
* Blocks are marked by indentation and an opening colon instead of
braces.
* Simple statements are separated by newlines instead of
semicolons.
* EXPRs in control flow structures do not need parentheses around.
Additionally, the filter understands the keywords "pass" and "in".
foreach my $n in 1..100:
while $n != 1:
if $n % 2:
$n = 3*$n + 1
else:
$n /= 2
DETAILS
Labels
The syntax this module provides introduces an ambiguity: Given
if $flag:
do_this()
else:
do_that()
there's no way to know whether that is meant to be
if ($flag) {
do_this();
} else {
do_that();
}
or rather
if ($flag) {
do_this();
}
else: {
do_that();
}
where the second half is a labeled block, and so "do_that()" is
unconditionally executed.
To solve this labels in Pythonic code have to be in upper case.
In addition, to be able to write a BEGIN block as
BEGIN:
$foo = 3
"BEGIN", "CHECK", "INIT", "END" cannot be used as labels.
Let's see some examples. This is the Pythonic version of the
snippet in
perlsyn:
OUTER: for my $wid in @ary1:
INNER: for my $jet in @ary2:
next OUTER if $wid > $jet
$wid += $jet
And here we have a labeled block:
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".
"do/while"-like constructs
Acme::Pythonic tries to detect statement 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.
New Keywords
pass
"pass" is a NO-OP, it is meant to explicit empty blocks:
sub abstract_method:
pass
in
This works:
foreach my $foo @array:
do_something_with $foo
However "in" is supported in case you find the following more
readable
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
&-Prototyped subroutines
"&"-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
If the prototype is exactly "&", however, Acme::Pythonic needs to
know
it because it might need to add a semicolon after the closing
bracket in
the generated code.
Thus, if any module defines such a subroutine "use()" it *before*
Acme::Pythonic:
use Thread 'async';
use Acme::Pythonic; # now Acme::Pythonic knows async() has
prototype "&"
async:
do_this()
do_that()
If such a subroutine is defined in the very code being filtered
declare
it before Acme::Pythonic is "use()"d:
sub twice (&); # declaration
use Acme::Pythonic; # now Acme::Pythonic knows twice() has
prototype "&"
# the definition itself can be Pythonic
sub twice (&):
my $code = shift
$code->() for 1..2
twice:
do_this_twice()
Nevertheless, the module is not smart enough to handle optional
arguments as in a subroutine with prototype "&;$".
Line joining
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, backslashes in a line with a comment are allowed
my $foo = 1 + \ # comment, no problem
2
In Python that's a syntax error, but I think that's more in the
line of
Perl forgiveness.
If a line ends in a comma or arrow ("=>") it is conceptually
joined with
the following as well:
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',)
Acme::Pythonic munges a source that has already been processed by
Filter::Simple. In particular, Filter::Simple blanks out
quotelikes
whose content is not even seen by Acme::Pythonic so backslashes in
"qw//" and friends won't be removed:
# Do not put backslashes here because qw// is bypassed
my @colors = qw(Red
Blue
Green)
LIMITATIONS
Keywords followed by code in the same line are "not" supported.
This
would be valid in Python:
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"
DEBUG
You can pass a "debug" flag to Acme::Pythonic like this:
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.
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. Those parts are marked with the label
"BLANKED_OUT" for easy identification.
BUGS
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!
THANKS
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.
SEE ALSO
perlfilter, Filter::Simple, SuperPython, Acme::Dot.
AUTHOR
Xavier Noria (FXN), <fxn@cpan.org>
COPYRIGHT AND LICENSE
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.
- Next message: ypetinot: "Re: How to use 2 DIFFERENT VERSIONS of the SAME MODULE in the same perl program ?"
- Previous message: Peter J. Acklam: "Re: Need > 15 digits precision without big performance hit"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|