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