On Sun, Jan 07, 2007 at 11:42:05AM +0000, Luke Palmer wrote:
: >+    Any       .foo      method truth            ?any($_.foo)
: 
: So... why the any() ?  (0,"",undef,0) should be considered false?

Just trying to carry the "intersection" idea through to a method that
might return a list of things.  But as you say, there's conflicting
pulls going on that we'll need a better way of resolving.

: >+    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?

I suppose that would work.  I suspect it's highly unusual to ask $_
for its own pattern to match itself against though.

: >+    Any       Bool      simple truth            $x.true given $_
: 
: Why given $_ ?

There's a lot of redundancy currently that's just there to emphasize
what's going on.  Agree the redundancy should be marked as redundant
somehow, much like in musical notation you put (#) to remind you that
something is already sharped.

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

It bothers me for a different reason.  I'd like to be able to say

    given $something {
        when 1 {...}
        when 2 {...}
        when 3 {...}
        when 4 {...}
    }

and have it build a jump table without having to say +$something, but we
can't do that if Num does inconsistent kinds of matches.  I think if
$something := @array then it should probably consistently dispatch based
on the length of the array, which is consistent with +$something, unlike
the autogrepping behavior.

: 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) {...}

or just

    when .any == $num

which makes me think that %hash.any should do %hash.keys.any maybe.

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

And like the Num one it clobbers the optimizability of

    given $something {
        when "foo" {...}
        when "bar" {...}
        when "baz" {...}
    }

: >+    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 (?).

Presumably warns.

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

I agree that we should have a consistent test based on the righthand type,
and rely on something to bend that type for different matches, or possibly
some keyword that biases to a particular style.  Trying to push both
partial matches and complete matches into the same syntax isn't working.

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

That's the approach I'm taking.

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

Well, arguably the default could also be intersection, but that's oddly
symmetrical compared to other patterns.

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

Me too.

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

It would indeed confuse term vs operator expections.   I think either of

    given $something {
        when $_ === $x {...}
    }

    given { $something === $_ } {
        when .($x) {...}
    }

probably is Good Enough For Now.

: 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,*] {...}

Which

    when * -> 1, * {...}

might give us as a form of binding.  Maybe even

    when * -> *, 1, $a, 2, $b 3, * {...}

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

I almost put in a */Capture to rebind the given's block.  :)

: >+    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?

See subsequent fix for definition of "top 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!

Figured you'd like that one...specially since it degenerates to what
we had before.

Anyway, thanks for reminding about the things that were bothering me
already, or that should have and didn't yet.  :)

Larry

Reply via email to