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.

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.)

... 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.

Tags:

2 Comments

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?

package Foo {
# Foo stuff
package Bar {
# Bar stuff
}
}

Right now, this will be parsed out as:

{
package Foo;
{
package Bar;
}
}

which might take some getting used to when compared to other languages, where nested packages yield nested namespaces like :

{
package Foo;
# Foo stuff
{
package Foo::Bar;
# bar stuff
}
}

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.