Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained

2006-07-14 Thread Darren Duncan
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


optimizing with === immutable comparitor

2006-07-14 Thread Darren Duncan

This may go without saying, but ...

If $a === $b means what I think it does, then I believe that a 
not-premature implementation optimization of === would be that it 
always $a := $b if it was returning true, so that any future === of 
$a and $b or aliases thereof could short-circuit with a =:= test even 
if they weren't created as aliases, and Perl would be automatically 
more memory efficient without those extra storage copies.


I know that was an implementation issue, but I think that it stands 
to be explicitly stated anyway, as it is a very simple and effective 
way to make Perl programs more resource efficient, possibly by orders 
of magnitude, over not doing so.


(The only time this may not work is if so-called immutable types are 
tied to external resourses, but then I'm not sure how often this 
would happen in practice so it could just be an exception if 
necessary.  The above-stated rule would still stand for any resources 
managed by Perl itself.)


-- Darren Duncan


Re: optimizing with === immutable comparitor

2006-07-14 Thread chromatic
On Friday 14 July 2006 00:30, Darren Duncan wrote:

 This may go without saying, but ...

 If $a === $b means what I think it does, then I believe that a
 not-premature implementation optimization of === would be that it
 always $a := $b if it was returning true, so that any future === of
 $a and $b or aliases thereof could short-circuit with a =:= test even
 if they weren't created as aliases, and Perl would be automatically
 more memory efficient without those extra storage copies.

 I know that was an implementation issue, but I think that it stands
 to be explicitly stated anyway, as it is a very simple and effective
 way to make Perl programs more resource efficient, possibly by orders
 of magnitude, over not doing so.

First there was copy-on-write and now there's share-on-compare?

 (The only time this may not work is if so-called immutable types are
 tied to external resourses, but then I'm not sure how often this
 would happen in practice so it could just be an exception if
 necessary.  The above-stated rule would still stand for any resources
 managed by Perl itself.)

In the absence of much Perl 6 code either way, I wonder at the value of adding 
such an extreme side effect to a simple comparison operation.  This goes way 
beyond loop hoisting and constant folding.

I can understand singleton value types (even Perl 5 does that with PL_undef), 
but ... wow, you have a lot more faith in local code analysis than I do.

-- c


CORRECTION: optimizing with === immutable comparitor

2006-07-14 Thread Darren Duncan

At 12:30 AM -0700 7/14/06, Darren Duncan wrote:
If $a === $b means what I think it does, then I believe that a 
not-premature implementation optimization of === would be that it 
always $a := $b if it was returning true, so that any future === of 
$a and $b or aliases thereof could short-circuit with a =:= test 
even if they weren't created as aliases, and Perl would be 
automatically more memory efficient without those extra storage 
copies.


Sorry, I stated some things badly in that previous email, mainly the 
$a := $b part, which is technically incorrect, so I will try and 
clarify what I meant to say.


What I propose concerning non-premature === optimizing is a system 
where, at any time that two appearances of the same immutable value 
are compared with ===, they are immediately consolidated into a 
single appearance.  Or at least $a.value := $b.value occurs 
immediately, and garbage collection of the second and now 
unreferenced copy happens whenever it would happen.


For illustration:

 $a = 'hello'; # one copy of the value 'hello' in memory
 $b = 'hello'; # a second copy of the value 'hello' elsewhere in memory
 $c = 'world'; # one copy of 'world' in memory
 $a === $b; # now only one copy of 'hello' is in memory, $a and $b point to
 $a === $c; # nothing changes, as values are different
 $b = $c; # now only $a points to 'hello', $b and $c point to one 'world'

I of course did not mean for the actual symbol $a := $b to happen, 
only what they point to internally.


Of course, the above example could be constant folded to one copy of 
'hello' at compile time, but my illustration is meant to be for 
situations where $a and $b are declared or set far apart, possibly 
from run-time input values, so the folding happens at run time.


What I meant with the =:= shortcut then, is that $a.value =:= 
$b.value could return true following the above run of $a === $b.


Sorry for any confusion.

FYI, I plan to explicitly illustrate the principle in my next 
Set::Relation update, since its types are immutable, so that any 
operations which involve comparing two relations or tuples or 
headings or values therein with === will have a side-effect of 
consolidating them if they are equal.  Later on, if this happens at 
the language level, I would less likely have to do it myself.


-- Darren Duncan


Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained

2006-07-14 Thread Smylers
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: CORRECTION: optimizing with === immutable comparitor

2006-07-14 Thread Ruud H.G. van Tol
Darren Duncan schreef:

 What I propose concerning non-premature === optimizing is a system
 where, at any time that two appearances of the same immutable value
 are compared with ===, they are immediately consolidated into a
 single appearance.

That should only be done voluntarily. A bit like memoization.

Something else: An immutable composite value can have unfinalized parts.
Finalizing them for the sake of a deep comparison, can hurt performance.
Does a lazy system need something like 'undecided' or 'NaB'
(not-a-boolean)?

-- 
Groet, Ruud



Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained

2006-07-14 Thread Yuval Kogman
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: optimizing with === immutable comparitor

2006-07-14 Thread Yuval Kogman
On Fri, Jul 14, 2006 at 00:30:20 -0700, Darren Duncan wrote:
 This may go without saying, but ...

...

This is a VM issue. It clarifies semantics, and the runtime VM may
choose to do this freely for simple values (but not for objects
which just pretend using .id).

In short: yes, the semantics allow that, but it has nothing to do
with the language it might not even be faster.

-- 
  Yuval Kogman [EMAIL PROTECTED]
http://nothingmuch.woobling.org  0xEBD27418



pgp2roLoyDefj.pgp
Description: PGP signature


Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained

2006-07-14 Thread Smylers
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: Run time dispatch on ~~

2006-07-14 Thread Aaron Sherman
On Fri, 2006-07-14 at 00:08 +0300, Yuval Kogman wrote:

 Also, sometimes i am matching on behalf of my caller, this is very
 common in dispatch algorithms, or things like tree visitors:
 
   my @list = $tree.filter_children( $match ); # very generic and useful

It's really the fact that that's a method that hoses everything. There's
essentially no way to compile-time dispatch that, so even macros won't
help you grr.

No, you've got me. There needs to be a way to do that, but oh dear it's
going to be confusing, and as ever, I worry about those who will use
this sort of thing poorly or mistakenly, and then rant on about how Perl
is write-only.

Perhaps the solution is not code, but documentation. Perhaps if we make
a clean break between comparison and matching in the docs, and push
people away from non-regex/string-~~ until they understand its
implications, we can head off much of the lossage.

For example (modified S03 Smart matching section without the table):

=head1 Smart matching

Smart matching is the process of asking, does thing Ia conform to the
specification of Ib? The most common reason to want to do this is to
match a string against a regex:

 if $s ~~ /^\d+$/ { ... }

But smart matching is also performed by given/when for switch-like behavior:

 given $s {
   when 'Apple' { ... }
   when 'Pear'  { ... }
   default  { die No fruit! }
 }

Notice that the specification can also be a string, as above, but because
Ceqv and C~~ mean the same thing in this context, it is clearer, when
writing a single expression to explicitly use Ceqv:

 if $a eqv $b { ... }

The right-hand side of C~~ (the specification) always controls the
nature of the matching, so care must be taken when matching. Do not
think of this as simple comparison where the arguments are considered
peers.

Here is the current table of smart matches with respect to $_ and $x
as they would be used here:

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

or

 $_ ~~ $x

The list is intended to reflect forms that can be recognized at
compile time.  If none of these forms is recognized at compile time, it
falls through to do MMD to C infix:~~() , which presumably
reflects similar semantics, but can finesse things that aren't exact
type matches.  Note that all types are scalarized here.  Both C~~
and Cgiven/Cwhen provide scalar contexts to their arguments.
(You can always hyperize C~~ explicitly, though.)

Both C$_ (the value) and C$x (the match specification) here are
potentially references to container objects.
And since lists promote to arrays in scalar context, there need be no
separate entries for lists.

(table goes here)

-- 
Aaron Sherman [EMAIL PROTECTED]
Senior Systems Engineer and Toolsmith
We had some good machines, but they don't work no more. -Shriekback




Re: Run time dispatch on ~~

2006-07-14 Thread Dr.Ruud
Aaron Sherman schreef:

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

 or

  $_ ~~ $x

Can that be written as .~~ $x?

-- 
Affijn, Ruud

Gewoon is een tijger.




Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained

2006-07-14 Thread Mark A. Biggar

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

2006-07-14 Thread Dave Whipp

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: Run time dispatch on ~~

2006-07-14 Thread Larry Wall
On Fri, Jul 14, 2006 at 04:34:26PM +0200, Dr.Ruud wrote:
: Aaron Sherman schreef:
: 
:   given $_ {
: when $x {...}
:   }
: 
:  or
: 
:   $_ ~~ $x
: 
: Can that be written as .~~ $x?

No, but you might just possibly get away with writing:

.infix:~~($x)

assuming that the $_.foo($x) SMD eventually fails over to foo($_,$x) MMD.
But that doesn't seem to be much of an improvement over when $x.

Larry


Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained

2006-07-14 Thread Dr.Ruud
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

2006-07-14 Thread Darren Duncan

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


Fwd: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained

2006-07-14 Thread Jonathan Lang

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?

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.


IIRC, this is because the implicit coercion to number or string gets
in the way.

IMHO, @a == @b ought to be synonymous with all (@a »==« @b) - it's
far more likely to DWIM.  Likewise with @a eq @b and all (@a »eq«
@b).  If what you want to do is to compare the lengths of two lists,
you ought to do so explicitly: [EMAIL PROTECTED] == [EMAIL PROTECTED].

Getting back to the notion of immutability: can someone give me an
example of a realistic immutable analog to a list, and then give an
example demonstrating the practical distinction between === and eqv
based on that?  I want to see why it's important to distinguish
between comparing mutable data types and comparing immutable data
types.

(Incidently, I think that a suitable word-based synonym for =:= would be is.)

--
Jonathan Dataweaver Lang


Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained

2006-07-14 Thread Darren Duncan

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

2006-07-14 Thread Larry Wall
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: Run time dispatch on ~~

2006-07-14 Thread Dr.Ruud
Larry Wall schreef:
 Dr.Ruud:
 Aaron Sherman:

  $_ ~~ $x

 Can that be written as .~~ $x?

 No, but you might just possibly get away with writing:

 .infix:~~($x)

 assuming that the $_.foo($x) SMD eventually fails over to foo($_,$x)
 MMD. But that doesn't seem to be much of an improvement over when
 $x.

OK, thanks. Is it ever useful for an SMD to fail over to MMD?

-- 
Affijn, Ruud

Gewoon is een tijger.




Re: ===, =:=, ~~, eq and == revisited (blame ajs!) -- Explained

2006-07-14 Thread Darren Duncan

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

2006-07-14 Thread Yuval Kogman
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

2006-07-14 Thread Dr.Ruud
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

2006-07-14 Thread Charles Bailey

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

2006-07-14 Thread Larry Wall
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 

[svn:perl6-synopsis] r10215 - doc/trunk/design/syn

2006-07-14 Thread larry
Author: larry
Date: Fri Jul 14 17:00:12 2006
New Revision: 10215

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

Log:
Differentiate === from eqv and clarify semantics.
Redefine cmp and add leg operator for old semantics.
Add ! metaoperator.
Fix random typos.


Modified: doc/trunk/design/syn/S03.pod
==
--- doc/trunk/design/syn/S03.pod(original)
+++ doc/trunk/design/syn/S03.podFri Jul 14 17:00:12 2006
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall [EMAIL PROTECTED]
   Date: 8 Mar 2004
-  Last Modified: 12 Jul 2006
+  Last Modified: 14 Jul 2006
   Number: 3
-  Version: 46
+  Version: 47
 
 =head1 Changes to existing operators
 
@@ -158,7 +158,7 @@
 
 Operators that imply list operations are excluded: prefix C@,
 prefix C% and infix Cxx, for instance.  Hyper operators are
-also excluded, but post-assigment forms such as CSIMPLE += SIMPLE
+also excluded, but post-assignment forms such as CSIMPLE += SIMPLE
 are allowed.
 
 All other forms imply parsing as a list assignment, which may or may not
@@ -317,22 +317,24 @@
 side for definedness instead of truth. There is a low-precedence form,
 too: Cerr.
 
-=item * Binary C=== tests type and value correspondence: for two value types,
-tests whether they are the same value (eg. C1 === 1); for two reference
-types, checks whether they have the same identity value.  For reference
-types that do not define an identity, the reference itself is used (eg. it
-is not true that C[1,2] === [1,2], but it is true that C@a === @a).
-
-Any reference type may pretend to be a value type by defining a C.id method
-which returns a built-in value, i.e. an immutable object or a native value,
-as specified in S06.
-
-Because Perl 6 uses a false C.id to signify a non-instantiated prototype,
-all instances should arrange to return a C.id that boolifies to true.
-
-A class may also overload C infix:===  for more efficient comparison of
-any two objects of that type, but it must return the same result as if
-the two identity values had been generated and compared.
+=item * Binary C=== tests immutable type and value correspondence:
+for two value types (that is, immutable types), tests whether
+they are the same value (eg. C1 === 1); for two mutable types
+(object types), checks whether they have the same identity value.
+(For most such types the identity is simply the reference itself.)
+It is not true that C[1,2] === [1,2] because those are different
+Array objects, but it is true that C@a === @a because those are
+the same Array object).
+
+Any object type may pretend to be a value type by defining a C.id
+method which returns a value type that can be recursively compared
+using C===, or in cases where that is impractical, by overloading
+C=== such that the comparison treats values consistently with their
+eternal identity.  (Strings are defined as values this way despite
+also being objects.)
+
+(Because Perl 6 uses a false C.id to signify a non-instantiated prototype,
+all instances should arrange to return a C.id that boolifies to true.)
 
 Two values are never equivalent unless they are of exactly the same type.  By
 contrast, Ceq always coerces to string, while C== always coerces to
@@ -342,7 +344,44 @@
 Note also that, while string hashes use Ceq semantics by default,
 object hashes use C=== semantics.
 
-=item * Binary C =  is no longer just a fancy comma.  It now
+=item * Binary Ceqv tests equality much like C=== does, but does
+so with snapshot semantics rather than eternal semantics.  For
+top-level components of your value that are of immutable types, Ceqv
+is identical in behavior to C===.  For components of your value
+that are mutable, however, rather than comparing object identity using
+C===, the Ceqv operator tests whether the canonical representation
+of both subvalues would be identical if we took a snapshot of them
+right now and compared those (now-immutable) snapshots using C===.
+
+If that's not enough flexibility, there is also an Ceqv() function
+that can be passed additional information specifying how you want
+canonical values to be generated before comparison.  This gives
+Ceqv() the same kind of expressive power as a sort signature.
+(And indeed, the Ccmp operator from Perl 5 also has a functional
+analog, Ccmp(), that takes additional instructions on how to
+do 3-way comparisons of the kind that a sorting algorithm wants.)
+In particular, a signature passed to Ceqv() will be bound to the
+two operands in question, and then the comparison will proceed
+on the formal parameters according to the information contained
+in the signature, so you can force numeric, string, natural, or
+other comparisons with proper declarations of the parameter's type
+and traits.  If the signature doesn't match the operands, Ceqv()
+reverts to standard Ceqv comparison.  (Likewise for Ccmp().)
+
+=item * Binary Ccmp is no longer the comparison operator that
+forces stringification.  Use the Cleg 

Re: [svn:perl6-synopsis] r10215 - doc/trunk/design/syn

2006-07-14 Thread Darren Duncan

At 5:00 PM -0700 7/14/06, [EMAIL PROTECTED] wrote:

Author: larry
Date: Fri Jul 14 17:00:12 2006
New Revision: 10215

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

Log:
Differentiate === from eqv and clarify semantics.
Redefine cmp and add leg operator for old semantics.
Add ! metaoperator.
Fix random typos.


Larry, this new version looks great.

A few small omissions or clarifications though ...


+=item * Binary Ccmp is no longer the comparison operator that
+forces stringification.  Use the Cleg operator for the old Perl 5
+Ccmp semantics.  The Ccmp is just like the Ceqv above except that
+instead of returning CBool::False or CBool::True values it always
+returns COrder::Increase, COrder::Same, or COrder::Decrease
+(which numerify to -1, 0, or +1).
+
+=item * the Cleg operator (less than, equal, or greater) is defined
+in terms of Ccmp, so C$a leg $b is now defined as C~$a cmp ~$b.
+The sort operator still defaults to Ccmp rather than Cleg.  The
+C =  operator's semantics are unchanged except that it returns
+and Order value as described above.


1. I suggest for parity (vs leg as exists eq vs ==) and clarity that 
you explicitly state the = semantics like you did for leg, rather 
than just saying it was unchanged.  Eg, amend the last sentence 
there to say specifically that C$a = $b is now defined as C+$a 
cmp +$b, especially since you don't explicitly say this anywhere 
else in Synopsis 3.



+[Conjecture: we could probably do away with C!~, but probably not
+C!= or Cne.]


2. I support eliminating !~ in favor of just !~~.

Unlike != or 'ne', which are each part of a set of 6 operators that 
remained unchanged as a whole from Perl 5 (so backwards compatability 
could be useful), the binding/smartmatch operator set that !~ belongs 
to was greatly changed, so there is no benefit to keeping !~ just 
because that syntax was in Perl 5.


3. The Precedence table at the end of Synopsis 3 currently does not 
reflect your latest changes.  Most importantly, it is missing 'eqv' 
and 'leg'.


Also importantly, it is missing the ?| operator and friends, which in 
my case leads to confusion as to whether it belongs with the tight-or 
set or the bitwise operator set.


Less importantly, I would consider the main versions of the negated 
eqality operators !==, !eq, !~~ to be more important than the 
alternate != or ne forms; as it is, that table already just lists the 
more canonical versions of things like the zip operator rather than 
both or the alternate versions.


4. I'm confused regarding the ?| operator, which is only mentioned in 
this paragraph near the top of Synopsis 3:


=item * Bitwise operators get a data type prefix: C+, C~, or C?.
For example, C| becomes either C+| or C~| or C?|, depending on
whether the operands are to be treated as numbers, strings, or boolean
values.  Left shift C   becomes C + , and correspondingly with
right shift. Unary C~ becomes either C+^ or C~^ or C?^, since a
bitwise NOT is like an exclusive-or against solid ones.  Note that C?^
is functionally identical to C!.  C?| differs from C|| in that
C?| always returns a standard boolean value (either 1 or 0), whereas
C|| return the actual value of the first of its arguments that is
true.

First of all, this paragraph seems to confuse in my mind as to 
whether or not ?| is a bitwise operator.  On one hand, it says that 
it takes 2 boolean values as input and or's them.  On the other hand, 
it says that it is just like ||, which takes any kind of values as 
input, but that the latter returns the first actual value of the 
first 2 arguments, while the former doesn't.  The || comparison 
suggests that maybe ?| belongs with the tight-or operator set rather 
than bitwise.  It might help if some of this was clarified.  Part of 
the confusion though is that ?| isn't in the operator precedence 
table.


-- Darren Duncan