On 1/7/07, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote
Author: larry
Date: Sun Jan  7 00:50:30 2007
New Revision: 13515

Modified:
   doc/trunk/design/syn/S03.pod

+    $_        $x        Type of Match Implied   Match if
+    ======    =====     =====================   =============
+    Any       Code:($)  scalar sub truth        $x($_)
+    Any       Code:()   simple closure truth    $x() (ignoring $_)
+    Any       undef     undefined               not defined $_
+    Any       *         block signature match   block successfully binds to |$_
+    Any       .foo      method truth            ?any($_.foo)

So... why the any() ?  (0,"",undef,0) should be considered false?

+    Any       .foo(...) method truth            ?any($_.foo(...))
+    Any       .(...)    list sub call truth     ?any($_(...))
+    Any       .[...]    array value slice truth ?any($_[...])
+    Any       .{...}    hash value slice truth  ?any($_{...})
+    Any       .<...>    hash value slice truth  ?any($_<...>)

Hmm, so how do you say "no, consider the return value of this method
call as a pattern."  Is it just "when $_.foo() { ... }"; i.e. when you
use an explicit invocant, it falls through all syntactic forms?

+    Any       Bool      simple truth            $x.true given $_

Why given $_ ?

+    Num       Num       numeric equality        +$_ == $x
+    Capture   Num       numeric equality        +$_ == $x
+    Array     Num       array contains number   any(@$_) == $x

I don't know about these array and hash forms.  I know it is "smart
match", but the notion that an array somehow matches a number is
dubious.  Especially since Array ~~ Set does not check for "array
contains set".  I could buy, perhaps, an array matching its length as
a number, but even that's a bit of a stretch.

I'm much more in favor of pattern constructors of some kind like what
I suggested earlier:

   when contains($num) {...}

The only thing I worry about is namespace pollution, since such
constructors don't seem such "generally applicable" things. But I
guess we are going to great lengths to allow a large vocabulary while
still avoiding that (eg. putting method calls in a different
namespace, allowing detailed scoping control).

Or we could stick it in the Pattern namespace or something:

   when Pattern::contains($num) {...}

Or, hey, why not just put it in the Array namespace:

   when .contains($num) {...}

+    Hash      Num       hash key existence      $_.exists($x)

I also think that the hash key existence forms are likely not to be
put into when's very often.  I think it will be much more common to
see:

   if %hash<foo> {...}
   if %hash<bar> {...}
   if %hash<baz> {...}

Than:

   if %hash<foo> {...}
   elsif %hash<bar> {...}
   elsif %hash<baz> {...}

So given/when doesn't really seem like the right place for this (in
addition to the issues with arrays above).  "when .exists($x)" seems
sufficient.

+    Byte      Num       numeric equality        +$_ == $x
+    Any       Num       numeric equality        +$_ == $x

That + in front of the $_ is a little strange, too.  You'd get that
"foobar" ~~ 0.  With a warning, I suppose (?).

+    Str       Str       string equality         $_ eq $x
+    Capture   Str       string equality         ~$_ eq $x
+    Array     Str       array contains string   any(@$_) eq $x
+    Hash      Str       hash key existence      $_.exists($x)
+    Byte      Str       string equality         ~$_ eq $x
+    Any       Str       string equality         ~$_ eq $x
+
+    Buf       Buf       buffer equality         $_ eq $x
+    Str       Buf       string equality         $_ eq Str($x)
+    Array     Buf       arrays are comparable   $_ »===« @$x
+    Hash      Buf       hash key existence      $_.exists($x)
+    Any       Buf       buffer equality         Buf($_) eq $_
+
+    Buf       Byte      buffer contains byte    $_.match(/$x/)
+    Str       Byte      string contains byte    Buf($_).match(/$x/)
+
+    Str       Char      string contains char    $_.match(/$x/)
+    Buf       Char      string contains char    Str($_).match(/$x/)

Very strange.  I suppose it's consistent with the array views I was
contesting above, but I think this example just helps drive home the
absurdity of that match.

+    Hash      Set       hash keys same set      $_.keys === $x

You can either think of a hash as a set of pairs, or you can just
project to a set of its keys.  As long as we're consistent about going
with a latter, I think it will be okay.

Actually, it might be nice; though I think it will be more common to
want to know whether a hash *contains* a set of keys rather than have
exactly those keys.  See below.

+    Array     Set       array equiv to set      Set($_) === $x
+    Set       Set       identical sets          $_ === $x

See above.  The same argument applies here, I suppose.  It seems
inconsistent and unpredictable for smart match against a set to mean
subset for a hash (which is just being thought of as a set) and
equivalent for a set.  I'm really not sure about this (or the last)
one.

Perhaps we should take a lesson from the Pattern paradigm and define
in English the purpose of each type as a pattern.  After all, we are
not trying to define equivalence (for the fifth time), but having a
pattern mean several different things based on what you're comparing
it to isn't much like a pattern.  We can use "$_ === $x" for
equivalence (or perhaps even define "when === $x" for that, but that
might get us into parsing troubles with, eg. "when < $x".

So, to ask what a pattern means, I think we should ask what you're
most likely to ask about using a literal of this type, without respect
for what you're asking.  I may be more liberal in a statically-typed
language, since we know for sure what kind of thing we're asking.
That brings up a philosophical issue that somehow in a dynamically
typed issue you don't know what you're asking, when in fact you
usually do.  I guess I have a tendency to dislike things whose meaning
is allowed to differ (in a way significant enough that will affect how
you read it) at runtime.

Okay, enough philosophical garbage.  I think the atomic types get a
pretty clear interpretation: equivalence.

I would say that array gets an "element of" relation if we didn't
already have junctions and it didn't throw away the order.  I can see
array equivalence being useful if we had unification: something like:

   when [1,*] {...}

Perhaps aggregates forward pattern matching to embedded patterns in
some way.  But unification is really limited if you're not allowed to
do binding as well.  Or maybe arrays just do equivalence.  I'm not
sure.

Hashes are even tougher.  I'm not really sure how to approach them.
What would you match against a literal hash?

Sets as "contains this set" makes sense to me.   The problem I have
with equivalence with aggregates is that usually when you're dealing
with aggregates, you're working with them because you don't know
what's in them.  I think of the subset thing as matching a poor man's
interface of some sort.  "If this hash can tell me about paragraphs
and unordered lists, then I know what to do with it'.   It's harder to
justify for arrays; I think of arrays as telling me what order things
go in (or representing a queue or a stack). In the first sense, it
sort of makes sense.

+    Any       Set       identical sets          Set($_) === $x

+
+    Array     Array     arrays are comparable   $_ »===« $x
+    Buf       Array     arrays are comparable   @$_ »===« $x
+    Str       Array     array contains string   any(@$x) eq $_
+    Num       Array     array contains number   any(@$x) == $_
+    Hash      Array     hash slice exists       $_.exists(any(@$x))
+    Scalar    Array     array contains object   any(@$x) === $_
+    Set       Array     array equiv to set      $_ === Set($x)
+    Any       Array     lists are comparable    @$_ »===« $x
+
+    Hash      Hash      hash keys same set      $_.keys === $x.keys
+    Set       Hash      hash keys same set      $_ === $x.keys
+    Array     Hash      hash slice existence    $x.exists(any @$_)
+    Regex     Hash      hash key grep           any($_.keys) === /$x/
+    Scalar    Hash      hash entry existence    $x.exists($_)
+    Any       Hash      hash slice existence    $x.exists(any @$_)
+
+    Str       Regex     string pattern match    $_.match($x)
+    Hash      Regex     hash key grep           any($_.keys) === /$x/
+    Array     Regex     match array as string   cat(@$_).match($x)
+    Any       Regex     pattern match           $_.match($x)
+
+    Num       Range     in numeric range        $x.min <= $_ <= $x.max (mod 
^'s)
+    Str       Range     in string range         $x.min le $_ le $x.max (mod 
^'s)
+    Any       Range     in generic range        [!after] $x.min,$_,$x.max 
(etc.)
+
+    Any       Type      type membership         $_.does($x)
+
+    Signature Signature sig compatibility       $_ is a subset of $x      ???
+    Code      Signature sig compatibility       $_.sig is a subset of $x  ???
+    Capture   Signature parameters bindable     $_ could bind to $x (doesn't!)
+    Any       Signature parameters bindable     |$_ could bind to $x (doesn't!)

These make quite a lot of sense to me, though I am a little disturbed
in general about the instance/subtype ambiguity (which one does it
mean?).  Perhaps I can live with that one.

+    Signature Capture   parameters bindable     $x could bind to $_

Definitely, though the inevitable repetition is unsettling from a
coding practices point of view.

+    Set       Scalar    set member exists       any($_.keys) === $x
+    Hash      Scalar    hash key exists         any($_.keys) === $x
+    Array     Scalar    array contains item     any(@$_) === $x
+    Scalar    Scalar    scalars are identical   $_ === $x


+Matching against a C<Grammar> object will call the first rule defined
+in the grammar.

Perhaps this is just because Grammar is just a subtype of Rule?

+Matching against a C<Signature> does not actually bind any variables,
+but only tests to see if the signature I<could> bind.  To really bind
+to a signature, use the C<*> pattern to delegate binding to the C<when>
+statement's block instead.  Matching against C<*> is special in that
+it takes its truth from whether the subsequent block is bound against
+the topic, so you can do ordered signature matching:
+
+    given $capture {
+        when * -> Int $a, Str $b { ... }
+        when * -> Str $a, Int $b { ... }
+        when * -> $a, $b         { ... }
+        when *                   { ... }
+    }

Ooh ooh!  Yay!

Luke

Reply via email to