Hinrik Örn Sigurðsson > Perl6-Doc > share/Apocalypse/A04.pod


Annotate this POD



Open  0
View/Report Bugs


Apocalypse 4: Syntax


Larry Wall <larry@wall.org>


  Maintainer: Larry Wall <larry@wall.org>
  Date: 18 Jan 2002
  Last Modified: 18 May 2006
  Number: 4
  Version: 6

This Apocalypse is all about syntax in the large. The corresponding chapter in the Camel book is entitled "Statements and Declarations", but it could just as easily have been entitled, "All About Blocks". The basic underlying question is "What exactly do those curlies mean?"

For Perl 5 and earlier, the answer to that question was, "Too many things". Or rather, too many things with inconsistent rules. We'll continue to use curlies for much of what we've used them for up till now, but by making a few critical simplifications, the rules will be much more consistent. In particular, built-ins will parse with the same rules as user-defined constructs. It should be possible to make user-extensible syntax look just like built-in syntax. Perl 5 started down this road, but didn't get all the way there. In Perl 6, all blocks operate under the same rules. Effectively, every block is a kind of closure that can be run by user-defined constructs as well as built-ins.

Associated with block structure are the various constructs that make use of block structure. Compound constructs like loops and conditionals use blocks explicitly, whereas declarations refer to their enclosing block implicitly. This latter feature was also inconsistently applied in Perl 5. In Perl 6, the rule is simple: A lexically scoped declaration is in effect from the declaration to the end of its enclosing block. Since blocks are delimited only by curlies or by the ends of the current compilation unit (file or string), that implies that we can't allow multi-block constructs in which lexically scoped variables "leak" or "tunnel" from the end of one block to the beginning of the next. A right curly (without an intervening left curly) absolutely stops the current lexical scope. This has direct bearing on some of these RFCs. For instance, RFC 88 proposes to let lexical scope leak from a try block into its corresponding finally block. This will not be allowed. (We'll find a different way to solve that particular issue.)

While lexical declarations may not leak out of a block, control flow must be able to leak out of blocks in a controlled fashion. Obviously, falling off the end of a block is the most "normal" way, but we need to exit blocks in other "abnormal" ways as well. Perl 5 has several different ways of exiting a block: return, next, last, redo, and die, for instance. The problem is that these various keywords are hard-wired to transfer control outward to a particular built-in construct, such as a subroutine definition, a loop, or an eval. That works against our unifying concept that every block is a closure. In Perl 6, all these abnormal means of block exit are unified under the concept of exceptions. A return is a funny kind of exception that is trapped by a sub block. A next is an exception that is trapped by a loop block. And of course die creates a "normal" exception that is trapped by any block that chooses to trap such exceptions. Perl 6 does not require that this block be an eval or try block.

You may think that this generalization implies excessive overhead, since generally exception handling must work its way up the call stack looking for an appropriate handler. But any control flow exception can be optimized away to a "goto" internally when its target is obvious and there are no user-defined blocks to be exited in between. Most subroutine return and loop control operators will know which subroutine or loop they're exiting from because it'll be obvious from the surrounding lexical scope. However, if the current subroutine contains closures that are being interpreted elsewhere in user-defined functions, it's good to have the general exception mechanism so that all needed cleanup can be automatically accomplished and consistent semantics maintained. That is, we want user-defined closure handlers to stay out of the user's face in the same way that built-ins do. Control flow should pretend to work like the user expects, even when it doesn't.

Here are the RFCs covered in this Apocalypse. PSA stands for "problem, solution, acceptance", my private rating of how this RFC will fit into Perl 6. Interestingly, this time I've rejected more RFCs than I accepted. I must be getting cruel and callous in my old age. :-)

    RFC   PSA    Title
    ---   ---    -----
    006   acc    Lexical variables made default
    019   baa    Rename the C<local> operator
    022   abc    Control flow: Builtin switch statement
    063   rr     Exception handling syntax
    064   bdc    New pragma 'scope' to change Perl's default scoping
    083   aab    Make constants look like variables
    088   bbc    Omnibus Structured Exception/Error Handling Mechanism
    089   cdr    Controllable Data Typing
    106   dbr    Yet another lexical variable proposal: lexical variables made default
    113   rr     Better constants and constant folding
    119   bcr    Object neutral error handling via exceptions
    120   bcr    Implicit counter in for statements, possibly $#   
    167   bcr    Simplify do BLOCK Syntax
    173   bcc    Allow multiple loop variables in foreach statements
    209   cdr    Fuller integer support in Perl   
    262   cdr    Index Attribute
    279   cdr    my() syntax extensions and attribute declarations
    297   dcr    Attributes for compiler hints
    309   adr    Allow keywords in sub prototypes
    330   acc    Global dynamic variables should remain the default
    340   dcr    with takes a context
    342   bcr    Pascal-like "with"

Accepted RFCs ^

Note that, although these RFCs are in the "accepted" category, most are accepted with major caveats (a "c" acceptance rating), or at least some "buts" (a "b" rating). I'll try to list all those caveats here, but where there are systematic changes, I may indicate these generally in this document without attempting to rewrite the RFC in every detail. Those who implement these features must be sensitive to these systematic changes and not just uncritically implement everything the RFC says.

I'd like to talk about exceptions first, but before that I have to deal with the switch statement, because I think it's silly not to unify exception handlers with switch statements.

RFC 022: Control flow: Builtin switch statement


Another argument against having a switch statement in Perl 6 is that we never had it in the first five versions of Perl. But it would be incorrect to say that we didn't miss it. What actually happened was that every time we started discussing how to add a switch statement, it wasn't obvious how far to go. A switch statement in Perl ought to do more than a switch statement in C (or in most any other language, for that matter). So the fact that we haven't added a switch statement so far says more about how hard it is to design a good one than about how much we wanted a lousy one. Eventually the ever inventive Damian Conway came up with his famous design, with a Perl 5 module as proof of concept, and pretty much everyone agreed that he was on the right track, for some definition of "right" (and "track"). This RFC is essentially that design (not surprisingly, since Damian wrote it), so it will be accepted, albeit with several tweaks.

In the first place, as a quasi-linguist, I loathe the keywords switch and case. I would prefer keywords that read better in English. Much as I love verbing nouns, they don't work as well as real verbs or real prepositions when topicalizers are called for. After thrashing over several options with Damian and other folks, we've settled on using given instead of switch, and when instead of case:

    given EXPR {
        when EXPR { ... }
        when EXPR { ... }

The other great advantage of using different words is that people won't expect it to work exactly like any other switch statement they may be familiar with.

That being said, I should point out that it is still called "the switch statement", and the individual components are still "cases". But you don't have to put "switch" or "case" into constant-width font, because they're not keywords.

Because curlies are so extremely overloaded in Perl 5, I was at first convinced that we would need a separator of some sort between the expression and the block, maybe a : or => or some such. Otherwise it would be too ambigous to come upon a left curly when expecting an operator--it would be interpreted as a hash subscript instead. Damian's RFC proposes to require parentheses in certain situations to disambiguate the expression.

But I've come to the conclusion that I'd rather screw around (a little) with the "insignificant whitespace" rule than to require an extra unnatural delimiter. If we observe current practice, we note that 99% of the time, when people write a hash subscript they do so without any whitespace before it. And 99% of the time, when they write a block, they do put some whitespace in front of it. So we'll just dwim it using the whitespace. (No, we're not going all the way to whole-hog whitespace dwimmery--Python will remain the best/worst example of that approach.)

Subscripts are the only valid use of curlies when an operator is expected. (That is, subscripts are essentially postfix operators.) In contrast, hash composers and blocks are terms, not operators. Therefore, we will make the rule that a left curly that has whitespace in front of it will never be interpreted as a subscript in Perl 6. (If you think this is totally bizarre thing to do, consider that this new approach is actually consistent with how Perl 5 already parses variables within interpolated strings.) If there is any space before the curly, we force it to start a term, not an operator, which means that the curlies in question must delimit either a hash composer or a block. And it's a hash composer only if it contains a => pair constructor at the top level (or an explicit hash keyword on the front.) Therefore it's possible to unambiguously terminate an expression by following it with a block, as in the constructs above.

Interestingly, this one tweak to the whitespace rule also means that we'll be able to simplify the parentheses out of other similar built-in constructs:

    if $foo { ... }
    elsif $bar { ... }
    else { ... }
    while $more { ... }
    for 1..10 { ... }


By a similar chain of logic (or illogic), I also want to tweak the whitespace rules for the trailing curly. There are severe problems in any C-derived language that allows user-defined constructs containing curlies (as Perl does). Even C doesn't entirely escape the head-scratching puzzle of "When do I put a semicolon after a curly?" A struct definition requires a terminating semicolon, for instance, while an if or a while doesn't.

In Perl, this problem comes up most often when people say "Why do I have to put a semicolon after do {} or eval {} when it looks like a complete statement?"

Well, in Perl 6, you don't, if the final curly is on a line by itself. That is, if you use an expression block as if it were a statement block, it behaves as one. The win is that these rules are consistent across all expression blocks, whether user-defined or built-in. Any expression block construct can be treated as either a statement or a component of an expression. Here's a block that is being treated as a term in an expression:

    $x = do {
    } + 1;

However, if you write

    $x = do {
    + 1;

then the + will be taken erroneously as the start of a new statement. (So don't do that.)




[Update: We ended up solving this by distinguishing statement BEGIN from term BEGIN. Also, we can't really syntactically distinguish the closures for constructs like sort or map if they are subject to multiple dispatch, since we wouldn't know the signature. However, you never have to end such a block on a line by itself, since you can always put a comma, or even feed the list to the operator using the <== pipe operator.]

Anyway, back to switch statements. Damian's RFC proposes various specific kinds of dwimmery, and while some of those dwims are spot on, others may need adjustment. In particular, there is an assumption that the programmer will know when they're dealing with an object reference and when they're not. But everything will be an object reference in Perl 6, at some level or other. The underlying characteristics of any object are most generally determined by the answer to the question, "What methods does this object respond to?"


[Update: String context is now forced by unary ~.]

Another thing that needs adjustment is that the concept of "isa" matching seems to be missing, or at least difficult to express. We need good "isa" matching to implement good exception handling in terms of the switch mechanism. This means that we need to be able to say something like:

    given $! {
        when Error::Overflow { ... }
        when Error::Type { ... }
        when Error::ENOTTY { ... }
        when /divide by 0/ { ... }

and expect it to check $!.isa(Error::Overflow) and such, along with more normal pattern matching. In the case of the actual exception mechanism, we won't use the keyword given, but rather CATCH:

    CATCH {
        when Error::Overflow { ... }
        when Error::Type { ... }
        when Error::ENOTTY { ... }
        when /divide by 0/ { ... }

CATCH is a BEGIN-like block that can turn any block into a "try" block from the inside out. But the insides of the CATCH are an ordinary switch statement, where the discriminant is simply the current exception object, $!. More on that later--see RFC 88 below.

Some of you may recall that I've stated that Perl 6 will have no barewords. That's still the case. A token like Error::Overflow is not a bareword because it's a declared class. Perl 6 recognizes package names as symbolic tokens. So when you call a class method as Class::Name.method(), the Class::Name is actually a class object (that just happens to stringify to "Class::Name"). But the class method can be called without a symbolic lookup on the package name at run time, unlike in Perl 5.

Since Error::Overflow is just such a class object, it can be distinguished from other kinds of objects in a switch statement, and an "isa" can be inferred. It would be nice if we could go as far as to say that any object can be called with any class name as a method name to determine whether it "isa" member of that class, but that could interfere with use of class name methods to implement casting or construction. So instead, since switch statements are into heavy dwimmery anyway, I think the switch statement will have to recognize any Class::Name known at compile time, and force it to call $!.isa(Class::Name).

[Update: Actually, it just follows from how smart matching works. But in fact, smart match calls the .does method, which is more general than the .isa method, insofar as .does can check both roles and inheritance. See A12 for more.]


[Update: Parsing rules tend to use the :p modifier, which anchors the next token automatically to the start of the rule. That's all that needs to be user visible. Everything else is the domain of the optimizer.]

Another possible adjustment is that the proposed else block could be considered unnecessary. The code following the final when is automatically an "else". Here's a duodecimal digit converter:

    $result = given $digit {
        when "T" { 10 }
        when "E" { 11 }

Nevertheless, it's probably good documentation to line up all the blocks, which means it would be good to have a keyword. However, for reasons that will become clearer when we talk about exception handlers, I don't want to use else. Also, because of the identification of when and if, it would not be clear whether an else should automatically supply a break at the end of its block as the ordinary when case does.

So instead of else, I'd like to borrow a bit more from C and use default:

    $result = given $digit {
        when "T" { 10 }
        when "E" { 11 }
        default  { $digit }

Unlike in C, the default case must come last, since Perl's cases are evaluated (or at least pretend to be evaluated) in order. The optimizer can often determine which cases can be jumped to directly, but in cases where that can't be determined, the cases are evaluated in order much like cascaded if/elsif/else conditions. Also, it's allowed to intersperse ordinary code between the cases, in which case the code must be executed only if the cases above it fail to match. For example, this should work as indicated by the print statements:

    given $given {
        print "about to check $first";
        when $first { ... }
        when $next { ... }
        print "giving up";
        default { ... }
        die "panic: shouldn't see this";

We can still define when as a variant of if, which makes it possible to intermix the two constructs when (or if) that is desirable. So we'll leave that identity in--it always helps people think about it when you can define a less familiar construct in terms of a more familiar one. However, the default isn't quite the same as an else, since else can't stand on its own. A default is more like an if that's always true. So the above code is equivalent to:

    given $given {
        print "about to check $first";
        print "giving up";
        if 1 { ...; break; }
        die "panic: shouldn't see this";

We do need to rewrite the relationship table in the RFC to handle some of the tweaks and simplifications we've mentioned. The comparison of bare refs goes away. It wasn't terribly useful in the first place, since it only worked for scalar refs. (To match identities we'll need an explicit .id method in any event. We won't be relying on the default numify or stringify methods to produce unique representations.)

[Update: Instead of an .id method, which would be unclear how to compare, there's a =:= operator for comparing identities. Though you can always compare two id's with the === operator.]

I've rearranged the table to be applied in order, so that default interpretations come later. Also, the "Matching Code" column in the RFC gave alternatives that aren't resolved. In these cases I've chosen the "true" definition rather than the "exists" or "defined" definition. (Except for certain set manipulations with hashes, people really shouldn't be using the defined/undefined distinction to represent true and false, since both true and false are considered defined concepts in Perl.)


    when @array          { "array intersection" }

while a list looks like this:





[Update: since we ended up adding junctions, you do use vertical bars now. If you like commas you can always use any().]




    given EXPR1 {
        when EXPR2 { ... }

it's equivalent to saying this:

    for (scalar(EXPR1)) {

[Update: the =~ operator has been renamed ~~.]

Table 1: Matching a switch value against a case value

    $a      $b        Type of Match Implied    Matching Code
    object  class     class membership         match if $a.isa($b)
    expr    subst     substitution match       match if $a =~ subst
    expr    number    numeric equality         match if $a == $b
    expr    string    string equality          match if $a eq $b
    expr    boolean   simple expression truth* match if $b
    expr    undef     undefined                match unless defined $a

[Update: This is inaccurate in several ways; see the most recent table in S03.]

In order to facilitate optimizations, these distinctions are made syntactically at compile time whenever possible. For each comparison, the reverse comparison is also implied, so $a/$b can be thought of as either given/when or when/given. (We don't reverse the matches marked with * are because it doesn't make sense in those casees.)

If type of match cannot be determined at compile time, the default is to try to apply the very same rules in the very same order at run time, using the actual types of the arguments, not their compile-time type appearance. Note that there are no run-time types corresponding to "method" or "boolean". Either of those notions can be expressed at runtime as a closure, of course.


    Intent      Natural           Forced
    array       @foo              [list] or @{expr}
    hash        %bar              {pairlist} or %{expr}
    string      string literal    _expr str(expr)

[Update: qr// is now spelled rx//. String context is forced ~. A regex is "interpolated" with /<$expr/>, but it's not interpolated as a separate pass as in Perl 5.]



it is treated as if you wrote

    { $_.foo(1,2,3) }

and then the closure is evaluated for its truth.


[Update: You can specify a run-time class name via ::($expr) without explicitly using .does (or .isa, for that matter).]


It might be argued that boolean expressions have no place here at all, and that you should use if if that's what you mean. (Or use a sub() closure to force it to ignore the given.) However, the "comb" structure of a switch is an extremely readable way to write even ordinary boolean expressions, and rather than forcing people to write:

    anyblock {
        default          { ... }

I'd rather they be able to write:

    anyblock {
        when $a == 1 { ... }
        when $b == 2 { ... }
        when $c == 3 { ... }
        default      { ... }

This also fits better into the use of "when" within CATCH blocks:

    CATCH {
        default              { die }

To force all the when clauses to be interpreted as booleans without using a boolean operator on every case, simply provide an empty given, to be read as "given nothing...":

    given () {
        when $a.isa(Ant) { ... }
        when $b.isa(Bat) { ... }
        when $c.isa(Cat) { ... }
        default          { ... }

[Update: you can just say given {.true} to get the same effect without a special case.]


    for @foo {
        when 1   { ... }
        when 2   { ... }
        when "x" { ... }
        default  { ... }

By symmetry, a given will by default alias $_ to the "given". Basically, the only difference between a given and a for is that a given takes a scalar expression, while a for takes a pre-flattened list and iterates over it.

[Update: for takes a lazily flattened list, not a pre-flattened list. Use the eager listop to pre-flatten a list.]


    given $value -> $g {
        when 1 { /foo/ }
        when 2 { /bar/ }
        when 3 { /baz/ }

In the same way, a loop's values can be aliased to one or more loop variables.



    for @foo { ... }

is really compiled down to this:


Since for and given work by passing arguments to a closure, it's a small step to generalize that in the other direction. Any method definition is a topicalizer within the body of the method, and will assume a "given" of its $self object (or whatever you have named it). Bare closures topicalize their first argument, implicitly aliasing it to $_ unless $^a or some such is used. That is, if you say this:

    grep { $_ eq 3 } @list

it's equivalent to this more explicit use of a curried function:

    grep { $^a eq 3 } @list

But even a grep can use the aliasing syntax above:


Outside the scope of any topicalizer, a when will assume that its given was stored in $_ and will test implicitly against that variable. This allows you to use when in your main loop, for instance, even if that main loop was supplied by Perl's -n or -p switch. Whenever a loop is functioning as a switch, the break implied by finishing a case functions as a next, not a last. Use last if that's what you mean.

A when is the only defaulting construct that pays attention to the current topicalizer regardless of which variable it is associated with. All other defaulting constructs pay attention to a fixed variable, typically $_. So be careful what you're matching against if the given is aliased to something other than $_:

    $_ = "foo";
    given "bar" -> $f {

[Update: The first argument is always aliased to $_ now.]

Oh, one other tweak. The RFC proposes to overload next to mean "fall through to the next case". I don't think this is wise, since we'll often want to use loop controls within a switch statement. Instead, I think we should use skip to do that. (To be read as "Skip to the next statement.")

[Update: That's now spelled continue.]

Similarly, if we make a word to mean to explicitly break out of a topicalizer, it should not be last. I'd suggest break! It will, of course, be unnecessary to break out of the end of a when case because the break is implied. However, there are times when you might want to break out of a when block early. Also, since we're allowing when modifiers that do not implicitly break, we could use an explicit break for that situation. You might see cases like this:

    given $x {
        warn("No value"), break  when undef;

So it looks to me like we need a break.

RFC 088: Omnibus Structured Exception/Error Handling Mechanism


RFC 88 is massive, weighing in at more than 2400 lines. Annotating the entire RFC would make this Apocalypse far too big. ("Too late!" says Damian.) Nonetheless, I will take the approach of quoting various bits of the RFC and recasting those bits to work with my additional requirements. Hopefully this will convey my tweaks most succinctly.

Here's what the RFC gives as its first example:

    exception 'Alarm';
    try {

    catch Alarm => { ... }



    catch { ... }

    finally { ... }

Here's how I see that being written in Perl 6:

    try {
        CATCH {
            when X::Alarm             { ... }
            when /divide by 0/        { ... }
            default                   { ... }
        POST { ... }

[Update: the comma in the second case should be a |.]



[Update: PRE and POST are now spelled ENTER and LEAVE. (PRE and POST are reserved for Design By Contract assertions).]

A try {} without a CATCH is equivalent to Perl 5's eval {}. (In fact, eval will go back to evaluating only strings in Perl 6, and try will evaluate only blocks.)


The inside of the CATCH block is precisely the syntax of a switch statement. The discriminant of the switch statement is the exception object, $!. Since the exception object stringifies to the error message, the when /divide by 0/ case need not be explicitly compared against $!. Likewise, explicit mention of a declared class implies an "isa" lookup, another built-in feature of the new switch statement.

In fact, a CATCH of the form:

    CATCH { 
        when xxx { ... }          # 1st case
        when yyy { ... }          # 2nd case
        ...                       # other cases, maybe a default

means something vaguely like:

    BEGIN {
        %MY.catcher = {
            given current_exception() -> $! {
                when xxx { ... }          # 1st case from above
                when yyy { ... }          # 2nd case from above
                ...                       # other cases, maybe a default
                die;            # rethrow $! as implicit default
            $!.markclean;       # handled cleanly, in theory


Also note that the CATCH block implicitly supplies a rethrow (the die above) after the cases of the switch statement. This will not be reached if the user has supplied an explicit default case, since the break of that default case will always bypass the implicit die. And if the switch rethrows the exception (either explicitly or implicitly), $! is not marked as clean, since the die will bypass the code that marks the exception as "cleanly caught". It should be considered an invariant that any $! in the normal control flow outside of a CATCH is considered "cleanly caught", according to the definition in the RFC. Unclean exceptions should only be seen inside CATCH blocks, or inside any POST blocks that have to execute while an exception is propagating to an outer block because the current try block didn't handle it. (If the current try block does successfully handle the exception in its CATCH, any POST blocks at the same level see a $! that is already marked clean.)



That will instead look like


in Perl 6. A try with no CATCH:

    try { ... }

is equivalent to:

    try { ... CATCH { default { } } }

(And that's another reason I didn't want to use else for the default case of a switch statement--an else without an if looks really bizarre...)


    try { $string.parse.run }






This will simply be:

    try { fragile; }

But it means the same thing, and it's still the case that all exceptions propagate unless they are cleanly caught. In this case, the caught exception lives on in $! as a new proto-exception that could be rethrown by a new die, much as we used to use $@. Whether an exception is currently considered "cleanly caught" can be reflected in the state of the $! object itself. When $! passes through the end of a CATCH, it is marked as clean, so that subsequent attempts to establish a new $! know that they can clear out the old @$! stack. (If the current $! is not clean, it should just add its information without deleting the old information--otherwise an error in a CATCH could delete the exception information you will soon be wanting to print out.)





(The angle brackets aren't really there--I'm just copying the RFC's metasyntax here.)

Note that we're assuming a test that matches the "boolean" entry from the switch dwimmery matrix. If not, you can always wrap closure curlies around the test:


That will force the test to be called as a subroutine that ignores its argument, which happens to be $!, the exception object. (Recall that the implied "given" of a CATCH statement sets $! as the given value. That given value is automatically passed to any "when" cases that look like subroutines or closures, which are free either to ignore the passed value, or access it as $_ or $^a.)

Or you might just prefer to use the unary true operator:


I personally find that more readable than the closure.

[Update: POST is now LEAVE.]






Actually, this is not so--the while and continue blocks don't share the same lexical scope even in Perl 5. But we'll solve this issue without "tunneling" in any case. (And we'll change the continue block into a NEXT block that goes inside, so we can refer to lexical variables from within it.)







Also, @@ is a non-starter because everything about the current exception should all be in a single data structure. Keeping the info all in one place makes it easy to rethrow an exception without losing data, even if the exception was marked as cleanly caught. Furthermore I don't think that the exception stack needs to be Huffman coded that badly.

So $! contains the current exception, and $!.stack accesses the current exception stack. Through the magic of overloading, the $! object can likely be used as an array even though it isn't one, in which case @$! refers to that stack member. The push rule guarantees that $!.id == $![-1].id.

RFC (speaking of the exception declaration):



If I understand this, I think I disagree. A package ought to able to contain exceptions without being an exception class itself. There certainly ought to be a shorthand for exceptions within the current package. I suspect they're inner classes of some sort, or inner classes of an inner package, or some such.


If the given name does not match /::/ (say it's just Alarm), this happens instead:
    @Alarm::ISA = 'Exception';




I also happen to think that Exception is too long a name to prefix most common exceptions, even though they're derived from that class. I think exceptions will be better accepted if they have pithier names like X::Errno that are derived from Exception:

    our class X::Control is Exception;
    our class X::Errno is Exception;
    our class X::NumericError is Exception;
    our class C::NEXT is X::Control;
    our class E::NOSPC is X::Errno;
    our class X::FloatingUnderflow is X::NumericError;

Or maybe those could be:


if we decide uppercase names are too much like user-defined package names. But that looks strange. Maybe we just reserve single letter top-level package names for Perl. Heck, let's just reserve all top-level package names for Perl. Er, no, wait... :-)

RFC 80 suggests that exception objects numerify to the system's errno number when those are available. That's a possibility, though by the current switch rules we might have to write

    CATCH {
        when +$ENOSPC { ... }


    CATCH {
        when X::ENOSPC { ... }

That's longer, but I think it's clearer. Possibly that's E::NOSPC instead. But in any event, I can't imagine getting people to prefix every exception with "Exception::". That's just gonna discourage people from using exceptions. I'm quite willing to at least reserve the X top-level class for exceptions. I think X:: is quite sufficiently distinctive.




        my $f = open "foo"; ...
        POST { $f and close $f }


We could go as far as to make

        POST { close $f }

do something reasonable even without the guard. Maybe an undefined object could "emulate" any method for you within a POST. Maybe try is really a unary operator:

        POST { try close $f }

Or some such. I dunno. This needs more thought along transactional lines...

Time passes...

Actually, now that I've thought on it, it would be pretty easy to put wrappers around POST blocks that could do commit or rollback depending on whether the block exits normally. I'd like to call them KEEP and UNDO. KEEP blocks would only be executed if the block succeeded. UNDO blocks would only be executed if the block failed. One could even envision a syntax that ties the block to particular variable:

    UNDO $f { close $f }


It's tempting to make the execution of UNDO contingent upon whether the block itself was passed during execution, but I'm afraid that might leave a window in which a variable could already be set, but subsequent processing might raise an exception before enabling the rollback in question. So it's probably better to tie it to a particular variable's state more directly than just by placing the block at some point after the declaration. In fact, it could be associated directly with the variable in question at declaration time via a property:


[Update: All of these should use will rather than is, or the closure has to be an explicit argument to undo with no intervening space.]











    sub attempt_closure_after_successful_candidate_file_open
        foreach my $file (@fileList) {
        throw Exception "Can't open any file.",
               debug => @fileList . " tried.";


    sub attempt_closure_after_successful_candidate_file_open
      (&closure, @fileList)
        foreach my $file (@fileList) {
            my $f is post { close }
        throw Exception "Can't open any file.",
               debug => @fileList . " tried.";

[Update: That "foreach" should now be for @fileList - $file>. And the is post should be is leave. Also these days I'd leave the ampersand off the call to closure() (though it's still necessary in the declaration of the parameter).]

Note that the next within the CATCH refers to the loop, not the CATCH block. It is legal to next out of CATCH blocks, since we won't use next to fall through switch cases.


    CATCH {
        when Exception { ... }   # catch any exception

will stop returns and loop exits. This could be construed as a feature. When it's considered a bug, you could maybe say something like

    CATCH {
        when X::Control { die }  # propagate control exceptions
        when Exception  { ... }  # catch all others


    CATCH {


[Update: We now distinguish a CONTROL block from a CATCH block. Control exceptions are invisible to the CATCH block.]

Following are some more examples of how the expression evaluation of when can be used. The RFC versions sometimes look more concise, but recall that the "try" is any block in Perl 6, whereas in the RFC form there would have to be an extra, explicit try block inside many subroutines, for instance. I'd rather establish a culture in which it is expected that subroutines handle their own exceptions.




    try {
        CATCH {

This works because =~ is considered a boolean operator.

[Update: The operator is ~~ now.]


    catch not &TooSevere => { ... }


    when not &TooSevere { ... }

The unary not is also a boolean operator.








    try {
        CATCH {

I suppose we could also assume grep to be a boolean operator in a scalar context. But that's kind of klunky. If we accept Damian's superposition RFC, it could be written this way:

    try {
        CATCH {

Actually, by the "any" rules of the =~ table, we can just say:

    try {
        CATCH {
            when @$! =~ Foo { ... }

[Update: Lists must be explicitly made into junctions, so now we'd write that as any($![]) ~~ Foo.]

The RFC proposes the following syntax for finalization:

    finally { $p and $p->Done; }
    finally { $q and $q->Done; }

A world of hurt is covered over by that "...", which could move the finally clauses far, far away from what they're trying to clean up after. I think the intent is much clearer with POST. And note also that we avoid the "lexical tunneling" perpetrated by finally:


More concisely, we can say:

        my $p is post { .Done } = P.new;
        my $q is post { .Done } = Q.new;


    try     { TryToFoo; }
    catch   { TryToHandle; }
    finally { TryToCleanUp; }
    catch   { throw Exception "Can't cleanly Foo."; }

How I'd write that:

    try {
        try {
            POST    { TryToCleanUp; }
            CATCH   { TryToHandle; }
        CATCH   { throw Exception "Can't cleanly Foo."; }





RFC (regarding on_raise):

Derived classes may override this method to attempt to "handle" an exception or otherwise manipulate it, just before it is raised. If on_raise throws or returns true the exception is raised, otherwise it is not. An exception can be manipulated or replaced and then propagated in modified form simply by re-raising it in on_raise.

Offhand, I don't see this one. Not only does it seem to be making the $SIG{__DIE__} mistake all over again, it also makes little sense to me to use "throw" to do something that doesn't throw. A throw should guarantee termination of control, or you're just going to run user code that wasn't expected to be run. It'd be like return suddenly not returning! Let's please use a different method to generate an unthrown exception. I think a fail method is the right approach--it terminates the control flow one way or another, even if just returning the exception as a funny-looking undef.

The on_catch might be a bit more useful.






The try is not for Perl's sake. It's for the developer's sake. It says, watch out, some sort of non-local flow control is going on here. It signals intent to deal with action at a distance (unwinding semantics). It satisfies the first requirement listed under MOTIVATION.

try {} is the new spelling of eval {}, so it can still be used when self-documentation is desired. It's often redundant, however, since I think the all-caps CATCH and POST also serve the purpose of telling the developer to "watch out". I expect that developers will get used to the notion that many subroutines will end with a CATCH block. And I'm always in favor of reducing the bracket count of ordinary code where practical. (That's why the package declaration has always had a bracketless syntax. I hope to do the same for classes and modules in Perl 6.)


The comma or = in a conditional catch clause is required so the expression can be parsed from the block, in the fashion of Perl 5's parsing of: map <expression>, <list>; Without the comma, the form catch $foo { ... } could be a test for $foo or a test for $foo{...} (the hash element).

We now require whitespace before a non-subscript block, so this is not much of a problem.



I don't think defining things as core vs non-core is very useful--"core" is not a fundamental type of exception. I do think the standard exception taxonomy should be extensible, so that non-standard exceptions can migrate toward being standard over time. I also think that modules and classes should have their own subpackage in which to store exceptions.






Depends on the constructor, I suspect.



Probably depends on the class.


What should stringification return?



Mixed Flow Control



This matter will have to be referred to the internals experts. It's ok if this functionality is not possible, it can always be simulated with lexical state variables instead.


We can do this with special control exceptions that aren't caught until it makes sense to catch them. (Where exactly control exceptions fit in the class hierarchy is still open to debate.) In any event, there's no problem throwing a control exception from a CATCH, since any exception thrown in a CATCH or POST would propagate outside the current try block in any event.



Use %@ for Errors from Builtins


The RFC appears to give no justification for this last assertion. If we unify the error variables, die with no arguments can simply raise the current value of $!, and we stay object oriented all the way down. Then $! indicates the current error whether or not it's being thrown. It keeps track of its own state, as to whether it is currently in an "unclean" state, and refuses to throw away information unless it's clean.

        $@    current exception
        @@    current exception stack
        %@    current core fault information
        $@[0]        same as $@
        $@{message}  "can't find file"
        $@{child}    $?
        $@{errno}    $!
        $@{os_err}   $^E
        $@{chunk}    That chunk thingy in some msgs.
        $@{file}     Source file name of caller.
        $@{line}     Source line number of caller.

%@ should not contain a severity or fatality classification.








The semantics of eval are, "clear $@ and don't unwind unless the user re-dies after the eval". The semantics of try are "unwind after try, unless any raised exception was cleanly and completely handled, in which case clear $@".


And, of course, we still need eval $string.


        try { } catch { } # Clears $@.
        my $e;
        # now process $e instead of $@


I don't think the exact semantics of eval {...} are worth preserving. I think having bare try {...} assume a CATCH { default {} } will be close enough. Very few Perl 5 programs actually care whether $@ is set within the eval. Given that and the way we've defined $!, the translation from Perl 5 to Perl 6 involves simply changing eval {...} to try {...} and $@ to $! (which lives on as a "clean" exception after being caught by the try). Perhaps some attempt can be made to pull an external handler into an internal CATCH block.


catch v/s else + switch


        eval { ... }
        else {
            switch ($@) {
                case $@->my_method { ... }


This RFC allows a switch to be used in a catch { ... } clause, for cases where that approach would minimize redundant code in catch <expr> { ... } clauses, but with the mechanism proposed in this RFC, the switch functionality shown above can be written like this, while still maintaining the automatic exception propagation when no cases match:

        try { ... }
        catch Exception::IO => { ... }

The switch construct works fine, because the implied break of each handled case jumps over the default rethrow supplied by the CATCH. There's no reason to invent a parallel mechanism, and lots of reason not to.


Mechanism Hooks



    try on_catch_enter => sub { ... },
        on_catch_exit  => sub { ... },



        temp &*on_catch_enter = sub { ... };
        temp &*on_catch_exit  = sub { ... };



Mixed-Mode Modules




         sub Foo
            # Replace the old return $err_code with this:
  • Use throw internally, add support for return at API:
         sub Foo
            try {
                # real code goes here, may execute:
            return $ok;

Yow. Too much mechanism. Why not just:



    Foo() or die;

ends up throwing the proto-exception. (The current proto-exception can be kept in $! for use in messages, provided it's in thread-local storage.)

Actually, this is really important to make simple. I'd be in favor of a built-in that clearly says what's going on, regardless of whether it ends in a throw or a return of undef:

    fail "Couldn't foo", errno => 2;

Just as an aside, it could be argued that all such "built-ins" are really methods on an implicit class or object. In this case, the Exception class...




$SIG{__DIE__} must die. At least, that name must die--we may install a similar global hook for debugging purposes.




Perhaps $! could be implicitly declared to have a type of Exception. But I see little reason to make $! readonly by default. All that does is prevent clever people from doing clever things that we haven't thought of yet. And it won't stop stupid people from doing stupid things. In any event, $! is just a reference to an object, and access to the object will controlled by the class, not by Perl.


First I should note in passing that it is likely that





        my $l = $keyword.label;
        while (&condition()) {
            CATCH {
                my $t = $!.tag;


How a block gets a label in general is an interesting question. It's all very well to say that the keyword is the label, but that doesn't help if you have two nested constructs with the same name. In Perl 5, labels are restricted to being at the beginning of the statement, but then how do you label a grep? Should there be some way of specifying a label on a keyword rather than on a statement? We could end up with something like this:





I don't think every block should implicitly have a way to return, or we'll have difficulty optimizing away blocks that don't do anything blockish. That's because setting up a try environment is always a bit blockish, and does in fact impose some overhead that we'd just as soon avoid when it's unnecessary.

However, it's probably okay if certain constructs that would know how to deal with a label are implicitly labelled by their keyword name when they don't happen to have an explicit label. So I think we can allow something like:

    last grep: $_


[Update: there's now a general leave verb that can exit from an inner block.]


As for using numbers instead of labels to indicate how many levels to break out of, that would be fine, except that I don't believe in breaking out by levels. If the problem is complex enough that you need to break out more than one level, you need a name, not a number. Then it doesn't matter if you refactor your code to have more block levels or less. I find I frequently have to refactor my code that way.

It's possible to get carried away and retrofit grep and map with every conceivable variety of abort, retry, accept, reject, reduce, reuse, recycle, or whatever exception. I don't think that's necessary. There has to be some reason for writing your own code occasionally. If we get rid of all the reasons for writing user-defined subroutines, we might as well pack our bags and go home. But it's okay at minimum to treat a looping construct like a loop.

RFC 006: Lexical variables made default


However, the programming-in-the-small advocates also have a valid point: they don't want to have to go to all the trouble of turning off strictures merely to write a succinct one-liner, since keystrokes are at a premium in such programming, and in fact the very strictures that increase clarity in large programs tend to decrease clarity in small programs.

So this is one of those areas where we desire to have it both ways, and in fact, we pretty much can. The only question is where to draw the line. Some discussion suggested that only programs specified on the command line via the -e switch should be exempt from stricture. But I don't want to force every little file-based script into the large model of programming. And we don't need to.


RFC 330: Global dynamic variables should remain the default


RFC 083: Make constants look like variables

It's important to keep in mind the distinction between variables and values. In a pure OO environment, variables are merely references to values, and have no properties of their own--only the value itself would be able to say whether it is constant. Some values are naturally constant, such as a literal string, while other values could be marked constant, or created without methods that can modify the object, or some such mechanism. In such an environment, there is little use for properties on variables. Any time you put a property on a variable, it's potentially lying about its value.

However, Perl does not aspire to be a pure OO environment. In Perl-think, a variable is not merely a container for a value. Rather, a variable provides a "view" of a value. Sometimes that view could even be construed as a lie. That's okay. Lying to yourself is a useful survival skill (except when it's not). We find it necessary to repeat "I think I can" to ourselves precisely when we think we can't. Conversely, it's often valuable psychologically to treat possible activities as forbidden. Abstinence is easier to practice if you don't have to decide anew every time there's a possible assignation, er, I mean, assignment.

Constant declarations on variables fall into this category. The value itself may or may not naturally be constant, but we will pretend that it is. We could in theory go farther than that. We could check the associated object to make sure that it is constant, and blow up if it's not, but that's not necessary in this case for consistent semantics. Other properties may be stricter about this. If you have a variable property that asserts a particular shape of multidimensional array, for instance, the object in question had better be able to supply semantics consistent with that view, and it's probably a good idea to blow up sooner rather than later if it can't. This is something like strong typing, except that it's optional, because the variable property itself is optional.


The proposed syntax is fine, except that we'll be using is instead of : for properties, as discussed in Apocalypse 2. (And it's constant, not const.)

[Update: compile-time properties are now called "traits".]


As already revealed in Apocalypse 2, attributes will be known as "properties" in Perl 6, to avoid confusion with existing OO nomenclature for instance variables. Also, we'll use the is keyword instead of the colon.

[Update: run-time properties are set with but, while traits are set with is.]

Setting properties on array and hash elements bothers me, particularly when those properties have names like "public" and "private". This seems to me to be an attempt to paper over the gap of some missing OO functionality. So instead, I'd rather keep arrays and hashes mostly for homogenous data structures, and encourage people to use objects to store data of differing types. Then public and private can be properties of object attributes, which will look more like real variables in how they are declared. And we won't have to worry about the meaning of my @foo[2], because that still won't be allowed.


    my Dog @dogpound is loud;


    my Dog @dogpound is DogPound is loud;



[Update: The .is is no longer needed, since properties are really mixin methods now.]





Note that you can use:

    @dogpound =~ Dog

to test the individual elements for Doghood.

[Update: We use ~~ instead of =~ now. And @dogpound.DogPound throws an exception if @dogpound doesn't have a DogPound method.]

RFC 173: Allow multiple loop variables in foreach statements



Also the RFC assumes pairs will be passed as two elements, which is no longer necessarily the case. A hash by itself in list context will return a list of pair objects. We'll need to say something like:



I like the idea of this RFC, but the proposed syntax is not what I'd like. There are various possible syntaxes that could also potentially fulfill the intent of RFC 120:


But I like the idea of something that feels like repeated binding. We could use the := binding operator, but since binding is actually the operation performed by formal parameters of subroutines, and since we'd like to keep the list near the for and the formals near the closure, we'll use a variant of subroutine declaration to declare for loops:


You can un-interleave an array by saying:


Iterating over multiple lists in parallel needs a syntax much like a multi-dimensional slice. That is, something like a comma that binds looser than a comma. Since we'll be using semicolon for that purpose to delimit the dimensions of multi-dimensional slices, we'll use similar semicolons to delimit a parallel traversal of multiple lists: So parallel arrays could be stepped through like this:



Each "stream" is considered separately, so you can traverse two arrays each two elements at a time like this:




and it ends up meaning the same thing as if the comma were a semicolon, but only because the number of variables on the right happens to be the same as the number of streams on the right. That doesn't have to be the case. To get values one at a time across three streams, you can say


Each semicolon delimited expression on the left is considered to be a list of generated values, so it's perfectly legal to use commas or "infinite" ranges on the left. The following prints "a0", "b2", "c3", and so on forever (or at least for a very long time):

        print "$a$i";

[Update: This has been simplified. The arguments to a closure are always separated by commas, and you can use the each function to interleave two or more arrays on the left.]

RFC 019: Rename the local operator

We'll go with temp for the temporizing operator.



I can't stop people from experimenting, but I'm not terribly interested in performing this experiment myself. I made my short for a reason. So I'm accepting this RFC in principle, but only in principle. Standard Perl declarations will be plainly marked with my or our.

Rejected RFCs ^

Just because I've rejected these RFCs doesn't mean that they weren't addressing at a valid need. Usually an RFC gets rejected simply because I think there's a better way to do it. Often there's little difference between a rejected RFC that I've borrowed ideas from and an RFC accepted with major caveats.

We're already running long, so these descriptions will be terse. Please read the RFC if you don't understand the commentary.

RFC 089: Controllable Data Typing

This is pretty close to what we've been planning for Perl for a long time. However, a number of the specifics are suboptimal.

If you declare a constant, it's a constant. There's no point in allowing warnings on that by default. It should be fatal to modify a constant. Otherwise you lose all your optimization possibilities.

For historical reasons, the assignment in

     my ($a, $b) = new Foo;



In general, there seems to be a lot of confusion in this RFC between constraints on variables and constraints on values. For constraints to be useful to the compiler, they have to be on the variable, and you can't be "pushing" constraints at runtime.


So anyway, although I'm rejecting this RFC, we'll certainly have a declaration syntax resembling some of the tables in the RFC.


Yes, it's true that other widely-admired languages like Ruby do implicit declaration of lexicals, but I think it's a mistake, the results of which don't show up until things start getting complicated. (It's a sign of this weakness that in Ruby you see the workaround of faking up an assignment to force declaration of a variable.)

I dislike the implicit declaration of lexicals because it tends to defeat the primary use of them, namely, catching typos. It's just too easy to declare additional variable names by accident. It's also too easy to broaden the scope of a variable by accident. You might have a bunch of separate subroutines each with their own lexical, and suddenly find that they're all the same variable because you accidentally used the same variable name in the module initialization code.



RFC 119: Object neutral error handling via exceptions

Good goals, but I don't want yet another independent system of exception handling. Simplicity comes through unification. Also, the proposed syntax is all just a little too intertwingled for my tastes. Let's see, how can I explain what I mean?

The out-of-band stuff doesn't stand out visually enough to me, and I don't like thinking about it as control flow. Nevertheless, I think that what we've ended up with solves a number of the problems pointed out in this RFC. The RFC essentially asks for the functionality of POST, KEEP and UNDO at a statement level. Although POST, KEEP, and UNDO blocks cannot be attached to any statement, I believe that allowing post, keep, and undo properties in scoped declarations is powerful enough, and gives the compiler something tangible to attach the actions to. There is a kind of precision in attaching these actions to a specific variable--the state is bound to the variable in a transactionally instantaneous way. I'm afraid if we attach transactional actions to statements as the RFC proposes, it won't be clear exactly when the statement's state change is to be considered successful, since the transaction can't "know" which operation is the crucial one.



I am prejudiced against this one, simply because I've been burned too many times by implicit variables that mandate implicit overhead. I think if you need an index, you should declare one, so that if you don't declare one, the compiler knows not to bother setting up for it.

Another problem is that people will keep asking what


is supposed to mean.

I expect that we'll end up with something more like what we discussed earlier:


RFC 262: Index Attribute

Everyone has a use for : these days...

This one seems not to be of very high utility, suffering from similar problems as the RFC 120 proposal. I don't think it's possible to efficiently track the container of a value within each contained object unless we know at compile time what a looping construct is, which is problematic with user-defined control structures.


Again, I'd rather have something declared so we know whether to take the overhead. Then we don't have to pessimize whenever we can't do a complete static analysis.

RFC 167: Simplify do BLOCK Syntax



[Update: Bare blocks are still legal, and always execute immediately as expected. To return a closure you should use an explicit return.]

RFC 209: Fuller integer support in Perl.

The old use integer pragma was a hack. I think I'd rather use types and representation specs on individual declarations for compile-time selection, or alternate object constructors for run-time selection, particularly when infinite precision is desired. I'm not against using pragmas to alter the defaults, but I think it's generally better to be more specific when you have the capability. You can force your programs to be lexically scoped with pragmas, but data wants to flow wherever it likes to go, so your lexically scoped module had better be able to deal rationally with any data thrown at it, even if it isn't in the exact form that you prefer.

By the way, the RFC is misleading when it asserts that 32-bit integer precision is lost when represented in floating point. That's only true if you use 32-bit floats. Perl has always used 64-bit doubles, which give approximately 15 digits of integer precision. (The issue does arise with 64-bit integers, of course.)

All that being said, Perl 6 will certainly have better support for integer types of various sorts. I just don't think that a pragma redefining what an "integer" is will provide good documentation to whoever is trying to understand the program. Better to declare things of type MagicNum, or whatever.


RFC 279: my() syntax extensions and attribute declarations

We already treated this in Apocalypse 2.


And again, it doesn't make much sense to me to put properties on a variable at run-time.


RFC 297: Attributes for compiler hints

Sorry, we can't have the semantics suddenly varying drastically merely because the user decided to run the program through a different translator. I think there's a happy medium in there somewhere where we can have the same semantics for both interpreter and compiler.

RFC 309: Allow keywords in sub prototypes

This RFC is rejected only because it doesn't go far enough. What we'll eventually need is to allow a regex-ish syntax notation for parsing that may be separate from the argument declarations. (Then again, maybe not.) In any event, I think some kind of explicit regex notation is called for, not the promotion of identifiers to token matchers. We may want identifiers in signatures for something else later, so we'll hold them in reserve.

[Update: This functionality is provided by macros using the is parsed trait. See A06.]

RFC 340: with takes a context

This seems like a solution in search of a problem. Even if we end up with a context stack as explicit as Perl 5's, I don't think the amount we'll deal with it warrants a keyword. (And I dislike "return with;" as a needlessly opaque linguistic construct.)

That being said, if someone implements (as user-defined code) the Pascalish with as proposed in RFC 342 (and rejected), and if the caller function (or something similar) returns sufficient information to build references to the lexical scope associated with the call frame in question, then something like this could also be implemented as user code. I can't decide whether it's not clear that this is a good idea, or it's clear that this is not a good idea. In any event, I would warn anyone doing this that it's likely to be extremely confusing, akin to goto-considered-harmful, and for similar reasons, though in this case by displacing scopes rather than control flow.


So I think we'll stick with closures and continuations that don't transport lexical scopes at runtime.

RFC 342: Pascal-like "with"

I expect Perl's parsing to be powerful enough that you could write a "with" if you wanted one.

Withdrawn RFCs ^

RFC 063: Exception handling syntax

RFC 113: Better constants and constant folding

Other decisions ^

C-style for loop

Due to syntactic ambiguities with the new for syntax of Perl 6, the generalized C-style for loop is going to get its keyword changed to loop. And for will now always mean "foreach". The expression "pill" is now optional, so instead of writing an infinite loop like this:

    for (;;) {

you can now write it like this:

    loop {

C-style do {} while EXPR no longer supported


    do {
    } while CONDITION;


    loop {
        last unless CONDITION;

[Update: We'll also allow the <loop {...} while CONDITION;> form to mean execute once first. Loop until also works, of course.]

Bare blocks

In Perl 5, bare blocks (blocks used as statements) are once-through loops. In Perl 6, blocks are closures. It would be possible to automatically execute any closure in void context, but unfortunately, when a closure is used as the final statement in an outer block, it's ambiguous as to whether you wanted to return or execute the closure. Therefore the use of a closure at the statement level will be considered an error, whether or not it's in a void context. Use do {} for a "once" block, and an explicit return or sub when you want to return a reference to the closure.

[Update: Bare blocks are legal again and work as expected.]

continue block



can now be defined as equivalent to:

    while EXPR2 {
        NEXT { EXPR3 }


[Update: s/POST/LEAVE/]

Well, that about wraps it up for now. You might be interesting to know that I'm posting this from the second sesquiannual Perl Whirl cruise, on board the Veendam, somewhere in the Carribean. If the ship disappears in the Bermuda Triangle, you won't have to worry about the upcoming Exegesis, since Damian is also on board. But for now, Perl 6 is cruising along, the weather's wonderful, wish you were here.

syntax highlighting: