Perl6-Doc

 view release on metacpan or  search on metacpan

share/Apocalypse/A04.pod  view on Meta::CPAN

construction. So instead, since switch statements are into heavy
dwimmery anyway, I think the switch statement will have to recognize
any C<Class::Name> known at compile time, and force it to call
C<$!.isa(Class::Name)>.

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

Another possible adjustment will involve the use of switch statements
as a means of parallelizing regular expression evaluation.
Specifically, we want to be able to write parsers easily in Perl, which
means that we need some way of matching a token stream against
something like a set of regular expressions. You can think of a token
stream as a funny kind of string. So if the "given" of a switch
statement is a token stream, the regular expressions matched against it
may have special abilities relating to the current parse's data
structure. All the regular expressions of such a switch statement will
likely be implicitly anchored to the current parse location, for
instance. There may be special tokens referring to terminals and
non-terminals. Basically, think of something like a yacc grammar, where
alternative pattern/action grammar rules are most naturally expressed
via switch statement cases. More on that in the next Apocalypse.

[Update: Parsing rules tend to use the C<: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 C<else> block could be
considered unnecessary. The code following the final C<when> is
automatically an "else". Here's a duodecimal digit converter:

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

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 C<else>. Also, because of the identification of
C<when> and C<if>, it would not be clear whether an C<else> should
automatically supply a C<break> at the end of its block as the ordinary
C<when> case does.

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

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

Unlike in C, the C<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 C<if>/C<elsif>/C<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 { ... }
        print "didn't match $first; let's try $next";
        when $next { ... }
        print "giving up";
        default { ... }
        die "panic: shouldn't see this";
    }

We can still define C<when> as a variant of C<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 C<default> isn't quite the same as an
C<else>, since C<else> can't stand on its own. A C<default> is more
like an C<if> that's always true. So the above code is equivalent to:

    given $given {
        print "about to check $first";
        if $given =~ $first { ...; break }
        print "didn't match $first; let's try $next";
        if $given =~ $next { ...; break }
        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 C<.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 C<.id> method, which would be unclear how to compare,
there's a C<=:=> operator for comparing identities.  Though you can always
compare two id's with the C<===> 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.)

Some of the table entries distinguish an array from a list. Arrays look
like this:

    when [1, 3, 5, 7, 9] { "odd digit intersection" }
    when @array          { "array intersection" }

while a list looks like this:



( run in 0.561 second using v1.01-cache-2.11-cpan-b16cb0d3907 )