Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
David Green writes: On 8/13/06, Smylers wrote: Please could the proponets of the various behaviours being discussed here share a few more concrete examples ... OK, Thanks for that. In summary, if I've understood you correctly, it's that: =:= two aliases to the same actual variable === one variable contains a copy of the other's actual contents eqv both contain contents which represent the same thing but may have come from different sources And that being true at one level implies being true for the above levels. Yes? === Example: Suppose I have some employee objects, and I employ two John Smiths. They have the same name, work in the same department, and by stunning coincidence everything my class knows about them just happens to be the same. Except that they wouldn't. Because each one would have a separate payroll number, or some artificial thing invented just for the sake of being different. So this example doesn't sound plausible to me. But they're still different objects (the payroll system definitely needs to produce two cheques, although since they earn the same salary, it doesn't matter which one of them gets which cheque); so $john1 !=== $john2, and I can tell them apart. And why on earth would you be making such a comparison? If you have a list of employees who need cheques then you just iterate through them and process them in turn; you wouldn't be comparing an arbitrary pair of them. So I now understand what this operator does. But I'm still struggling to fathom where I would ever have a use for it. Smylers
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
David Green schreef: === ...is equality-of-contents, basically meaning that the things you're comparing contain the same [...] values. How about strings; are normalized copies used with the === ? http://www.unicode.org/faq/normalization.html http://www.unicode.org/notes/tn5/ -- Affijn, Ruud Gewoon is een tijger.
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On 8/14/06, Smylers wrote: David Green writes: Thanks for that. In summary, if I've understood you correctly, it's that: =:= two aliases to the same actual variable === one variable contains a copy of the other's actual contents eqv both contain contents which represent the same thing but may have come from different sources And that being true at one level implies being true for the above levels. Yes? Right. (Where the ordering for above means =:= implies ===, and === implies eqv, but not in the other direction, of course.) === Example: Suppose I have some employee objects, and I employ two John Smiths. They have the same name, work in the same department, and by stunning coincidence everything my class knows about them just happens to be the same. Except that they wouldn't. Because each one would have a separate payroll number, or some artificial thing invented just for the sake of being different. So this example doesn't sound plausible to me. Well, I didn't say it was a *good* payroll system! OK, it's a silly contrived example; maybe my objects should have represented the reticulated flanges I have in stock, since one piece of inventory is the same as any other. Except I wouldn't really create an object for each one, I'd just have a single group-object that contained a $num_available counter (Anyone cleverer than I should feel free to jump in with a better example.) So I now understand what this operator does. But I'm still struggling to fathom where I would ever have a use for it. Maybe you wouldn't -- eqv is what most of us will use most of the time, I expect (being the ordinary everyday parallel to == and eq). But since it is possible to use variables both by value and by reference, there still needs to be a way to work with and compare both of them when you want to do fancy advanced stuff. -David
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On July 14th Yuval Kogman wrote: On Fri, Jul 14, 2006 at 11:42:24 +0100, Smylers wrote: I'm afraid I still don't get it. Or rather, while I can manage to read an explanation of what one of these operators does and see how it applies to the variables in the examples next to it, I am struggling to retain a feeling of _why_ I would want to use any of these operators in real-life Perl 6 code. To compare deep structures ;-) Already in Perl 5 having 2 different equality operators is something that learners often stumble over. But only for low level types. To see if two objects are the same, or two hashes, you need to use Data::Compare, or to overload either == or eq, neither of which is a perfect fit. I have to catch my flight, so I'll explain more later. Hi there. Ann's (excellent, very useful, and much appreciated) summary reminded me that this was still pending. Did you catch your flight? For the benefit of anybody else who's struggling to remember a thread from a month ago this was my original request. Please could the proponets of the various behaviours being discussed here share a few more concrete examples which start by explaning a scenario in which there is a desire to do something, preferably one that Perl 5 coders can identify with, and then show how one of these new operators would meet that desire (and that without that operator it would be hard or clumsy to achieve the same thing)? Cheers. Smylers
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On 8/13/06, Smylers wrote: Please could the proponets of the various behaviours being discussed here share a few more concrete examples which start by explaning a scenario in which there is a desire to do something, preferably one that Perl 5 coders can identify with, and then show how one of these new operators would meet that desire (and that without that operator it would be hard or clumsy to achieve the same thing)? OK, if I can come up with examples that make sense, then that probably means I actually understand it myself! eqv ...is your standard equality-of-values, which would be just = or == in many languages, and which Perl has never really had. == and eq coerce their operands to be numbers or strings, which was fine back in days or yore when Perl only had nums and strings. With the introduction of references/objects, Perl effectively got user-definable types without a user-definable equality operator, so you either had to rely on suitable numifications (or stringifications) of your objects to make sense, or overload stuff, or something. In P6 you can just compare their values in a normal way (or still numify/stringify them using == or eq if that's what you want). Example: I have a Date class that lets each of its objects carry around its own different epoch value, so using == won't work (unless both dates that I'm comparing happen to share the same epoch -- a yucky work-around might be if $a==$b $a.epoch==$b.epoch). And let's suppose my Dates are text-insensitive-but-preserving, meaning that objects created as 2006/1/1 and as Jan. 1, 2006 return those exact strings when stringified, even though they represent the same date: so comparing with eq won't work either. Instead I want to compare my dates with eqv which compares their real values. (Real is determined by the class -- this is where the Special Key ID stuff comes in. In this example, the SKID for a date might be an int using a fixed epoch; or it might be a text representation in canonical form. The user doesn't have to care, of course.) (eqv also means you no longer need code like if (we're using ints) return $a==$b else if (we've got strings) return $a eq $b, which was occasionally a pain even in those Days of Yore. Now that P6 can use variable types, you don't [necessarily] need to specify the type in the equality operator, you can just use eqv to do the appropriate kind of comparison. (And cmp is becoming the analogue of eqv instead of eq.)) === ...is equality-of-contents, basically meaning that the things you're comparing contain the same variables and values. (E.g. things that are references to other variables, possibly nested in some kind of data structure.) Now if you have a couple of plain old ints, then it's the same as testing whether they have the same values (eqv). But if $a contains a ref to @x and $b contains a ref to @y, then $a will not === $b. (Unless @x and @y are really the same variable in disguise, of course. $a might *eqv* $b, because @x and @y could have the same value, but as long as $x and $y are different guys, then $a !=== $b. Conversely, if $a does === $b, then they must have the same value too, i.e. it follows that $a eqv $b.) Example: Suppose I have some employee objects, and I employ two John Smiths. They have the same name, work in the same department, and by stunning coincidence everything my class knows about them just happens to be the same. So they're basically indistinguishable (serialising one John Smith object produces the same results as the other -- and indeed, $john1 eqv $john2). But they're still different objects (the payroll system definitely needs to produce two cheques, although since they earn the same salary, it doesn't matter which one of them gets which cheque); so $john1 !=== $john2, and I can tell them apart. In fact, === is how a hash tests its keys (assuming it's a hash that uses objects rather than a P5-like hash that uses stringy keys -- of course, for a string hash, === wouldn't work out any different from eqv anyway). =:= ...is equality-of-variable, or binding -- it simply checks whether its operands are both the same variable (possibly under different names). This might be a little esoteric for ordinary code (if there is any such thing), but binding is pretty common in P6, even if inconspicuous: sub foo($a, $b) will bind $x to both $a and $b if I call foo($x, $x). I might want to know whether my $a and $b really are the same variable passed in twice or not. Example: a fairly simple reason why you might care whether you've got the same variable twice is if you're doing some expensive comparison -- an easy optimisation is to check whether the two things you're comparing are really the same thing to start with. (Or, going back to my double John Smiths setup, my payroll functions can make sure that all the John Smith really are different people, and not a single
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
Way back on 7/14/06, Larry Wall wrote: On Thu, Jul 13, 2006 at 10:19:24PM -0600, David Green wrote: [...] No, === is also deep. It's only shallower (or potentially shallower) in the sense that it treats any mutable object node as a leaf node rather than changing to snapshot semantics like eqv does. Yup, which it would have to be even given the slightly-off way I was thinking of it. So I've quietly snipped the part where I said it wasn't and will pretend it was never there. : (One [1,2] is as good as any other [1,2] -- what's the use of ever : having them not compared as the same? I can see maybe for =:=, since : something that doesn't have a name cannot, by definition, have the : same name as something else... although even there, it arguably makes : sense to consider equivalent anonymous values as bound to the same : place. There's only one unique [1,2] in platonic heaven, I'm just : mentioning it directly instead of dropping a name.) On the contrary, there isn't one single platonic [1,2], since square brackets construct a mutable Array object: @a := [1,2]; @b := [1,2]; @b[0]++; say @a @b; # 1 2 2 2 $ perl -e 'print ++([1,2]-[1])' 3 Hmm... well, I guess I shouldn't be surprised that that worked, it makes sense -- you can't have an array-ref unless it refers to something. But something still bothers me... Perl knows that my anonymous array-ref is pointing at something, so it's [effectively] got some kind of internal name that it knows about, but I don't. So it isn't really anonymous... it's a Rumpelstiltskin array! I guess my problem is that [1,2] *feels* like it should === [1,2]. You can explain that there's this mutable object stuff going on, and I can follow that (sort of...), but it seems like an implementation detail leaking out. In many languages, strings are just character arrays, and presumably someone could write a version of Perl that actually built strings out of array refs, but I'd still want foo to === foo. And I feel this way because [1,2] looks like it should be platonically unique. Or at least leibnizianly unique: if two things don't have any different features, then they aren't different. And one [1,2] can do anything that another [1,2] can. ...Except have the same object ID, which doesn't seem particularly useful, except for distinguishing them, which is what I don't want to do. Is there a useful non-implementary reason to tell them apart (excepting obfuscated P6 and stuff Damian might do), or can you just hide it?? (Ignorance is bliss for bears of little brain like me.) Some convenient skidding around to make identical array-refs look, well, the identical. Of course, when you suppress one thing, you have to start stomping down spots all over the waterbed, and eventually it might burst. Maybe I'm just not thinking about it from the right direction... Do I feel that \1 (a ref to a literal 1) should be platonic? Does it matter? As you said, ordinarily I'll be assigning rather than binding, so stuff will just work. Can I make a nested Seq with something like (1;2; 3,4)? Compared to the nested Array referential [1,2, [3,4]]? [EMAIL PROTECTED] should be different from (!===) [EMAIL PROTECTED] because even if @a eqv @b eqv (1,2), @b might change. But if $a=[1,2] and $b=[1,2] there's nothing I can change that will make $a and $b different, so for $a not to === $b is Fairly Surprising in Principle. That is, nothing *else* I can change, since of course changing either $a or $b will make them different. You may tell me that $b[0]++ *is* changing something other than $b, but it sure looks like changing $b. The only way I can get at the original [1,2] is by going through $b, so I think I am changing $b. But wouldn't I think the same thing if [EMAIL PROTECTED] and I do $b[0]++? It might look superficially as though I were changing $b, but $b still is [EMAIL PROTECTED] -- @b is what's really changed. Hmmm. If Perl is simply more complex, there's no point my trying to hold a naive view. Maybe it's one of those things that never will seem quite comfortable until I just get used to it -David
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
I think that Jonathan meant for his reply to my message to go to the list, so I am including it in its entirety, in my reply. At 11:23 PM -0700 7/13/06, Jonathan Lang wrote: Darren Duncan wrote: Jonathan Lang wrote: So the purpose of === is to provide a means of comparison that doesn't implicitly coerce its arguments to a particular type? Yes, absolutely. The === takes 2 arguments exactly as they are, without changing anything, and says if they are two appearances of the same value. It would always return false if the 2 arguments are of different declared types. And if they are of the same types, then no coersion is necessary in order to compare them for equality. So the difference between eqv and === is: @a eqv @b iff all(for each(@a, @b) - $a, $b { $a === $b }) # a deep comparison or @a === @b iff all(for each(@a, @b) - $a, $b { $a =:= $b }) # a shallow comparison ? That seems counterintuitive to me; I'd rather see both === and eqv represent a deep comparison, and leave shallow comparisons to less elegant approaches. I see eqv and === as both being recursive with their own kinds when used on any and immutable data types respectively. Arrays are mutable, so I see that the above examples mean the following (only relevant parts changed, other syntax parts may be wrong): @a eqv @b iff all(for each(@a, @b) - $a, $b { $a eqv $b }) # a deep comparison using eqv all along @a === @b iff @a =:= @b # a shallow comparison since === only tests immutable aspects Now, lets try two Seq, $a and $b, instead, which are like Array but immutable: $a === $b iff all(for each($a.values, $b.values) - $a, $b { $a === $b }) # a deep-as-possible comparison using === all along Assuming that all elements of $a and $b are themselves immutable to all levels of recursion, === then does a full deep copy like eqv. If at any level we get a mutable object, then at that point it turns into =:= (a trivial case) and stops. Note that if your Seqs just contain other immutable things like Str or Int or Set or Pair or Mapping etc to all recursion levels, which they are highly likely to do, then === is simply a deep recursion. That's how I understand it, and it seems quite elegant and simple. -- Darren Duncan
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
Yuval Kogman writes: So, Larry assisted by Audrey explained the purpose of === vs eqv vs =:=. I'm afraid I still don't get it. Or rather, while I can manage to read an explanation of what one of these operators does and see how it applies to the variables in the examples next to it, I am struggling to retain a feeling of _why_ I would want to use any of these operators in real-life Perl 6 code. Please could the proponets of the various behaviours being discussed here share a few more concrete examples which start by explaning a scenario in which there is a desire to do something, preferably one that Perl 5 coders can identify with, and then show how one of these new operators would meet that desire (and that without that operator it would be hard or clumsy to achieve the same thing)? Already in Perl 5 having 2 different equality operators is something that learners often stumble over. If we're going to have 5 of the things in Perl 6 then there needs to be a very clear way of explaining how to determine which one to use (or at least an explanation that 3 of the operators are very esoteric and beginners don't need to worry about them). Smylers
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On Fri, Jul 14, 2006 at 11:42:24 +0100, Smylers wrote: I'm afraid I still don't get it. Or rather, while I can manage to read an explanation of what one of these operators does and see how it applies to the variables in the examples next to it, I am struggling to retain a feeling of _why_ I would want to use any of these operators in real-life Perl 6 code. To compare deep structures ;-) Already in Perl 5 having 2 different equality operators is something that learners often stumble over. But only for low level types. To see if two objects are the same, or two hashes, you need to use Data::Compare, or to overload either == or eq, neither of which is a perfect fit. I have to catch my flight, so I'll explain more later. -- Yuval Kogman [EMAIL PROTECTED] http://nothingmuch.woobling.org 0xEBD27418 pgp4zdMSoN13m.pgp Description: PGP signature
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
Yuval Kogman writes: On Fri, Jul 14, 2006 at 11:42:24 +0100, Smylers wrote: Or rather, while I can manage to read an explanation of what one of these operators does and see how it applies to the variables in the examples next to it, I am struggling to retain a feeling of _why_ I would want to use any of these operators in real-life Perl 6 code. To compare deep structures ;-) Thank you. That helps. My initial instinct was that this meant the new operators can all be dismissed as ignorable by learners, as they won't be using nested data structures anyway. But actually deep doesn't have to be very deep in order for such a comparison op to have use: merely wanting to see if the contents of 2 arrays are the same doesn't involve any nesting and is a concept that is well within the grasp of a beginner. so I'll explain more later. Great. I appreciate your help, and I'm looking forward to your explanation of the different behaviours in this thread. Smylers
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
Darren Duncan wrote: Now, I didn't see them yet anywhere in Synopsis 3, but I strongly recommend having negated versions of all these various types of equality tests. Eg, !== for ===, nev for eqv, etc. They would be used very frequently, I believe (and I have even tried to do so), and of course we get the nice parity. Yes and they should be strictly implicitly defined in term of the positive versions in such a way that you can't explicitly redefine them separately. I.e., $x !== $y should always mean exactly the same thing as !($x === $y). Maybe by a macro definition. To do otherwise would be very confusing as it would make such simple program transformations as: say foo if $x !== $y; into say foo unless $x === $y; very unreliable. Actually a similar argument could be made about '' vs '', '=' and '=' in other words just redefining '==' '' should automatically get you '!=', '=', '=' and ''. -- [EMAIL PROTECTED] [EMAIL PROTECTED]
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
Darren Duncan wrote: Assuming that all elements of $a and $b are themselves immutable to all levels of recursion, === then does a full deep copy like eqv. If at any level we get a mutable object, then at that point it turns into =:= (a trivial case) and stops. ( 1, 2.0, 3 ) === ( 1,2,3 ) True or false? More imprtantly, how do I tell perl what I mean? The best I can think of is: [] (@a »==« @b) Vs [] (@a »eq« @b) But this only works for nice flat structures. For arbitrary tree structures, we probably need adverbs on a comparison op (I think Larry mentioned this a few posts back) ... but if we're going with adverbs do we really need 5 different base operators? Are all of the 5 so common that it would be clumbersome to require adverbs for their behavior? Also, when sorting things, maybe deep inequalities would be useful, too.
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
Mark A. Biggar schreef: Darren Duncan: Now, I didn't see them yet anywhere in Synopsis 3, but I strongly recommend having negated versions of all these various types of equality tests. Eg, !== for ===, nev for eqv, etc. They would be used very frequently, I believe (and I have even tried to do so), and of course we get the nice parity. Yes and they should be strictly implicitly defined in term of the positive versions in such a way that you can't explicitly redefine them separately. I.e., $x !== $y should always mean exactly the same thing as !($x === $y). Maybe by a macro definition. To do otherwise would be very confusing as it would make such simple program transformations as: say foo if $x !== $y; into say foo unless $x === $y; And how about symmetry: say foo unless $y === $x; very unreliable. -- Affijn, Ruud Gewoon is een tijger.
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
At 9:22 AM -0700 7/14/06, Dave Whipp wrote: Darren Duncan wrote: Assuming that all elements of $a and $b are themselves immutable to all levels of recursion, === then does a full deep copy like eqv. If at any level we get a mutable object, then at that point it turns into =:= (a trivial case) and stops. ( 1, 2.0, 3 ) === ( 1,2,3 ) True or false? That would be false, because a Str does not === an Int. I should point out, though, that in at least some situations where you are ===, you would have more control of the creation of the structures in the first place and they will probably have been created in a more strict fashion that required the data to be of corresponding types in the first place. Eg, each Seq would have only been allowed to store Ints in the first place. The best place to normalize input is as early as possible, after all, like when the Ints were input and before they were put in the Seq to be compared. More imprtantly, how do I tell perl what I mean? The best I can think of is: [] (@a »==« @b) Vs [] (@a »eq« @b) But this only works for nice flat structures. For arbitrary tree structures, we probably need adverbs on a comparison op (I think Larry mentioned this a few posts back) ... but if we're going with adverbs do we really need 5 different base operators? Are all of the 5 so common that it would be clumbersome to require adverbs for their behavior? Also, when sorting things, maybe deep inequalities would be useful, too. I will punt on that one. -- Darren Duncan
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
At 6:55 PM +0200 7/14/06, Dr.Ruud wrote: say foo if $x !== $y; into say foo unless $x === $y; And how about symmetry: say foo unless $y === $x; very unreliable. Any equality or inequality operator is commutative, so it doesn't matter whether you have $x and $y or $y and $x, the result is the same. So you can use whichever order you want without it needing to be coded for. -- Darren Duncan
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On Thu, Jul 13, 2006 at 10:56:59PM -0700, Darren Duncan wrote: : Now, I didn't see them yet anywhere in Synopsis 3, but I strongly : recommend having negated versions of all these various types of : equality tests. Eg, !== for ===, nev for eqv, etc. They would be : used very frequently, I believe (and I have even tried to do so), and : of course we get the nice parity. My gut feeling contradicts yours--I think these are going to be far rarer in practice than == and eq, so they don't warrant yet more special forms that have to be memorized. And !== is too easy to confuse with != visually, or with !(==) semantically. For such long operators, I'd try to do exact syntactical composition rather than replacement, so they'd be !=== and neqv, probably, along with !=:=. Maybe even go with !eqv rather than neqv, and make ! into a metaoperator on relationals. Then !== and !eq would be identical to != and ne. But a lot of the time the negated versions are going to be disallowed anyway, simply because English mangles junctions when it does not raising. Valid English: If X doesn't equal one or two or three, say out of range. Naïve Perl: if $x != 1 | 2 | 3 { say out of range; } But that's wrong because Perl doesn't do not raising, so the statement above always prints out of range. You should have said one of: if not $x == 1 | 2 | 3 { say out of range; } if $x != 1 2 3 { say out of range; } So either we have to make Perl do not-raising like English, which will probably confuse non-English speakers, or we have to disallow negative operators from participating in junctional logic, or we have a huge educational problem (read FAQ). My money is currently on disallowing distribution of junctions over negated operators, and forcing people to do not-raising explicitly, at least in the syntactic case above. Perhaps we can still allow the semantics where it's not likely to be confused with English. Anyway, that's just another reason for going slow on throwing in the negated versions. Larry
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
At 12:55 PM -0700 7/14/06, Larry Wall wrote: On Thu, Jul 13, 2006 at 10:56:59PM -0700, Darren Duncan wrote (edited): : Now, I didn't see them yet anywhere in Synopsis 3, but I strongly : recommend having negated versions of all these various types of : equality tests. Eg, !=== for ===, !eqv for eqv, etc. They would be : used very frequently, I believe (and I have even tried to do so), and : of course we get the nice parity. My gut feeling contradicts yours--I think these are going to be far rarer in practice than == and eq, so they don't warrant yet more special forms that have to be memorized. Actually, now that I think about it, I could use 'not' to avoid a lot of the syntactic hassle that I've been having with a lack of !===. Eg, what I wanted was to avoid having to say: if (!($foo === $bar) and ...) { ... } So I had proposed instead: if ($foo !=== $bar and ...) { ... } But then your post reminded me of 'not', and since it binds tighter than 'and' and 'or', I can say: if (not $foo === $bar and ...) { ... } While I still like the second example best, in light of the issues of not-raising you mention that could confuse others, I'll withdraw my request for now. -- Darren Duncan
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On Fri, Jul 14, 2006 at 09:22:10 -0700, Dave Whipp wrote: Darren Duncan wrote: Assuming that all elements of $a and $b are themselves immutable to all levels of recursion, === then does a full deep copy like eqv. If at any level we get a mutable object, then at that point it turns into =:= (a trivial case) and stops. ( 1, 2.0, 3 ) === ( 1,2,3 ) True or false? false More imprtantly, how do I tell perl what I mean? The best I can think of is: [] (@a »==« @b) Vs [] (@a »eq« @b) Neither - it's on the natural types. If the types are different it's != -- Yuval Kogman [EMAIL PROTECTED] http://nothingmuch.woobling.org 0xEBD27418 pgpdVijcRjp0Q.pgp Description: PGP signature
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
Darren Duncan schreef: Dr.Ruud: say foo if $x !== $y; into say foo unless $x === $y; And how about symmetry: say foo unless $y === $x; Any equality or inequality operator is commutative, If $x and $y are not of the same type, and one or both of the involved types has its own (or overloaded?) 'deep equality operator', the choice (which implementation is used) can depend on the order. Not so long ago, there was an issue with Perl5 in this area (IIRC with '==' and undef). so it doesn't matter whether you have $x and $y or $y and $x, the result is the same. So you can use whichever order you want without it needing to be coded for. -- Darren Duncan -- Affijn, Ruud Gewoon is een tijger.
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On 7/14/06, David Green [EMAIL PROTECTED] wrote: On 7/13/06, Yuval Kogman wrote: So, Larry assisted by Audrey explained the purpose of === vs eqv vs =:=. It makes sense now, but I still feel that as far as ergonomics go this is not perfect. I think I understand it... (my only quibble with the syntax is that === and eqv look like spin-offs of == and eq, but I don't know what to suggest instead (we're running short of combinations of = and : !)) So there are three basic kinds of comparison: whether the variables are the same (different names, but naming the same thing); whether the values are the same (deep comparison, i.e. recursively all the way down in the case of nested containers); and in-between (shallow comparison, i.e. we compare the top-level values, but we don't work out *their* values too, etc., the way a deep comparison would). If I've got it right, this is what =:=, eqv, and === give us, respectively. It may well be that I'm misunderstanding here -- I've been away from Perl development for too long and have a lot of catching up to do -- but I'm uneasy about using the terms shallow comparison and immutably equal to describe the same thing. If the true meaning of $a === $b is that $a.id eq $b.id, where .id is the value for a simple type, I think it'd be least confusing to just call it a shallow comparison. Immutable equality sounds more like a promise of deep and lasting equality, not an assertion that equality is skin deep. I make a similar inference from the long sigil -- it has more the flavor of more equal than a special case of equal (to me, at least). Just to muddy the waters further, I'd think -- off the cuff -- that you might do well with expectations to say == and eq - shallow comparison of numeric and string values, specifically (with other types being free to specify what their numeric and string values are -- caveat usor) Matches existing expectations of these operators === - deeply equal (equivalent to the current eqv); alias for isreally or isdeeply Expectation based on extending the == metaphor eqv - Different names for the same thing (what I think =:= means now) Expectation based on glossing as equivalent rather than equal value. =:=- Defined identically, with no promise about contents (what I think === means now). Expectation based on the use of : to indicate declaratory behavior Just two cents from a Perl6 newbie. -- Regards, Charles Bailey Lists: bailey _dot_ charles _at_ gmail _dot_ com Other: bailey _at_ newman _dot_ upenn _dot_ edu
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On Thu, Jul 13, 2006 at 10:19:24PM -0600, David Green wrote: : On 7/13/06, Yuval Kogman wrote: : So, Larry assisted by Audrey explained the purpose of === vs eqv vs =:=. : It makes sense now, but I still feel that as far as ergonomics go : this is not perfect. : : I think I understand it... (my only quibble with the syntax is that : === and eqv look like spin-offs of == and eq, but I don't know what : to suggest instead (we're running short of combinations of = and : !)) That's partly because they *are* spinoffs, on a metaphorical level. The === operator is a mathematically equal, where that implies equality henceforth and forevermore. There is also a bit of the notion that, since a number is a singular thing, you can't treat any of the bits of a number as mutable. There's no lvalue substr() defined on a number, as it were. The eqv operator, on the other hand, is a you have to work at figuring this out by serializing both values conceptually to canonical strings (think Storable) and see if those are eq. (Only you don't really go to all that work, if you can short circuit any of it.) There is also the notion (though this breaks down if you look at it too hard) that a string can be modified in place, so a string value is mutable (at least from the standpoint of the variable holding it; from the standpoint of ===, string values are immutable, which is where the analogy breaks down). : So there are three basic kinds of comparison: whether the variables : are the same (different names, but naming the same thing); whether : the values are the same (deep comparison, i.e. recursively all the : way down in the case of nested containers); and in-between (shallow : comparison, i.e. we compare the top-level values, but we don't work : out *their* values too, etc., the way a deep comparison would). If : I've got it right, this is what =:=, eqv, and === give us, : respectively. No, === is also deep. It's only shallower (or potentially shallower) in the sense that it treats any mutable object node as a leaf node rather than changing to snapshot semantics like eqv does. : (When I say value I'm thinking of everything that makes up the : value, such as type (so the number 3 is different from the string : 3), or details like the encoding for a string, etc.) Arguably the encoding of a string has nothing to do with its value most of the time, if the semantics are supposed to be consistent Unicode semantics at the codepoint or grapheme level. But yes, by and large types do have to be included. Bool::True is a different value from 1, even though they are often interchangable in many contexts. : Examples: : : @x=foo bar; : @y=foo bar; : : $a=[1, 2, [EMAIL PROTECTED]; : $b:=$a; : $c=[1, 2, [EMAIL PROTECTED]; : $d=[1, 2, [EMAIL PROTECTED]; : : : $a =:= $b; #true, same variable with two names : $a === $b; #true _/ $b just another name for $a, : $a eqv $b; #true\ so comparable at all levels : : $a =:= $c; #false, different variables : $a === $c; #true, same elements make up $a and $c : $a eqv $c; #true, same elements therefore same values : : $a =:= $d; #false, different variables : $a === $d; #false, [EMAIL PROTECTED] and [EMAIL PROTECTED] are different refs : $a eqv $d; #true, values of @x and @y happen to be the same All correct. : (Of course, @x eqv @y, @[EMAIL PROTECTED], but not @x=:[EMAIL PROTECTED]) : Note that if $i=:=$j, then $i===$j; and of course if $i===$j, then $i eqv : $j. Those are necessarily true, assuming nobody else is meddling with our data structures in the middle of our comparison. If someone is modifying some mutable component in $i or $j while we're taking a snapshot, then we can get into inconsistent states where eqv can return false despite === being true. : OK, looking at S03 again, that still isn't correct. I think my =:= : and eqv are all right, but I don't understand exactly what === is : supposed to do, or why it's useful. And how do I do my : shallow-comparison above? S03 hasn't been updated to reflect all this yet. === semantics are useful for figuring out whether you have a unique key for a hash when you want to hash on live objects. eqv is for dead keys, because as soon as you've taken a snapshot of your data, you can't modify the snapshot or dereference any object in your hash key. eqv semantics are what Perl 5 hashes use for keys, which is why you can't deref a hash key directly even if you thought you were putting an object in as the key. : (One [1,2] is as good as any other [1,2] -- what's the use of ever : having them not compared as the same? I can see maybe for =:=, since : something that doesn't have a name cannot, by definition, have the : same name as something else... although even there, it arguably makes : sense to consider equivalent anonymous values as bound to the same : place. There's only one unique [1,2] in
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
So, Larry assisted by Audrey explained the purpose of === vs eqv vs =:=. It makes sense now, but I still feel that as far as ergonomics go this is not perfect. Then again, I trust that Larry's opinion is probably better and at the very least more likely to be accepted than mine ;-) [1] So, this is the deal: === is for checking immutable equality. This is a bit nasty to explain. eqv is going to be deep comparison, like most of us thought '===' was going to be (I had initially thought that eqv was renamed to === when === started popping up). =:= is something completely different, but will be easy to explain in a moment. What it means for something to be immutable can be demonstrated rather easily here: my $x = 10; my $y = $x; $x === $y; # true $y++: $x === $y; # false Since numbers (and also strings) are simple values, that are not modified in place (at least not explicitly), but are instead copied and modified or just replaced when you change them, the .id of the thing inside $x and $y is bound to the value. You could rationalize this such that .id is the same if and only if it doesn't actually matter (and never will matter) if the value is in the same chunk of memory or a separate one, as far as the runtime is concerned. Arrays and hashes, and other complex types can, on the other hand have parts of them transformed without first cloning everything (which is precisely why they're useful). The underlying idea is that === can be used to test if two values are *always* going to be the same (if they're container gets a different value in it that does not mean that they are no longer the same). eqv, on the other hand is used to test whether or not two values are the same right now, without making any implications as to what their values will be later on, since they may mutate. This is deceivingly like == and eq if you assume that numbers and strings are changed, instead of replaced. Lastly, =:= is really variable($x) === variable($y) - that is, whether or not the container is the same value or not. This basically checks whether either $x or $y was at some point bound to the other, or in specific situations whether they're tied to the same representation even if they are different containers. Overridding .id is useful for when you want to imply that two items are exactly the same and will always be the same and will never change as far as their comparison is concerned (both eqv and === will always be true), even if the default implementation of === does not return true due to technical details. === can be thought of as .id eqv .id. I hope this clears things up, and thanks again, Larry and Audrey, for clearing this up. I'd like for someone with better english skills to summarize into an S03 patch please. It needs to be much shorter =) [1] My preferred ergonomics: 1. eqv goes away 2. what was eqv is renamed to === 3. === becomes =:=, which has a constant feel to it 4. =:= is rarely useful IMHO, so you can just type variable($x) =:= variable($y) Ciao -- Yuval Kogman [EMAIL PROTECTED] http://nothingmuch.woobling.org 0xEBD27418 pgpU0Qe5CPlhQ.pgp Description: PGP signature
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On Thu, Jul 13, 2006 at 09:32:08PM +0300, Yuval Kogman wrote: : [1] My preferred ergonomics: : : 1. eqv goes away : 2. what was eqv is renamed to === : 3. === becomes =:=, which has a constant feel to it : 4. =:= is rarely useful IMHO, so you can just type : variable($x) =:= variable($y) It is important for eqv to be alphabetic so we can have the functional form take an optional signature parameter to specify what is compared. eqv($a,$b, :($x,$y)) Think of this as the same as the sort specifier that says what to sort on, only we're only interested in eqv-ness rather than cmp-ness. In fact, cmp (or something like it) also wants to take a third parameter: leg($a,$b, :($x is num,$y is rev)); and then sort is just done with the same signature: sort :($x is num,$y is rev), @foo; or some such, however you want to canonicalize the records. The sort routine can decide whether it'll be more efficient to do various transforms or maneuvers based on the declarative syntax of the signature. Then $a eqv $b and $a leg $b both just default to a signature that selects everything. Larry
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On Thu, Jul 13, 2006 at 12:50:19PM -0700, Larry Wall wrote: : Then $a eqv $b and $a leg $b both just default to a signature that selects : everything. Though arguably P5's string-forcing semantics should be Cleg and the polymorphic semantics should probably be Ccmp. Larry
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On 7/13/06, Yuval Kogman wrote: So, Larry assisted by Audrey explained the purpose of === vs eqv vs =:=. It makes sense now, but I still feel that as far as ergonomics go this is not perfect. I think I understand it... (my only quibble with the syntax is that === and eqv look like spin-offs of == and eq, but I don't know what to suggest instead (we're running short of combinations of = and : !)) So there are three basic kinds of comparison: whether the variables are the same (different names, but naming the same thing); whether the values are the same (deep comparison, i.e. recursively all the way down in the case of nested containers); and in-between (shallow comparison, i.e. we compare the top-level values, but we don't work out *their* values too, etc., the way a deep comparison would). If I've got it right, this is what =:=, eqv, and === give us, respectively. (When I say value I'm thinking of everything that makes up the value, such as type (so the number 3 is different from the string 3), or details like the encoding for a string, etc.) Examples: @x=foo bar; @y=foo bar; $a=[1, 2, [EMAIL PROTECTED]; $b:=$a; $c=[1, 2, [EMAIL PROTECTED]; $d=[1, 2, [EMAIL PROTECTED]; $a =:= $b; #true, same variable with two names $a === $b; #true _/ $b just another name for $a, $a eqv $b; #true\ so comparable at all levels $a =:= $c; #false, different variables $a === $c; #true, same elements make up $a and $c $a eqv $c; #true, same elements therefore same values $a =:= $d; #false, different variables $a === $d; #false, [EMAIL PROTECTED] and [EMAIL PROTECTED] are different refs $a eqv $d; #true, values of @x and @y happen to be the same (Of course, @x eqv @y, @[EMAIL PROTECTED], but not @x=:[EMAIL PROTECTED]) Note that if $i=:=$j, then $i===$j; and of course if $i===$j, then $i eqv $j. OK, looking at S03 again, that still isn't correct. I think my =:= and eqv are all right, but I don't understand exactly what === is supposed to do, or why it's useful. And how do I do my shallow-comparison above? (One [1,2] is as good as any other [1,2] -- what's the use of ever having them not compared as the same? I can see maybe for =:=, since something that doesn't have a name cannot, by definition, have the same name as something else... although even there, it arguably makes sense to consider equivalent anonymous values as bound to the same place. There's only one unique [1,2] in platonic heaven, I'm just mentioning it directly instead of dropping a name.) -David
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
David Green wrote: I think I understand it... (my only quibble with the syntax is that === and eqv look like spin-offs of == and eq, but I don't know what to suggest instead (we're running short of combinations of = and : !)) Agreed. So there are three basic kinds of comparison: whether the variables are the same (different names, but naming the same thing); whether the values are the same (deep comparison, i.e. recursively all the way down in the case of nested containers); and in-between (shallow comparison, i.e. we compare the top-level values, but we don't work out *their* values too, etc., the way a deep comparison would). If I've got it right, this is what =:=, eqv, and === give us, respectively. Apparently, there are _four_ basic kinds of comparison: the ones mentioned above, and == (I believe that eq works enough like == that whatever can be said about one in relation to ===, =:=, or eqv can be said about the other). I'd be quite interested in an expansion of David's example to demonstrate how == differs from the others. -- Jonathan Dataweaver Lang
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On Thu, Jul 13, 2006 at 12:50:19 -0700, Larry Wall wrote: On Thu, Jul 13, 2006 at 09:32:08PM +0300, Yuval Kogman wrote: : [1] My preferred ergonomics: : : 1. eqv goes away : 2. what was eqv is renamed to === : 3. === becomes =:=, which has a constant feel to it : 4. =:= is rarely useful IMHO, so you can just type : variable($x) =:= variable($y) It is important for eqv to be alphabetic so we can have the functional form take an optional signature parameter to specify what is compared. There's no contradiction, === could be an alias to eqv ;-) -- Yuval Kogman [EMAIL PROTECTED] http://nothingmuch.woobling.org 0xEBD27418 pgpPDRBxXCeip.pgp Description: PGP signature
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
On Thu, Jul 13, 2006 at 21:55:15 -0700, Jonathan Lang wrote: Apparently, there are _four_ basic kinds of comparison: the ones mentioned above, and == (I believe that eq works enough like == that whatever can be said about one in relation to ===, =:=, or eqv can be said about the other). I'd be quite interested in an expansion of David's example to demonstrate how == differs from the others. sub infix:== ( Any $x, Any $y ) { +$x === +$y; # propagate coercion failure warnings to caller } sub infix:eq ( Any $x, Any $y ) { ~$x === ~$y } -- Yuval Kogman [EMAIL PROTECTED] http://nothingmuch.woobling.org 0xEBD27418 pgp3B4GnByYFK.pgp Description: PGP signature
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
Yuval Kogman wrote: Jonathan Lang wrote: Apparently, there are _four_ basic kinds of comparison: the ones mentioned above, and == (I believe that eq works enough like == that whatever can be said about one in relation to ===, =:=, or eqv can be said about the other). I'd be quite interested in an expansion of David's example to demonstrate how == differs from the others. sub infix:== ( Any $x, Any $y ) { +$x === +$y; # propagate coercion failure warnings to caller } sub infix:eq ( Any $x, Any $y ) { ~$x === ~$y } So the purpose of === is to provide a means of comparison that doesn't implicitly coerce its arguments to a particular type? -- Jonathan Dataweaver Lang
Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained
At 10:36 PM -0700 7/13/06, Jonathan Lang wrote: So the purpose of === is to provide a means of comparison that doesn't implicitly coerce its arguments to a particular type? Yes, absolutely. The === takes 2 arguments exactly as they are, without changing anything, and says if they are two appearances of the same value. It would always return false if the 2 arguments are of different declared types. And if they are of the same types, then no coersion is necessary in order to compare them for equality. Now, I didn't see them yet anywhere in Synopsis 3, but I strongly recommend having negated versions of all these various types of equality tests. Eg, !== for ===, nev for eqv, etc. They would be used very frequently, I believe (and I have even tried to do so), and of course we get the nice parity. -- Darren Duncan