Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-30 Thread TSa

HaloO,

John M. Dlugosz wrote:

TSa Thomas.Sandlass-at-barco.com |Perl 6| wrote:


   multi infix:<=> (Any $lhs, A $rhs)
   {
   $lhs.STORE($rhs.clone); # or .cow if that's not automatic
   }



  $lhs.VAR.STORE.


I guess I also forgot the is rw to get a binding to the caller's
container not the local one of the sub. Otherwise you could write
into the caller's container without rw in the sig.

The issue I want to address is how easy it is to implement
immutable semantics. The ref copying is sort of an annoyance
there.

   class A
   {
   has $.a = 0;
   submethod BUILD ($.a) {}
   method inc ($self is rw:) # get at the container of
   { # of the caller
   $self = self.^new(self.a + 1);
   # return self.^new(self.a + 1) without the rw
   # sadly doesn't work for $x.inc syntax
   }
   }

   my A $a .= new(7);
   my A $b = $a;

   $a === $b; # true
   $a eqv $b; # true

   $a.inc; # shall behave like ++ for Int

   $a === $b; # false
   $a eqv $b; # false

The spec also says that one has to use .=method to call an in-place
mutator. That is $x.inc in Daniel's example should actually mean
$x = $x.inc along the lines that $x++ also means $x = $x + 1.

Finally combine that with the wish to allow literals of class A. Let's
assume the grammar is patched to parse integer literals as As. Then
with the above 7.inc gives an error because 7 is not mutable. So as
I outlined before I want to care for the callers constraint. Perl 6
lacks a syntax for that.


My readings have been that = just copies the ref.  Unless it's a "value 
type" or "immutable" which just means that it doesn't matter.  I'll have 
to read up on that some more soon.


Keep us informed, please.


Regards, TSa.
--

"The unavoidable price of reliability is simplicity"  -- C.A.R. Hoare
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-30 Thread TSa

HaloO,

Daniel Ruoso wrote:

[ I'm using this message to reply, because I didn't receive your
reply... I'm taking it from the list history... There really seems to be
something wrong with this list... ]


I see all your messages arrive twice.



This is not specced apparently to leave room for decision in the
implementation. But there's an important question to be answered before
that...

what is the type returned by WHICH?


Isn't that up to the implementation as well? E.g. on a 32bit platform
use an unsigned 32bit integer. The only things that should not happen
is that you let it leak onto the value level or that WHICHes of
differently typed objects are compared.

With leaking to the value level I mean allowing $x.WHICH == 42 even
if it is known that WHICH is implemented with a number.



But it's important to keep in mind that eqv behaviour might also be
overriden by the object, that might give a canonical representation that
matches the other object.


Ups, no object can override eqv or any other binary method. These
live outside of HOW space. You can insert your dispatch targets
but that's about it.



On the other hand, a 'realises' trait could change the object in order
that it would still match with both 'eqv' and '===', while still '~~' to
an additional type.

This would be done simply by creating an anonymous class that isa the
original class while overriding .^does, WHICH and eqv to shadow to the
original class, and then re-blessing the object to this anonymous class.


I don't understand your motivation, but I think it is the obsession with
object identity. You say that the object changes class, i.e. its HOW or
WHAT changes while perhaps keeping its WHICH. But eqv, === and ~~ are
defined outside of the class or object system. There is an inheritance
order on HOW space and a subtyping order on WHAT space. Class based
dispatch goes along the former, type based dispatch along the latter.
The object that changes class should not be eqv or === to itself before
the transition or nominal typing becomes absurd.


Regards, TSa.
--

"The unavoidable price of reliability is simplicity"  -- C.A.R. Hoare
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread Daniel Ruoso
Ter, 2008-04-29 às 14:21 +0200, TSa escreveu:
> Daniel Ruoso wrote:
> > Not really... 'does' is a composition operation, 'realises' would be
> > just a type annotation that doesn't change the actual composition.
> OK, but that is not in the spec yet. To me that is like the
> proposed 'like' operator but with the programmer taking full
> responsibility. Like reinterpret_cast in C++.

It doesn't need to be. New traits can be implemented later.

> First of all assignment has copy semantics. That is after $y = $fp,
> $y =:= $fp is false. I agree that

It will copy the scalar, which means that later change in the value cell
won't propagate to the other variable. But both cells point to the same
value.

 $a = $b;
 $a === $b; # TRUE
 $a =:= $b; # FALSE
 $b = $c;
 $a === $b; # FALSE

As opposed to

 $a := $b;
 $a === $b; # TRUE
 $a =:= $b; # TRUE
 $b = $c;
 $a === $b; # TRUE

In the later, the scalar itself is copied, which means that both
variables *are* the same scalar, and changing the cell value in one is
the same as changing the cell value in the other.

So...

 class A { has $.a; method inc { $.a++ } };
 $a = A.new( a => 0);
 $b = $a;
 $b.inc();
 $a.inc();
 say $a.a; # 2
 say $b.a; # 2

Will work as expected.

> But either the HOW, the WHAT or both of $fp have to change

That is true

> which implies that $y === $fp can't remain true after
> $fp does Point

Not really... see below...

> BTW, an interesting question is if a typed
> binding could become invalid:
>subset AntiPoint of Any where {not .^does(Point)}
>my AntiPoint $ap := $fp; # fine for now
>$fp does Point; # now $ap is bound to a Point which
># violates the AntiPoint constraint

This is a composition error that generates an exception. It even
provides enough information for a compile-time error.

> > It doesn't. By definition. === only checks WHICH.
> Then we must read different versions of S03. Mine has the
> sentence "Two values are never equivalent unless they are
> of exactly the same type."

*Value types*!!! Which is not the case here, we are talking about
*Object types*, also in S03:

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

Which means that (continuing the code starting with "class A")...

   $a = A.new(a => 0);
   $b = $a;
   $a === $b; # TRUE
   $b.inc;
   $a === $b; # TRUE

daniel



Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread Daniel Ruoso
[ I'm using this message to reply, because I didn't receive your
reply... I'm taking it from the list history... There really seems to be
something wrong with this list... ]

TSa wrote:
> BTW, is WHICH globally unique? Or is that also an
> implementation detail?

This is not specced apparently to leave room for decision in the
implementation. But there's an important question to be answered before
that...

what is the type returned by WHICH?

I haven't implemented that in SMOP yet (because I have the constant
identifiers that allow me to make simple pointer comparison), but I
think in the low-level it will end-up being something like a native
binary blob.

Which means that every non-native type will, in the end, have to be
reduced to native types in the WHICH call to provide a proper value for
comparison.

TSa wrote:
> So, even though the WHICH stays the eqv check has to change:
> $a = A.new( a => 0); # your class A
> $b = A.new( a => 0);
> $a === $b; # False, but
> $a eqv $b; # True because of snapshot semantic
> $b does Point;
> $a eqv $b; # False because HOW or WHAT is different

But it's important to keep in mind that eqv behaviour might also be
overriden by the object, that might give a canonical representation that
matches the other object.

An implementation of the 'realises' trait could make its canonical
representation unchanged.

As I said earlier, 'does' is an composition operator, it will change the
class composition, therefore making it a different object.

On the other hand, a 'realises' trait could change the object in order
that it would still match with both 'eqv' and '===', while still '~~' to
an additional type.

This would be done simply by creating an anonymous class that isa the
original class while overriding .^does, WHICH and eqv to shadow to the
original class, and then re-blessing the object to this anonymous class.

TSa wrote:
> But I would like to reserve infix: for a type check without
> subsequent canonical value comparison. That is continuing from above
>$b.inc;
>$a like $b; # still true even though $a.a != $b.a

It doesn't need to be part of the spec, it's a simple module that
traverses .^methods to check if $a implements all methods described by
$b. You might want to implement it already in other to "reserve" the
name ;).

daniel



Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread John M. Dlugosz

TSa Thomas.Sandlass-at-barco.com |Perl 6| wrote:


   multi infix:<=> (Any $lhs, A $rhs)
   {
   $lhs.STORE($rhs.clone); # or .cow if that's not automatic
   }



  $lhs.VAR.STORE.


My readings have been that = just copies the ref.  Unless it's a "value 
type" or "immutable" which just means that it doesn't matter.  I'll have 
to read up on that some more soon.


--John



Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread John M. Dlugosz

TSa Thomas.Sandlass-at-barco.com |Perl 6| wrote:

HaloO,

Daniel Ruoso wrote:

Not really... 'does' is a composition operation, 'realises' would be
just a type annotation that doesn't change the actual composition.


OK, but that is not in the spec yet. To me that is like the
proposed 'like' operator but with the programmer taking full
responsibility. Like reinterpret_cast in C++.


I've not gotten that far yet, but I do envision a way to test for 
conformance rather than mix-in to create conformance and change things 
around.  There might be a more primitive operation for doing than than 
binding a capture to a signature.


I also envision that this can give the compiler information that it uses 
to make a cached dispatch table, but this is not visible to the user.  
It just means that declaring your types, even "duck types" will not only 
give compile-time checking but speed up calling for that variable.







But either the HOW, the WHAT or both of $fp have to change
which implies that $y === $fp can't remain true after
$fp does Point. BTW, an interesting question is if a typed
binding could become invalid:

  subset AntiPoint of Any where {not .^does(Point)}

  my AntiPoint $ap := $fp; # fine for now

  $fp does Point; # now $ap is bound to a Point which
  # violates the AntiPoint constraint




It's not different than

   my Int $y = 5;
   subset X of Int where { $_ < 5 }
   my X $x := $y;
   ++$y;

The subset is part of the type of the item container.  You alias it to 
something which is a different type of container.  How can such aliasing 
ever be other than non-variant to be correct, unless the alias is read-only?


That's no different than defining a symbol with container type 
MyTiedItem and then trying to alias it to a plain Scalar.  Type mismatch 
in the := operation.


--John




Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread TSa

HaloO,

Daniel Ruoso wrote:

So...

 class A { has $.a; method inc { $.a++ } };
 $a = A.new( a => 0);
 $b = $a;
 $b.inc();
 $a.inc();
 say $a.a; # 2
 say $b.a; # 2

Will work as expected.


Depends a bit on one's expectations :)
So infix:<=> has shallow copy semantics. IIRC, there was once
an 'is deep' trait. Otherwise one has to implement

   multi infix:<=> (Any $lhs, A $rhs)
   {
   $lhs.STORE($rhs.clone); # or .cow if that's not automatic
   }



But either the HOW, the WHAT or both of $fp have to change


That is true


So, even though the WHICH stays the eqv check has to change:

$a = A.new( a => 0); # your class A
$b = A.new( a => 0);

$a === $b; # False, but
$a eqv $b; # True because of snapshot semantic

$b does Point;
$a eqv $b; # False because HOW or WHAT is different

BTW, is WHICH globally unique? Or is that also an
implementation detail?

The snapshot check is of course type aware:

class B { has $.a; method inc { $.a++ } };

$a = A.new( a => 0); # your class A
$b = B.new( a => 0); # same structural type

$a eqv $b; # False because of type mismatch

Funnily this implies we also need a version of eqv
that uses like or duck semantics. But this seems to
be foreseen. Could someone post the signature to use
for eqv() to make $a and $b to compare equal structurally
here? Is it eqv($a, $b, :(like A, like A))? Perhaps
that can be abbreviated to eqv($a, $b, :like)? Or even
infix: with the rational that this always is a
test not a modifying call like infix:. But I would
like to reserve infix: for a type check without
subsequent canonical value comparison. That is continuing
from above

   $b.inc;

   $a like $b; # still true even though $a.a != $b.a

Or the structural type test is similar to .does

   $a .like: $b;



BTW, an interesting question is if a typed
binding could become invalid:
   subset AntiPoint of Any where {not .^does(Point)}
   my AntiPoint $ap := $fp; # fine for now
   $fp does Point; # now $ap is bound to a Point which
   # violates the AntiPoint constraint


This is a composition error that generates an exception. It even
provides enough information for a compile-time error.


Where is it raised? In the '$fp does Point;' statement with
the error "can't compose role Point because of AntiPoint binding
to $ap"? How would that change if the line read

   my AntiPoint $ap = $fp; # or with real assignment
   # after the declaration

Would it say "can't compose role Point because of AntiPoint
reference in $ap"? How far does that reach? I mean does the
meta object system know about the constraints of all bindings
and stored references to an object?


Regards, TSa.
--

"The unavoidable price of reliability is simplicity"  -- C.A.R. Hoare
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread TSa

HaloO,

Daniel Ruoso wrote:

Not really... 'does' is a composition operation, 'realises' would be
just a type annotation that doesn't change the actual composition.


OK, but that is not in the spec yet. To me that is like the
proposed 'like' operator but with the programmer taking full
responsibility. Like reinterpret_cast in C++.



This way, the dispatching mechanism is still the same (and still typed),
but the object now also answers true to .^does(Point).

But note that
FoxPoint $fp = ...;
$y = $fp;
$y === $fp; # obviously true
$fp does Point;
$y === $fp; # false because of different HOW?


Wrong. $fp is still the same object and $y would also answer true
to .^does(Point). it's an in-place change, not a copy. you would need to
do

  $y = $fp.clone();


First of all assignment has copy semantics. That is after $y = $fp,
$y =:= $fp is false. I agree that

  $before := $fp;
  $fp does Point;
  $fp =:= $before; # maintain referential identity

But either the HOW, the WHAT or both of $fp have to change
which implies that $y === $fp can't remain true after
$fp does Point. BTW, an interesting question is if a typed
binding could become invalid:

  subset AntiPoint of Any where {not .^does(Point)}

  my AntiPoint $ap := $fp; # fine for now

  $fp does Point; # now $ap is bound to a Point which
  # violates the AntiPoint constraint



It doesn't. By definition. === only checks WHICH.


Then we must read different versions of S03. Mine has the
sentence "Two values are never equivalent unless they are
of exactly the same type."


Regards, TSa.
--

"The unavoidable price of reliability is simplicity"  -- C.A.R. Hoare
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread Daniel Ruoso

Ter, 2008-04-29 às 11:54 +0200, TSa escreveu:
> > If we are to define an operator to declare that some arbitrary object
> > conforms to some API, I would think the following as saner...
> > sub foo(Point $p) {...};
> > FoxPoint $fp = ...;
> > $fp realises Point;
> > foo($fp);
> Here the spec is quite clear that 'realises' is spelled 'does'.
> This is the infix operator that composes a role into an object's
> class at runtime.

Not really... 'does' is a composition operation, 'realises' would be
just a type annotation that doesn't change the actual composition.

> > This way, the dispatching mechanism is still the same (and still typed),
> > but the object now also answers true to .^does(Point).
> But note that
> FoxPoint $fp = ...;
> $y = $fp;
> $y === $fp; # obviously true
> $fp does Point;
> $y === $fp; # false because of different HOW?

Wrong. $fp is still the same object and $y would also answer true
to .^does(Point). it's an in-place change, not a copy. you would need to
do

  $y = $fp.clone();

to keep the non-typed version.

> Unfortunately S03 doesn't say if === checks for the same WHAT or the
> same HOW as precondition to checking the WHICH.

It doesn't. By definition. === only checks WHICH.

> Generally WHAT is also quite underspecced.

WHAT is implementation specific, it's underspecced for that reason.

> > Which means that the typed code remains typed and the feature is
> > implemented as a trait that can be used to any object, thus leaving the
> > fragile type inference to the code calling the method and not to the
> > method that wants a stronger typing...
> I don't understand what you want to say here.

I mean, the code that is calling the method would be the one doing the
untyped->typed mapping, not the calling sub signature (which would make
the dispatch much slower).

daniel



Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread Daniel Ruoso

Ter, 2008-04-29 às 09:28 +0200, TSa escreveu:
> The thing is the .^does  traverses the meta information
> to find the *named* concept Point. The FoxPoint in John's
> example doesn't have that and thus nominally fails the
> Point test. The idea is now to also have

.^does *might* traverse the information as well as simply return true if
the object says so.

The point here is whom to delegate the association between FoxPoint and
Point...

If we are to define an operator to declare that some arbitrary object
conforms to some API, I would think the following as saner...

sub foo(Point $p) {...};
FoxPoint $fp = ...;
$fp realises Point;
foo($fp);

This way, the dispatching mechanism is still the same (and still typed),
but the object now also answers true to .^does(Point).

Which means that the typed code remains typed and the feature is
implemented as a trait that can be used to any object, thus leaving the
fragile type inference to the code calling the method and not to the
method that wants a stronger typing...

daniel 



Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread TSa

HaloO,

Daniel Ruoso wrote:

.^does *might* traverse the information as well as simply return true if
the object says so.


Let's not regard the problem of meta level interoperation for now.
That is we have *one* meta level. The spec says that .^does asks
this meta system. Now the meta system does not invent the answer!
The programmer of FoxPoint has to declare that explicitly via

   class FoxPoint does Point {...}



The point here is whom to delegate the association between FoxPoint and
Point...


I see only two systems: the meta and the type system. The latter is
still underspecced. Even more unspecced is their interrelation.



If we are to define an operator to declare that some arbitrary object
conforms to some API, I would think the following as saner...

sub foo(Point $p) {...};
FoxPoint $fp = ...;
$fp realises Point;
foo($fp);


Here the spec is quite clear that 'realises' is spelled 'does'.
This is the infix operator that composes a role into an object's
class at runtime.



This way, the dispatching mechanism is still the same (and still typed),
but the object now also answers true to .^does(Point).


But note that

   FoxPoint $fp = ...;
   $y = $fp;
   $y === $fp; # obviously true

   $fp does Point;
   $y === $fp; # false because of different HOW?

Unfortunately S03 doesn't say if === checks for the same WHAT or the
same HOW as precondition to checking the WHICH. Generally WHAT is also
quite underspecced.



Which means that the typed code remains typed and the feature is
implemented as a trait that can be used to any object, thus leaving the
fragile type inference to the code calling the method and not to the
method that wants a stronger typing...


I don't understand what you want to say here.


Regards, TSa.
--

"The unavoidable price of reliability is simplicity"  -- C.A.R. Hoare
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: Polymorphism and Representations (Was: Re: First look: Advanced Polymorphism whitepaper)

2008-04-29 Thread TSa

HaloO,

Daniel Ruoso wrote:

hrmm... I might just be overlooking something... but...

sub foo (Point $p) {...}

means...

$signature ~~ $capture

means...

Point $p := $capture[0]

means...

$capture[0] ~~ Point

means...

$capture[0].^does(Point)


The thing is the .^does  traverses the meta information
to find the *named* concept Point. The FoxPoint in John's
example doesn't have that and thus nominally fails the
Point test. The idea is now to also have

  sub foo (Point $p) {...}

to mean

  $capture[0].^like(Point)

which does a *structural* analysis.


Regards, TSa.
--

"The unavoidable price of reliability is simplicity"  -- C.A.R. Hoare
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan