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