Zefram recently posted a patch to add package BLOCK syntax to Perl 5. If this were available now in 5.12 (or 5.10.1), I'd use it in every class or module where I can use a modern Perl.
This is a (reasonably) small change to the Perl 5 parser, as far as those things go. A few introspection portions of Perl 5 need corresponding changes, such as B::Deparse and the MAD annotations that few people besides Larry have understood. Yet it's beneficial as it is for three good reasons and one great reason.
First, a package with an explicit, brace-delimited scope allows readers to see where a package begins and ends. This is my sole problem with Python's whitespace: the use of vertical whitespace to denote the ends of blocks, of functions, and of classes. Using invisible characters to mark the beginnings and ends means that people (let alone parsers) sometimes have to guess, and people can guess wrong. I use vertical whitespace to separate sub-units within larger sections of code.
Schwern has a code-skimming technique where you scale down your font size and look at the program as a whole. This makes the structure of the code visible without distracting you with details of any unit of code. Languages which allow you to organize code into functions or classes or modules expose details of your design when viewed this way.
The package BLOCK syntax would make the organization of code more obvious in this respect.
Second, the package BLOCK syntax clearly delineates a scope. Any entity
defined within that block belongs to that package, and any referred to within
that block is visible within that package. This is a subtle point, but it's
also the important design reason to use the package
keyword rather
than requiring an explicit namespace on functions and methods:
sub My::Class::method
{
...
}
(Tedium also argues against that approach, but too few programming languages aggressively optimize against tedium. Perl 5 doesn't go far enough in that respect.)
This delineation is more than mere syntax. It's also visual. It suggests an encapsulation. Inside these curly braces is different from outside.
Third—and related, you prevent unintentional sharing of lexicals and other variables. Because package scoping rules and lexical scoping rules are orthogonal, it's easy to close over lexical variables declared at the top of a file even if you've switched packages several times.
Sometimes that's intentional, yet it's often enough a mistake that some people recommend starting your programs with:
#! perl
use Modern::Perl; # or do the pragma dance yourself
main(@ARGV);
sub main
{
...
}
They're right, too. Defensive coding sometimes requires you to change your habits to eliminate the possibility of making certain kinds of mistakes. Explicitly delimiting the lexical scope of a package means that lexicals can't leak into other packages by accident.
(Some people might argue that you can avoid these problems by adhering to a "one package per .pm file" policy, and that's true. It's also not always possible. Helper packages or inner classes or other entities encapsulated by their design deserve to stay encapsulated.)
You can get all three of these features now by writing:
{
package Foo 1.23.45;
...
}
{
package Bar 9.87.65;
...
}
{
package Baz 0.07;
...
}
... but aesthetics argues against this form. So does linguistics. The important data for the unit as a whole is its name and its version, and that belongs at either the start or the end of the unit. For the same reason unit of smaller organizational granularity put their metadata sections before their block. Compare:
sub foo :attr
{
...
}
... with:
{
sub foo :attr;
...
}
... or even:
while (1)
{
...
}
... with:
do
{
...
} while (1);
(I suspect that part of the distrust for do
/while
is linguistic distaste for inverted end weight, though whether that's due to familiarity with Algol-style control structures or a dislike for backreferences in code is for graduate students to debate.)
Without a change to Perl 5's syntax like Zefram's patch (or a grammar-mutating module built around Devel::Declare), it's impossible to attach the package's metadata where it belongs: at the start of the block.
Consistency suggests it. Linguistics suggests it. Correctness recommends it. I'd use this feature today, if it were available. I'd like to see it in Perl 5.14 next spring.
Reading about it on p5p, I thought this syntax was pretty damn awesome.
There's a few things that I was concerned about though.
What happens if you do this?
Right now, this will be parsed out as:
which might take some getting used to when compared to other languages, where nested packages yield nested namespaces like :
This will be surprising to people in the same way to people that use doesn't happen at runtime (what do you mean, I can't go use My::Bar if $debug in a nested subroutine?!). That being said, it's consistent with other, Perl-esque uniqueness.
I'd like to see the second option myself, but that will probably take significantly more work and create a greater amount of changes needed, to which the p5p's might balk at. No longer would it be syntactic sugar, it would create Yet Another Way Of Doing It, and if it turns out to be a bad idea, it'll have to be maintained for the next ten years.
Honestly, I think it would surprise and confuse more people (especially those that already do Perl) if the behavior changes to nesting. What would the syntax be for absolute package names? What should string eval do? I can imagine that down the road it would be regarded as safe to always use the absolute name syntax, and only use the non-absolute one when it should nest. At least if eval would nest even deeper. But then again, if that would work it would open a lot of other cans containing worms.