Re: Ways to add behavior

2005-11-08 Thread Larry Wall
On Mon, Nov 07, 2005 at 08:44:28PM +0100, TSa wrote:
: HaloO,
: 
: Larry Wall wrote:
:  : ::Takes3Ints ::= :(Int,Int,Int -- Any);
:  : 
:  : my foo:(Takes3Ints);
:  
:  I'd say that has to be something like:
:  
:  my foo:(Takes3Ints:);
:  
:  or maybe one of
:  
:  my foo:(Takes3Ints \!);
:  my foo:(\Takes3Ints);
:  my foo\(Takes3Ints);
:  
:  since Takes3Ints is the implementation and/or arglist type.
: 
: Sorry, you lost me. Why is there a invocant colon in the
: first example,

It would presumably indicate an implementation type for foo, which
is probably wrong.

: and what exactly does the ref indicator
: mean in all the three different alternatives?

Those would indicate an arglist parameter, which is probably right.
The most recent S06 has

sub foo (\$arglist)

to bind the entire arglist object to $arglist, though arguably (no pun
intended) the syntax could be:

sub foo \($arglist)

instead.  This goes with the decision that rvalue \(1,2,3,:foo)
generates an arglist object.

:  Otherwise how do you distinguish
:  
:  my foo:(Takes3Ints);
:  my foo:(Int, Int, Int);
: 
: You mean the latter foo as non-code, simple 3-tuple type?
: Otherwise I would think the  sigil implies the optional
: default :( -- Any).

The Any would be implied in that case.  I don't see much difference between
that and the multi disambiguating construct:

my foo := bar:(Int, Int, Int);
say foo(1,1,1);

: But than again I haven't fully grasped
: your notion of the pure type name before the first colon.

I was just playing off of your @array:(Array: ...) thought, but the
signature is not the implementation type, so forget that.

:  The colon would still be required in an rvalue context.  But the extension
:  of that to subs seems to be:
:  
:  my sub(Sub: \$args)
:  
:  Hmm, does that mean that a method actually looks like this?
:  
:  my meth(Method: $self: \$args)
: 
: I have ranted that I see method invocation as a two step
: call with a covariant dispatch first and then a normal
: contravariant call with argument type check, but why the
: second colon?

Only because multiple colons imply tiebreaking behavior under MMD.
I'm just trying to picture SMD as a form of MMD.

: And why the first on sub(Sub: \$args)? Just
: to name the intended code subtype?

Yes, just the same as your @array:(FooArray: ...) idea that the first
invocant is the function-like object implementing the thing.

Larry


Re: Ways to add behavior

2005-11-07 Thread TSa

HaloO,

Stevan Little wrote:
This is actually the principe behind the Ruby style singleton methods  
(the shadow class), it basically creates an anon-class which inherits  
from $x's original class, then it rebinds/blesses $x into the anon- 
class. It is very simple really :)


Yes, it's the typical case were an implementation is way easier than
the (type) theoretical modelling of such a simple pointer reassignment.
Assignment in general is very difficult to model, actually.


As for if this is/should be accessible through .meta, i am not sure  
that is a good idea. The reason being is that .meta brings with it  the 
idea of metaclasses, which then relates to classes, and so now  the user 
is thinking they are accessing the metaclass of the class of  which $x 
is an instance.


Indeed, we should drop the association of meta with class. There should
be just meta *information* (MI) which is sort of opaque to the general
public. The .meta method should return a MIO (Meta Info Object, My Internal
Object, or what ever) from the MIR (Meta Info Repository). Note that mio in
italian means 'my' or 'mine' depending on the grammatical slot.


I would suggest instead that we have a method, which is found in  Object 
which allows instances to add methods to themselves (and only  
themselves). In Ruby this is called 'add_singleton_method' or  something 
like that. I use that same name in the metamodel prototype  too.



In the absence of that, what's going on seems more like

$x.META::addmethod($arg);

where META:: is smart enough to dispatch to the proper metaclass  without
throwing away the invocant, and then the metaclass decides what to do
based on the instancehood of $x.


Since we have imperative runtime forms of 'does' for role composition
why not the equivalent on the 'has' installer. But I know it reads bad.

   $x has action;
   $x has .action = action; # code slot form

   $x does action; # action wrapping role created on the fly?

   $x gets action; # new keyword?

But IIRC, re-opening of classes is now done with 'is also' and 'does also'
for extending and 'is instead' and 'does instead' for replacing
functionality. This reads better imperatively on the instance level:

   $x has also action;


In the prototype style the my form could use a class style declarator
block:

  my $point
  {
  has Num $.x = 0;
  has Num $.y = 0;

  method magnitude { sqrt( $.x**2 + $.y**2 ) }
  }

  $a = $point;  # kind is implicitly copied, that is $a.kind == $b.kind
  $b = $point;  # which could also be tested with ^$a == ^$b or $a =^= $b

  $a.x = 3; # easy with COW and a pseudo-hash implementation of $point kind
  $a.y = 4;

  say $a.magnitude; # prints 5



I am not sure I like this for 2 reasons.

1) META:: smells like ::SUPER, and that feels like re-dispatching to  
me, which is not really what we need to be doing.


I agree. Adding to an object incrementally slides it out of it's class's
kind to ultimately become its own singleton kind. Hmm, this gives us a
beautifully ugly cast operator syntax

  $foo.kind = Bar; # re-bless
  $foo.kind(Bar);  # same?
  Bar.bless($foo); # same?

  $foo ^= Bar;  # kind assignment available?

  if Bar{$foo}  # theorytic query
  {
 $foo.kind = Bar; # success guaranteed, I almost wrote: guaran-tied :)
  }

  $foo.kind = Bar if Bar{$foo}; # as statement modifier

to make such a transition in a single jump. The ^Bar kinding/blessing
of $foo might not succeed unless ^Bar is prepared to accept ^$foo kinds,
though.

And, I think perlkind is expecting persistence of referential identity of
$foo independent of the success or failure of the re-blessing. I guess there
should be a dedicated exception kind to handle that. So you can sport a very
experimental, explorative programming style.
--


Re: Ways to add behavior

2005-11-07 Thread TSa

HaloO,

Larry Wall wrote:

: or is 'bound of' proper english?

It doesn't really resonate for a native speaker.


--snip--


:  Plus, as we've defined
: them above, subtypes are the most generic type you can name in Perl.


--snip--


I wasn't using the term generic in a type-theoretic sense.  Rather,
I was calling them generic in an operational sense, which you just
demonstrated.  You can turn any other type into a subtype alias that
adds no additional constraints.  Maybe I should have said the widest
type instead.


With the introduction of kind capture variables ^T we could complety
drop the subtype special form. As you pointed out the adding of constraints
happens with the where clause anyway. Thus we return to the usage of the
compile time name assignment form

  ::Blahh ::= ::Fasel where {...}

where the :: in all cases means working on the MIR (Meta Information
Repository) which is the world of names (In Russian, Mir (Мир) means
peace, and connotes community. --- cited from Wikipedia).

Question: shouldn't there be a natural 1 to 1 relation of ::T and ^T
or globally ::*T and ^*T where the former is the name and the latter
the kind represented by T? Of course scoping applies and there are
anonymous things that can be captured into ^T vars at runtime.

If the answer is 'yes' as I expect, I wonder if the compiler has to restrict
the usage of ::= to scopes which don't depend on runtime evaluations like

   if $x  10 { ::*Surprise ::= ::*FunnyType; say 'did it'; }

Or should these be extracted out, making the above mean

   ::*Surprise ::= ::*FunnyType; # or further out if necessary

   if $x  10 { say 'did it'; }



: Question: does a subtype declaration work only on package-like things
: which are addressed with a :: sigil? Or does your 'potentially
: contravariant' mean that arrow types can be constraint or aliased, as
: well?
: 
:   subtype TakesInt of Sub where { .sig =:= :(Int -- Any) };
: 
:   my TakesInt foo;
: 
:   foo('a string'); # type error


Hmm, I would read that as declaring that foo *returns* a TakesInt,
not that foo *is* a TakesInt.  Just as

my TakesInt @bar;

declares an array of individual TakesInt elements.


This is not too bad because then the  sigil is naturally associated
with the :( -- ) arrow type syntax and the forms can be mixed only
to the extent of signature aliasing:

::Takes3Ints ::= :(Int,Int,Int -- Any);

my foo:(Takes3Ints);

How does arrow typing apply to the three data sigils $, @ and %?
Compare:

my $foo:(Int); # non-referential value type
my $foo:(--Int); # same? Or perhaps means anonymous ref/link/alias?
my $foo:(Ref--Int) # explicit reference? same as 'is ref' trait?
my $foo:(Item: --Int) # tied container

Which is the default when the Int is used in the type slot of the
declaration?

   my Int $foo;

Could this be used to define the key type of hashes?

   my %foo:(Blahh--Any);

And shape of arrays

   my @foo:(Int,Int,Int--Any);

where the Int or subtypes of it are enforced and Any defaulted.
Thus this could just be

   my @foo:(!,!,!);

The covariant invocant/container types are of course

   my $item :(Item:  -- Any);
   my @array:(Array: Int -- Any);
   my %hash :(Hash:  Key -- Any);

The  sigils have a free signature and ^ vars obviously have no signature
other than pure type ;)
--
$TSa.greeting := HaloO; # mind the echo!



Re: Ways to add behavior

2005-11-07 Thread Larry Wall
On Mon, Nov 07, 2005 at 01:05:16PM +0100, TSa wrote:
: With the introduction of kind capture variables ^T we could complety
: drop the subtype special form. As you pointed out the adding of constraints
: happens with the where clause anyway. Thus we return to the usage of the
: compile time name assignment form
: 
:   ::Blahh ::= ::Fasel where {...}
: 
: where the :: in all cases means working on the MIR (Meta Information
: Repository) which is the world of names (In Russian, Mir (Мир) means
: peace, and connotes community. --- cited from Wikipedia).

Except that a type declarator can remove the need for all those extra ::
markers.  (Actually, the ::Fasel can be presumably written Fasel if
Fasel is already declared, so the only strangeness is on the left.
We could hack identifier-left-of ::= like we did identifier-left-of =,
or we could turn ::= into more of a general alias macro idea.  But I think
people generally like declarators out to the left for readability.)

: Question: shouldn't there be a natural 1 to 1 relation of ::T and ^T
: or globally ::*T and ^*T where the former is the name and the latter
: the kind represented by T? Of course scoping applies and there are
: anonymous things that can be captured into ^T vars at runtime.

Yes, that's basically how I see it.  ::T is the literal form, ^T is the
free form, but both map to package T in some scope or other.

: If the answer is 'yes' as I expect, I wonder if the compiler has to restrict
: the usage of ::= to scopes which don't depend on runtime evaluations like
: 
:if $x  10 { ::*Surprise ::= ::*FunnyType; say 'did it'; }
: 
: Or should these be extracted out, making the above mean
: 
:::*Surprise ::= ::*FunnyType; # or further out if necessary
: 
:if $x  10 { say 'did it'; }

To me it's similar to

my $x = 1 if $y;

which should probably just be disallowed or warned about under strict.
On the other hand, the declarations in a class file are also contingent
on the class being used, so those declarations are also in a conditional
context.  So maybe we should just declare such things to be erroneous.

: : Question: does a subtype declaration work only on package-like things
: : which are addressed with a :: sigil? Or does your 'potentially
: : contravariant' mean that arrow types can be constraint or aliased, as
: : well?
: : 
: :   subtype TakesInt of Sub where { .sig =:= :(Int -- Any) };
: : 
: :   my TakesInt foo;
: : 
: :   foo('a string'); # type error
: 
: Hmm, I would read that as declaring that foo *returns* a TakesInt,
: not that foo *is* a TakesInt.  Just as
: 
: my TakesInt @bar;
: 
: declares an array of individual TakesInt elements.
: 
: This is not too bad because then the  sigil is naturally associated
: with the :( -- ) arrow type syntax and the forms can be mixed only
: to the extent of signature aliasing:
: 
: ::Takes3Ints ::= :(Int,Int,Int -- Any);
: 
: my foo:(Takes3Ints);

I'd say that has to be something like:

my foo:(Takes3Ints:);

or maybe one of

my foo:(Takes3Ints \!);
my foo:(\Takes3Ints);
my foo\(Takes3Ints);

since Takes3Ints is the implementation and/or arglist type.
Otherwise how do you distinguish

my foo:(Takes3Ints);
my foo:(Int, Int, Int);

: How does arrow typing apply to the three data sigils $, @ and %?
: Compare:
: 
: my $foo:(Int); # non-referential value type
: my $foo:(--Int); # same? Or perhaps means anonymous ref/link/alias?
: my $foo:(Ref--Int) # explicit reference? same as 'is ref' trait?
: my $foo:(Item: --Int) # tied container
: 
: Which is the default when the Int is used in the type slot of the
: declaration?
: 
:my Int $foo;

That means

   my $foo:(--Int);

: Could this be used to define the key type of hashes?
: 
:my %foo:(Blahh--Any);
: 
: And shape of arrays
: 
:my @foo:(Int,Int,Int--Any);
: 
: where the Int or subtypes of it are enforced and Any defaulted.

Certainly.  I wouldn't mind getting rid of the shape property.

: Thus this could just be
: 
:my @foo:(!,!,!);

Yeah, though that doesn't mean you can't write @foo[1] and get a :(!,!)
out of it.

: The covariant invocant/container types are of course
: 
:my $item :(Item:  -- Any);
:my @array:(Array: Int -- Any);
:my %hash :(Hash:  Key -- Any);
: 
: The  sigils have a free signature and ^ vars obviously have no signature
: other than pure type ;)

Works for me.  As with  sigs, we might be able to lose the colon in
a declarative context:

   my $item(Item:  -- Any);
   my @array(Array: Int -- Any);
   my %hash(Hash:  Key -- Any);

The colon would still be required in an rvalue context.  But the extension
of that to subs seems to be:

my sub(Sub: \$args)

Hmm, does that mean that a method actually looks like this?

my meth(Method: $self: \$args)

I also wonder about hybrid hash/arrays:

   my %harry(HashArray:  Key^Int -- Any);

It would be nice to generalize this sufficiently to be able to declare
polymorphic objects resembling 

Re: Ways to add behavior

2005-11-07 Thread Larry Wall
On Mon, Nov 07, 2005 at 09:37:04AM -0800, Larry Wall wrote:
: It would be nice to generalize this sufficiently to be able to declare
: polymorphic objects resembling match objects:
: 
:my $matchobj(Poly:  Key^Int^Notthere -- Any);
: 
: Or maybe that should be:
: 
:my $matchobj\(Highlander);
: 
: :-)

But seriously, I do keep wanting poly objects to keep trees in.  For
example, I want to represent XML with the tag attributes in a hash
but the contents in a list:

$obj = q:xml;   # (conjectural here-xml syntax)
t1 a1=x a2=y a3=z
text2
t2/
text2
/t1

say ~$obj;  # t1
say $obj.xml;   # t1 ... /t1
say $obj{a2};   # y
say $obj[2];# text2
say ~$obj.first('t2')   # t2
say $obj.first('t2').xml# t2/

Larry


Re: Ways to add behavior

2005-11-07 Thread TSa
HaloO,

Larry Wall wrote:
 : ::Takes3Ints ::= :(Int,Int,Int -- Any);
 : 
 : my foo:(Takes3Ints);
 
 I'd say that has to be something like:
 
 my foo:(Takes3Ints:);
 
 or maybe one of
 
 my foo:(Takes3Ints \!);
 my foo:(\Takes3Ints);
 my foo\(Takes3Ints);
 
 since Takes3Ints is the implementation and/or arglist type.

Sorry, you lost me. Why is there a invocant colon in the
first example, and what exactly does the ref indicator
mean in all the three different alternatives?


 Otherwise how do you distinguish
 
 my foo:(Takes3Ints);
 my foo:(Int, Int, Int);

You mean the latter foo as non-code, simple 3-tuple type?
Otherwise I would think the  sigil implies the optional
default :( -- Any). But than again I haven't fully grasped
your notion of the pure type name before the first colon.


 The colon would still be required in an rvalue context.  But the extension
 of that to subs seems to be:
 
 my sub(Sub: \$args)
 
 Hmm, does that mean that a method actually looks like this?
 
 my meth(Method: $self: \$args)

I have ranted that I see method invocation as a two step
call with a covariant dispatch first and then a normal
contravariant call with argument type check, but why the
second colon? And why the first on sub(Sub: \$args)? Just
to name the intended code subtype?
-- 


Re: Ways to add behavior

2005-11-05 Thread Larry Wall
On Sat, Nov 05, 2005 at 01:55:11AM +0100, TSa wrote:
: Larry Wall wrote:
: The notion of constraints or limitations is already conveyed by
: where, and some subtypes may just be aliases.
: 
: Wouldn't 'bound' work? Perhaps combined with 'on':
: 
:   bound SmallInt on Int where { 0  $_  100 };
: 
: and
: 
:   Int bound SmallInt where { 0  $_  100 };
: 
: or is 'bound of' proper english?

It doesn't really resonate for a native speaker.

: And perhaps ranges could be allowed in the type slot
: 
:   my 1..100 $x;
: 
:   $x = 101; # type error
: 
: And with enums
: 
:   my enum a b c d $x;
: 
:   $x = g; # error unless g exists and returns a type
:   # structurally equal to enum a b c d which
:   # might be the same as 0..3

It starts getting a bit special-casey to allow rvalue-ish expressions
in the type slot.  Now that we have a type sigil, maybe:

my ^(1..100) $x
my ^(enum a b c d) $x;

:  Plus, as we've defined
: them above, subtypes are the most generic type you can name in Perl.
: 
: Ahm, why? They just add predicates that have to hold true. The only
: genericity I see is that a subtype declaration doesn't need anything
: remotely implementation like. Not even the constraint type must be
: there yet:
: 
:   subtype Blahh of ::Fasel; # declaration of Fasel deferred
: 
:   my Blahh $b .=new; # compiles for now, but needs ::Fasel eventually
: 
: BTW, could we restrict predicates to deal with the state available through
: the type/kind that is constraint? This would allow compile time calculations
: of contraint subsumption, type entailment and of upper and lower bounds.

I wasn't using the term generic in a type-theoretic sense.  Rather,
I was calling them generic in an operational sense, which you just
demonstrated.  You can turn any other type into a subtype alias that
adds no additional constraints.  Maybe I should have said the widest
type instead.

: Question: does a subtype declaration work only on package-like things
: which are addressed with a :: sigil? Or does your 'potentially
: contravariant' mean that arrow types can be constraint or aliased, as
: well?
: 
:   subtype TakesInt of Sub where { .sig =:= :(Int -- Any) };
: 
:   my TakesInt foo;
: 
:   foo('a string'); # type error

Hmm, I would read that as declaring that foo *returns* a TakesInt,
not that foo *is* a TakesInt.  Just as

my TakesInt @bar;

declares an array of individual TakesInt elements.

: This might actually produce the strange association of subtype
: with subs and requesting corresponding methodtype, datatype,
: roletype, etc. keywords for other kinds of types.

I really don't know how far it makes sense to drive this.  Mostly I'm
just trying to keep the syntax open enough that the bikeshed doesn't
end up looking like grafitti when we're done.

Larry


Re: Ways to add behavior

2005-11-04 Thread TSa

HaloO,

Larry Wall wrote:

On Wed, Oct 26, 2005 at 04:56:23PM -0600, Luke Palmer wrote:
:  Then ^T $x binds T to the kind of $x.  And $x.kind == $y.kind asks
:  if two objects are of the same type,
: 
: Don't you mean $x.kind eqv $y.kind?


I start to dislike the eqv name as generic value comparator because
it looks too much like the dual of xor. And there is the numeric
comparator = and its string companion cmp. But I don't want to re-open
the settled discussion of the operator names. OTOH, we could use the Num
kind as the prime representative of things that provide ==, !=, =, =,
,  and =. Actually != is a bit odd there, but I guess no one would
accept  even if it were available. But then keeping the ! logical negation
indicator we could use ! and ! instead of = and = respectively.

This is not too bad linguistically if we define

below ! not below  # = is an alias
above ! not above  # = is an alias
 ==  equal=!= not equal
  =  equal != not equal  # this one is just too beautiful
 # to become Perl6 reality :)

and the string counter parts

 lt ge  !lt   !
 gt le  !gt   !
 eq ==   ne  !eq  =!=

Thus logical negation becomes a meta prefix operator like
meta postfix = deals with infix ops. The unless conditional
form then means exactly the same as outer logical negation

 if $x != $y  {...}
 if   !($x == $y) {...}   # same, also with space:   ! (...)
 unless $x == $y  {...}   # same
 if $x not == $y  {...}   # same
 if not($x == $y) {...}   # same, also with space: not (...)
 if($x == $y).not {...}   # same, method form

As a side effect the junctive annoyance

 if $x != any(1,2,3) {...}

automagically becomes

 if !($x == any(1,2,3)) {...}

The in-place modification unary method form then is $x.=not and might
have an optional boolean argument whose negated form becomes the new
boolean property. So $x.=not(0) means '$x becomes not false'. With bit
beeing an abbreviation of 'be it' just as not means 'no true' this can
be spelled $x.=bit(1) and read '$x becomes be it true' or some such.

If the Num kind models the mathematical ideal of real numbers then
$x == $y is synonym to false and $x != $y to true almost always. Anyone
doing numerics knows that you should actually use abs($x - $y)  $eps.
With $eps == 1 you get the integer case. Implementing Num as Int+Rem
where 0 ! Rem  1 the Int comparison would be spelled

   $x ==:rem(0) $y

or perhaps better looking as

   $x == $y :rem(0)

or

   $x ==:int $y

Note that there is a slight difference to $x ==:eps(1.0) $y which is true
for $x = 3.8 and $y = 4.2 because their delta is 0.4 while 3  4 intwise.
The default fall-back in case of $x and $y beeing actual non-int nums could
use e.g. :eps(1e-6) which of course is configurable via pragma

  use Num:eps(1e-10);

The spelled out forms might read

   $x equal:int $y  # infix form

   $x.equal( :int, $y ) # method form

   equal :int, $x, $y;  # listop form

and correspondingly

   $x below:int $y  # infix form

   $x.below( :int, $y ) # method form

   below :int, $x, $y;  # listop form


This logical negation idea could even be driven further

  // err /!/ nerr
  ||  or |!| nor
   and ! nand
  ^^ xor ^!^ nxor eqv

The same can be done with the equality/identity checkers
where the intended concept is indicated by something between
the two = chars

== generic num-like equality=!=  generic num-like inequality
   =:= referential identity
  =::= symbol identity
   =^= kind identity

 = value copy
:= referential binding
   ::= symbol binding

and perhaps something like

   :: type below
   :: type above

   ^  kind below   # or:  ^  ^=  ^
   ^  kind above



Now that infix::: has come available, maybe I mean:

$x.kind :: $y.kind


Well or

  $x =^= $y

and also

 ^$x == ^$y


Sorry, couldn't resist.
--


Re: Ways to add behavior

2005-11-04 Thread TSa

HaloO,

Larry Wall wrote:

At the moment, I think the weakest word choice is subtype.
People from certain cultures will confuse subtypes with subclasses.


Not to mention submethods and subroutines!



The notion of constraints or limitations is already conveyed by
where, and some subtypes may just be aliases.


Wouldn't 'bound' work? Perhaps combined with 'on':

  bound SmallInt on Int where { 0  $_  100 };

and

  Int bound SmallInt where { 0  $_  100 };

or is 'bound of' proper english? And perhaps ranges could be allowed
in the type slot

  my 1..100 $x;

  $x = 101; # type error

And with enums

  my enum a b c d $x;

  $x = g; # error unless g exists and returns a type
  # structurally equal to enum a b c d which
  # might be the same as 0..3



 Plus, as we've defined
them above, subtypes are the most generic type you can name in Perl.


Ahm, why? They just add predicates that have to hold true. The only
genericity I see is that a subtype declaration doesn't need anything
remotely implementation like. Not even the constraint type must be
there yet:

  subtype Blahh of ::Fasel; # declaration of Fasel deferred

  my Blahh $b .=new; # compiles for now, but needs ::Fasel eventually

BTW, could we restrict predicates to deal with the state available through
the type/kind that is constraint? This would allow compile time calculations
of contraint subsumption, type entailment and of upper and lower bounds.

Question: does a subtype declaration work only on package-like things
which are addressed with a :: sigil? Or does your 'potentially
contravariant' mean that arrow types can be constraint or aliased, as
well?

  subtype TakesInt of Sub where { .sig =:= :(Int -- Any) };

  my TakesInt foo;

  foo('a string'); # type error

This might actually produce the strange association of subtype
with subs and requesting corresponding methodtype, datatype,
roletype, etc. keywords for other kinds of types.



So maybe we should go with type...which is yet another thing I've
waffled on repeatedly...


HiHi.
--


Re: Ways to add behavior

2005-10-27 Thread Michele Dondi

On Wed, 26 Oct 2005, Rob Kinyon wrote:


I'd like to take this moment and point to my somewhat hand-wavy
metamodel proposal from last week. When Stevan and I were talking
about this, we called it a quark. Atom also works quite nicely,
but quarks are cooler.


They're also colorful. Does this mean we will have a colour trait? But 
most importantly, who is supposed to be $Muster_Mark?


Seriously, quark was originally chosen as a name because of the 
appearance of _three_ (somewhat mysterious) objects. Now it would 
indeed be cool to borrow the term in a CS context, especially in Perl, but 
it would be better suited in a naturally ternary (say, 
{property,structure}-wise) context.



Michele
--
Il tempo e' denaro, ma anche il denaro e' denaro.
- William Gibson, L'accademia dei sogni.


Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-27 Thread Rob Kinyon
On 10/26/05, Larry Wall [EMAIL PROTECTED] wrote:
 On Wed, Oct 26, 2005 at 07:35:05PM -0700, chromatic wrote:
 : On Wed, 2005-10-26 at 21:58 -0400, Rob Kinyon wrote:
 :
 :  Plus, the argument is a straw man. Instead of:
 : 
 :  class Some::Class is also {
 :  }
 : 
 :  you would do:
 : 
 :  class My::Version {
 :  does Some::Class;
 :  }
 : 
 :  Problem solved.
 :
 : Don't forget the fun of modifying all existing uses of Some::Class to
 : use My::Version instead, if that's even possible.

 That should mostly be handled by virtualized class names.

Will I be able to do something like:

package Foo;
$*VERSION = 1.3.2;

use Foo-1.3.1;

role My::Foo { does Foo; ... }
alias My::Foo - Foo; # Or whatever the syntax should be

And, in my other code, use Foo; will DWIM?


Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-27 Thread Larry Wall
On Thu, Oct 27, 2005 at 05:37:13AM -0400, Rob Kinyon wrote:
: Will I be able to do something like:
: 
: package Foo;

Hmm, you just started in Perl 5 mode.

: $*VERSION = 1.3.2;

Perl 5 would get confused here, so I'm presuming Perl 6.  But Perl 6
isn't likely to let you override the global run-time Perl version.

: use Foo-1.3.1;

That I think I understand.

: role My::Foo { does Foo; ... }

Okay, My::Foo does Foo here.  Presumably it must do the Foo alias
that the use just installed.  And presumably the Foo you just used
is a role that can be done.  Certainly you can't do the global
package Foo, assuming that's what your original package declared.

: alias My::Foo - Foo; # Or whatever the syntax should be

I have no clue where you're intending to install that alias.
Are you trying to install a *Foo alias?  A bare Foo is going to first
find the local alias to the Foo you used, and that hides the global
Foo that it would have found otherwise.  I suspect you're trying to
say

*Foo := My::Foo;

: And, in my other code, use Foo; will DWIM?

I don't know quite what you mean, so I don't know if it'll do what
you mean.  If you're trying to establish a policy that defaults a
particular name to a particular version, the library interface will
probably give you a more straightforward way to set that up.

Larry


Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-27 Thread Rob Kinyon
On 10/27/05, Larry Wall [EMAIL PROTECTED] wrote:
 On Thu, Oct 27, 2005 at 05:37:13AM -0400, Rob Kinyon wrote:
 : Will I be able to do something like:
 :
 : package Foo;

 Hmm, you just started in Perl 5 mode.

 : $*VERSION = 1.3.2;

 Perl 5 would get confused here, so I'm presuming Perl 6.  But Perl 6
 isn't likely to let you override the global run-time Perl version.

 : use Foo-1.3.1;

 That I think I understand.

 : role My::Foo { does Foo; ... }

 Okay, My::Foo does Foo here.  Presumably it must do the Foo alias
 that the use just installed.  And presumably the Foo you just used
 is a role that can be done.  Certainly you can't do the global
 package Foo, assuming that's what your original package declared.

 : alias My::Foo - Foo; # Or whatever the syntax should be

 I have no clue where you're intending to install that alias.
 Are you trying to install a *Foo alias?  A bare Foo is going to first
 find the local alias to the Foo you used, and that hides the global
 Foo that it would have found otherwise.  I suspect you're trying to
 say

 *Foo := My::Foo;

 : And, in my other code, use Foo; will DWIM?

 I don't know quite what you mean, so I don't know if it'll do what
 you mean.  If you're trying to establish a policy that defaults a
 particular name to a particular version, the library interface will
 probably give you a more straightforward way to set that up.

Sorry. I'm not up on the syntax. I should do some serious backlog reading.

What I'm trying to do is load role Foo 1.0, have My::Foo do Foo, then
call My::Foo version 2.0 of Foo so that anyone else in my program will
see My::Foo instead of the original Foo. Is this possible?

Rob


Re: Ways to add behavior

2005-10-26 Thread Larry Wall
On Tue, Oct 25, 2005 at 05:17:40PM -0400, Stevan Little wrote:
: Larry,
: 
: On Oct 25, 2005, at 4:37 PM, Larry Wall wrote:
: On Mon, Oct 24, 2005 at 06:33:20AM -0700, Ashley Winters wrote:
: : # behavior through prototype -- guessing realistic syntax
: : Base.meta.add_method(
: : do_it = method ($arg) {
: : say doing $arg!;
: : });
: :
: :
: : # or, just add it to a single instance
: : $x.meta.add_method(
: : do_it = method ($arg) {
: : say doing $arg!;
: : });
: 
: I don't have a comment on your actual question, but I'd like to use
: this opportunity to point out the symmetry of Base and $x at this
: point, and the fact that .meta can't simply call .add_method in the
: metaclass, or it would lose track of the original invocant, which is
: needed to convey both class and instance information.  I'm not sure
: it's even possible to say
: 
: $m = $x.meta;
: $m.addmethod($arg);
: 
: The only way that can work is if $x.meta returns a shadow class that
: is prebound only to $x.  (Though that might explain how .addmethod
: knows it's only adding a method to the object.)
: 
: This is actually the principe behind the Ruby style singleton methods  
: (the shadow class), it basically creates an anon-class which inherits  
: from $x's original class, then it rebinds/blesses $x into the anon- 
: class. It is very simple really :)

Sure, but such a heavy behavior shouldn't be implied merely by trying
to get at the metaclass.

: As for if this is/should be accessible through .meta, i am not sure  
: that is a good idea. The reason being is that .meta brings with it  
: the idea of metaclasses, which then relates to classes, and so now  
: the user is thinking they are accessing the metaclass of the class of  
: which $x is an instance.
: 
: I would suggest instead that we have a method, which is found in  
: Object which allows instances to add methods to themselves (and only  
: themselves). In Ruby this is called 'add_singleton_method' or  
: something like that. I use that same name in the metamodel prototype  
: too.

That's fine, and fits in with Prototype-Think anyway.

: Here is how it could be done.
: 
: class ShadowClass does Class {}
: 
: class Object is reopened {

That might change to is also, the generic trait for appending to things
that may or may not be classes.  (And is instead is used to replace things.)

: method add_singleton_method (Str $label, Method $method) {
: if ($?SELF.class.class != ShadowClass) {

s/$?SELF/self/

And I think .class should be a coercion to the class view of its
invocant, which would make your second .class a no-op.  I think what
you're calling .class.class I'm calling .meta.class.  I want to
think of the class as an abstraction that is not an object.  Everything
you call Class I want to sweep behind .meta, because the metaclass instance
is the real class object.

: my $shadow = ShadowClass.new();
: $shadow.meta.superclasses([ $shadow ]);
: $?SELF.class = $shadow;

I think that should be self.meta = $shadow.  .class is not an
lvalue--it's just a restricted view of the current object.  (Again,
by my definitions.  I realize clashing definitions are at work here.
Maybe I can come up with a different word for what I call class.
Or maybe I get class, and you get Class :-) * .5

: }
: $?SELF.class.meta.add_method($label, $method);

That's just self.meta.add_method($label, $method) by my lights.
A .meta already implies/ignores the .class coercion.  If we are to
support prototype-based programming $x.meta *must not care* whether
it has been given a class or an instance or something in between.
What I am calling a class here is basically that portion of the
current instance that is the same for all members of its class.
And that common information presumably includes information on what to
do if a method is called that is not directly recognized by the object.
Class-based and prototype-based systems have different answers to that,
but they have something in common, and I'd like to abstract that out
and call it something.  I've been calling it class, but maybe I
should call it something else to avoid confusion.  A type maybe.
That would imply that ¢ is really a type variable rather than a class
variable.  But maybe type is too overloaded already.  But maybe not.

Anyway, if my class turns into type or something else, maybe I
can be persuaded to go with ^T instead of ¢T.

Larry


Re: Ways to add behavior

2005-10-26 Thread Rob Kinyon
 That's just self.meta.add_method($label, $method) by my lights.
 A .meta already implies/ignores the .class coercion.  If we are to
 support prototype-based programming $x.meta *must not care* whether
 it has been given a class or an instance or something in between.
 What I am calling a class here is basically that portion of the
 current instance that is the same for all members of its class.
 And that common information presumably includes information on what to
 do if a method is called that is not directly recognized by the object.
 Class-based and prototype-based systems have different answers to that,
 but they have something in common, and I'd like to abstract that out
 and call it something.  I've been calling it class, but maybe I
 should call it something else to avoid confusion.  A type maybe.
 That would imply that ¢ is really a type variable rather than a class
 variable.  But maybe type is too overloaded already.  But maybe not.

I'd like to take this moment and point to my somewhat hand-wavy
metamodel proposal from last week. When Stevan and I were talking
about this, we called it a quark. Atom also works quite nicely,
but quarks are cooler.

Plus, if you think about the definitions that go into creating an
instance (class, role, prototype, etc), it makes sense that if the
instance is the smallest indivisible thing there is, then the things
that go about being its definition are the quarks.

 Anyway, if my class turns into type or something else, maybe I
 can be persuaded to go with ^T instead of ¢T.

Q(T) ? :-)

Rob


Re: Ways to add behavior

2005-10-26 Thread Larry Wall
On Wed, Oct 26, 2005 at 11:31:28AM -0400, Rob Kinyon wrote:
:  That's just self.meta.add_method($label, $method) by my lights.
:  A .meta already implies/ignores the .class coercion.  If we are to
:  support prototype-based programming $x.meta *must not care* whether
:  it has been given a class or an instance or something in between.
:  What I am calling a class here is basically that portion of the
:  current instance that is the same for all members of its class.
:  And that common information presumably includes information on what to
:  do if a method is called that is not directly recognized by the object.
:  Class-based and prototype-based systems have different answers to that,
:  but they have something in common, and I'd like to abstract that out
:  and call it something.  I've been calling it class, but maybe I
:  should call it something else to avoid confusion.  A type maybe.
:  That would imply that ¢ is really a type variable rather than a class
:  variable.  But maybe type is too overloaded already.  But maybe not.
: 
: I'd like to take this moment and point to my somewhat hand-wavy
: metamodel proposal from last week. When Stevan and I were talking
: about this, we called it a quark. Atom also works quite nicely,
: but quarks are cooler.

Yes, I was sorry it got Warnocked.

: Plus, if you think about the definitions that go into creating an
: instance (class, role, prototype, etc), it makes sense that if the
: instance is the smallest indivisible thing there is, then the things
: that go about being its definition are the quarks.
: 
:  Anyway, if my class turns into type or something else, maybe I
:  can be persuaded to go with ^T instead of ¢T.
: 
: Q(T) ? :-)

Will be misinterpreted as sexist, so not on the Q/T.  :-)

One wants to coin a word like Qlass.  Unfortunately qlass is too
easy to misread as glass.  Oy veh, I'm getting notions of the qlass
is half empty for a partially instantiated object.

But it's probably not appropriate to coin a new term if we can force type
to work.  Someone please martial some objections.

Of course, there are other words that are somewhat synonymous with
class, Unfortunately sort is already hosed.  Maybe kind.
Then evolutionists could make jokes about the K(T) boundary, and
creationists could make jokes about reproducing after their kind.
Some of us could make either kind of joke.  But perhaps it wouldn't
be kind.

Larry


Re: Ways to add behavior

2005-10-26 Thread Austin Frank

Larry Wall wrote:


Of course, there are other words that are somewhat synonymous with
class, Unfortunately sort is already hosed.  Maybe kind.
Then evolutionists could make jokes about the K(T) boundary, and
creationists could make jokes about reproducing after their kind.
Some of us could make either kind of joke.  But perhaps it wouldn't
be kind.


Which (sort of) takes us back to TSa's (non)sign-off note from 10/5, 
wherein he suggested:


 I've always taken the 'what type of expression' approach to
 programming languages and thus have an affinity to type systems and
 type theory.
 With 'type' in general and 'data type' in particular beeing too
 misleading or used in too many different meanings in other programming
 languages I propose to coin the notion of 'kind' which has the nice
 double meaning of nice and sort. And as such gives the nice pun

  Perl 6, the kind language

 with the two meanings

  Perl 6, a kind of language
, the language of kind(ness)

I don't know if this is a good sign or a bad one, but the jokes started 
before you even made the suggestion!  :)


/au


Re: Ways to add behavior

2005-10-26 Thread Stevan Little


On Oct 26, 2005, at 12:05 PM, Larry Wall wrote:

Of course, there are other words that are somewhat synonymous with
class, Unfortunately sort is already hosed.  Maybe kind.


Actually kind is used in the Core Calculus for Metaclasses paper  
which I brought to the hackathon (not sure if you got to read it or  
not). Here is a link:


http://research.sun.com/projects/plrg/core-calculus.pdf

They present an rather interesting view on things, that the  
definition of the instance creating portion of a class should be  
seperated from the class or kind portion of the class. Actually  
the first metamodel prototype grew out of an implementation of the  
model they describe in the paper.


Stevan


Re: Ways to add behavior

2005-10-26 Thread Jonathan Scott Duff
On Wed, Oct 26, 2005 at 09:05:22AM -0700, Larry Wall wrote:
 Of course, there are other words that are somewhat synonymous with
 class, Unfortunately sort is already hosed.  Maybe kind.

Maybe we could go with something Linnaean like family or genus
even though their relation to class isn't quite the same.

-Scott
-- 
Jonathan Scott Duff
[EMAIL PROTECTED]


Re: Ways to add behavior

2005-10-26 Thread Ruud H.G. van Tol
Larry Wall:

 But perhaps it wouldn't be kind.

'caste' wouldn't either.

For inspiraton: type sort class variety brand category breed manner
style nature form hue caste set background stage setting milieu locale
range assortment selection mixture strain suite scenery rank grade
division status genre ...

-- 
Grtz, Ruud



Re: Ways to add behavior

2005-10-26 Thread Rob Kinyon
On 10/26/05, Stevan Little [EMAIL PROTECTED] wrote:

 On Oct 26, 2005, at 12:05 PM, Larry Wall wrote:
  Of course, there are other words that are somewhat synonymous with
  class, Unfortunately sort is already hosed.  Maybe kind.

 Actually kind is used in the Core Calculus for Metaclasses paper
 which I brought to the hackathon (not sure if you got to read it or
 not). Here is a link:

 http://research.sun.com/projects/plrg/core-calculus.pdf

 They present an rather interesting view on things, that the
 definition of the instance creating portion of a class should be
 seperated from the class or kind portion of the class. Actually
 the first metamodel prototype grew out of an implementation of the
 model they describe in the paper.

This might dovetail quite nicely into the discussion of how types are
now sets instead of junctions. Objects are now a junction of the
various kinds that were used to create it. Thus, boxed types are now
almost trivial to implement ... ?

Rob


Re: Ways to add behavior

2005-10-26 Thread Ruud H.G. van Tol
Stevan Little:

 They present an rather interesting view on things, that the
 definition of the instance creating portion of a class should be
 seperated from the class or kind portion of the class.

Its quality. Its character. Its features. Its face.

-- 
Grtz, Ruud


Re: Ways to add behavior

2005-10-26 Thread Brent 'Dax' Royal-Gordon
Larry Wall [EMAIL PROTECTED] wrote:
 Of course, there are other words that are somewhat synonymous with
 class, Unfortunately sort is already hosed.  Maybe kind.
 Then evolutionists could make jokes about the K(T) boundary, and
 creationists could make jokes about reproducing after their kind.
 Some of us could make either kind of joke.  But perhaps it wouldn't
 be kind.

Flavor.  (Shades of CLOS, but we're already building the most flexible
object system since it...)

--
Brent 'Dax' Royal-Gordon [EMAIL PROTECTED]
Perl and Parrot hacker


Re: Ways to add behavior

2005-10-26 Thread TSa

HaloO,

Austin Frank wrote:
Which (sort of) takes us back to TSa's (non)sign-off note from 10/5, 
wherein he suggested:


I just can't help it, I love the good work done on this list!
And thanks for spelling the acronym correctly.

The Kindly One of a class beeing the representative like
the President of the United States is the First of Man :)
With limited runtime, of course ...

Who knows the Kindly Ones from the Sandman? This nicely
complements the seven Endless and their sigils ;)
But the German Sandmännchen has to put the kids to sleep
now---sweet dreams to everyone.
--
$TSa.greeting := HaloO; # mind the echo!



Re: Ways to add behavior

2005-10-26 Thread Larry Wall
On Wed, Oct 26, 2005 at 12:22:07PM -0400, Stevan Little wrote:
: 
: On Oct 26, 2005, at 12:05 PM, Larry Wall wrote:
: Of course, there are other words that are somewhat synonymous with
: class, Unfortunately sort is already hosed.  Maybe kind.
: 
: Actually kind is used in the Core Calculus for Metaclasses paper  
: which I brought to the hackathon (not sure if you got to read it or  
: not). Here is a link:
: 
: http://research.sun.com/projects/plrg/core-calculus.pdf
: 
: They present an rather interesting view on things, that the  
: definition of the instance creating portion of a class should be  
: seperated from the class or kind portion of the class. Actually  
: the first metamodel prototype grew out of an implementation of the  
: model they describe in the paper.

Interesting.  I didn't read it, but a bunch of us seem to be converging
on the same elephant.  I'm thinking of kind as the actual type of a
real instance separate from the machinery.  I think it probably corresponds
to what Luke is saying about classes not really having names.

So maybe we can define our terms like this:

type: a completely generic metaterm for any of the following,
and then some.

class: a mutable interface object that manages instances in the
classical way, with covariant derivational properties.

role: an immutable and possibly generic interface class, with
covariant compositional properties.

kind: the abstract, often unnamed type of an actual instance
or storage location, abstracted from any of its machinery or
degree of definedness.  You should not generally declare a kind,
they just happen.

subtype: a potentially contravariant type based on any of the
previous types, allowed to impose constraints that are more
selective than a kind is allowed to be.

Then ^T $x binds T to the kind of $x.  And $x.kind == $y.kind asks
if two objects are of the same type, but $x.kind isn't a class-like
object, only an identity of some sort.  $x.meta returns the Class
instance, or whatever.

At the moment, I think the weakest word choice is subtype.
People from certain cultures will confuse subtypes with subclasses.
The notion of constraints or limitations is already conveyed by
where, and some subtypes may just be aliases.  Plus, as we've defined
them above, subtypes are the most generic type you can name in Perl.
So maybe we should go with type...which is yet another thing I've
waffled on repeatedly...

Larry


Re: Ways to add behavior

2005-10-26 Thread Uri Guttman
 LW == Larry Wall [EMAIL PROTECTED] writes:

  LW One wants to coin a word like Qlass.  Unfortunately qlass is
  LW too easy to misread as glass.  Oy veh, I'm getting notions of
  LW the qlass is half empty for a partially instantiated object.

[EMAIL PROTECTED],

i think you need some immediate mental help. please step back from the
keyboard before you commit such a sin again. the next time, i will ask
gloria to stick you with a knitting needle.

is the smiley :) or (: ?

uri

-- 
Uri Guttman  --  [EMAIL PROTECTED]   http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs    http://jobs.perl.org


Re: Ways to add behavior

2005-10-26 Thread Rob Kinyon
 So maybe we can define our terms like this:

 type: a completely generic metaterm for any of the following,
 and then some.

 class: a mutable interface object that manages instances in the
 classical way, with covariant derivational properties.

 role: an immutable and possibly generic interface class, with
 covariant compositional properties.

 kind: the abstract, often unnamed type of an actual instance
 or storage location, abstracted from any of its machinery or
 degree of definedness.  You should not generally declare a kind,
 they just happen.

 subtype: a potentially contravariant type based on any of the
 previous types, allowed to impose constraints that are more
 selective than a kind is allowed to be.

 Then ^T $x binds T to the kind of $x.  And $x.kind == $y.kind asks
 if two objects are of the same type, but $x.kind isn't a class-like
 object, only an identity of some sort.  $x.meta returns the Class
 instance, or whatever.

A few questions:
1) Where does prototype-style OO fit into all of this? I hope it's not
through repeated eigenclasses (or whatever they're called this week)
... that just sounds too heavy.
2) Isn't Dog|Cat kinda declaring a kind? Thus, can't you say my
Dog|Cat $catdog; and be talking about a kind? I would think that a
named kind is just a role ...
3) Aren't classes mutable and roles immutable by default only? Or has
this changed?

Rob


Re: Ways to add behavior

2005-10-26 Thread Larry Wall
On Wed, Oct 26, 2005 at 03:54:35PM -0400, Rob Kinyon wrote:
:  So maybe we can define our terms like this:
: 
:  type: a completely generic metaterm for any of the following,
:  and then some.
: 
:  class: a mutable interface object that manages instances in the
:  classical way, with covariant derivational properties.
: 
:  role: an immutable and possibly generic interface class, with
:  covariant compositional properties.
: 
:  kind: the abstract, often unnamed type of an actual instance
:  or storage location, abstracted from any of its machinery or
:  degree of definedness.  You should not generally declare a kind,
:  they just happen.
: 
:  subtype: a potentially contravariant type based on any of the
:  previous types, allowed to impose constraints that are more
:  selective than a kind is allowed to be.
: 
:  Then ^T $x binds T to the kind of $x.  And $x.kind == $y.kind asks
:  if two objects are of the same type, but $x.kind isn't a class-like
:  object, only an identity of some sort.  $x.meta returns the Class
:  instance, or whatever.
: 
: A few questions:
: 1) Where does prototype-style OO fit into all of this? I hope it's not
: through repeated eigenclasses (or whatever they're called this week)
: ... that just sounds too heavy.

I don't profess to be an expert on prototype style, but I think even
if we do it with eigenclasses it's not too heavy as long as we find
a way to share structurally identical eigenclasses.  Copy on write
would get some sharing benefit, though wouldn't coalesce eigenclasses
that just happened to converge on the same definition.

On the other hand, I think we can abstract out kindness sufficiently
well that, for the prototype kind of object, the machinery can just
clone the method refs along with the attributes.

: 2) Isn't Dog|Cat kinda declaring a kind?

If it resolves to a set of types, it can be *used* as a kind.  But if
you insist on the ORness of it, then it's really a subtype, because
a kind supports all of its member roles, not just one of them.

: Thus, can't you say my Dog|Cat $catdog; and be talking about a kind?

No, that merely asserts that the kind of $catdog must support those
two interfaces, assuming | just constructs a set.

But it's not clear that we'll support | there at all, but assuming
AND juxtapositional syntax, we can just write that:

my Dog Cat $catdog;

and get the same constraints on $catdog.  And the fact of the matter is
that either of Dog or Cat may be a constrained subtype, not a real kind.
If we say

my Even Odd $evenodd;

then we'll never match our constraints, despite the fact that Even and Odd
are both subtypes of Int, and Int can function as a kind.

: I would think that a named kind is just a role ...

No, other way around, a role is just a named kind.  More precisely,
a non-generic role can be forced to compose to a class that can
function as a kind.  But there can be kinds that don't behave well
according to the rules of roles.  You can't compose two kinds that
happen to represent native types, for instance.

: 3) Aren't classes mutable and roles immutable by default only? Or has
: this changed?

Of course.  To change the default for a role, call it a class, and
to change the default for a class, call it a role.  :-)

Larry


Re: Ways to add behavior

2005-10-26 Thread Luke Palmer
On 10/26/05, Larry Wall [EMAIL PROTECTED] wrote:
 So maybe we can define our terms like this:

 type: a completely generic metaterm for any of the following,
 and then some.

 class: a mutable interface object that manages instances in the
 classical way, with covariant derivational properties.

 role: an immutable and possibly generic interface class, with
 covariant compositional properties.

 kind: the abstract, often unnamed type of an actual instance
 or storage location, abstracted from any of its machinery or
 degree of definedness.  You should not generally declare a kind,
 they just happen.

We're screwing around with existing OO jargon, so it's probably not
too bad to screw around with this one too, especially since it only
appears under the covers in ML.

A kind is the signature of a type.  So, for instance,

Int   has kind *
Array has kind * - *
Array Int has kind *

Other than that, I think the term works find.

 subtype: a potentially contravariant type based on any of the
 previous types, allowed to impose constraints that are more
 selective than a kind is allowed to be.

 Then ^T $x binds T to the kind of $x.  And $x.kind == $y.kind asks
 if two objects are of the same type,

Don't you mean $x.kind eqv $y.kind?

Ugh.

 but $x.kind isn't a class-like
 object, only an identity of some sort.  $x.meta returns the Class
 instance, or whatever.

 At the moment, I think the weakest word choice is subtype.
 People from certain cultures will confuse subtypes with subclasses.
 The notion of constraints or limitations is already conveyed by
 where, and some subtypes may just be aliases.  Plus, as we've defined
 them above, subtypes are the most generic type you can name in Perl.
 So maybe we should go with type...which is yet another thing I've
 waffled on repeatedly...

constrained type?   Though that only works for the literature, not
Perl's active vocabulary.

Luke


Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread Rob Kinyon
 : 3) Aren't classes mutable and roles immutable by default only? Or has
 : this changed?

 Of course.  To change the default for a role, call it a class, and
 to change the default for a class, call it a role.  :-)

Does this mean that roles are the recommended way to create immutable
classes? Given that roles and classes now seem to differ only in their
mutability, I can't see a reason why I would use class as my default
object definer. I would prefer to use roles as they're closed by
default, leaving class to be my powertool, if I need the power.

Rob


Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread chromatic
On Wed, 2005-10-26 at 20:29 -0400, Rob Kinyon wrote:

 I would prefer to use roles as they're closed by default, leaving
 class to be my powertool, if I need the power.

I don't understand this desire; can you explain your reasoning?

(NB: closed here, as I use it, still *does not* correspond to
licensing or availability of the source code.)

-- c



Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread Rob Kinyon
On 10/26/05, chromatic [EMAIL PROTECTED] wrote:
 On Wed, 2005-10-26 at 20:29 -0400, Rob Kinyon wrote:

  I would prefer to use roles as they're closed by default, leaving
  class to be my powertool, if I need the power.

 I don't understand this desire; can you explain your reasoning?

If a role is an immutable class, that means that its internals cannot
be changed. Hence, the compiler can trust that it will be the same at
the end as at the beginning. Which means it's optimized. Which means
my objects run faster if I create them from roles than if I create
them from classes. And, given that this seems to be the sole
difference between them (mutability vs. immutability), why would I use
classes as my standard?

Rob


Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread Luke Palmer
On 10/26/05, Rob Kinyon [EMAIL PROTECTED] wrote:
 On 10/26/05, chromatic [EMAIL PROTECTED] wrote:
  On Wed, 2005-10-26 at 20:29 -0400, Rob Kinyon wrote:
 
   I would prefer to use roles as they're closed by default, leaving
   class to be my powertool, if I need the power.
 
  I don't understand this desire; can you explain your reasoning?

 If a role is an immutable class, that means that its internals cannot
 be changed. Hence, the compiler can trust that it will be the same at
 the end as at the beginning. Which means it's optimized. Which means
 my objects run faster if I create them from roles than if I create
 them from classes. And, given that this seems to be the sole
 difference between them (mutability vs. immutability), why would I use
 classes as my standard?

Okay, an open class means you can add methods to it, right?  So, let's
say you have this class:

class Foo {
method foo() {...}
method bar() {...}
}

And this code:

my Foo $x = Foo.new;
$x.foo();
$x.bar();

This might be compiled to the following pseudo intermediate code:

my $x = Foo[0]();
Foo[1]($x);
Foo[2]($x);

Now let's say you extend the class:

   class Foo is also {
   method baz() {...}
   }

Is there any reason that the preceding pseudo intermediate code is no
longer valid?  I don't see one; baz() is just installed in slot 3.  So
why would you say it was faster to have it closed?

Indeed, it *could* be faster.  But we find that many programmers make
decisions that trade readability and extensibility for an extra 1% of
speed, even when they are writing a command-line frontend to
MPlayer[1].  If those people are module writers, then we have a bunch
of modules on CPAN that are not friendly to the user who wants to use
the module in the one way the writer didn't expect.

So the reason we made classes open by default is so that people
wouldn't have a chance to make that decision until they're more
experienced.  Indeed, no module writer can say that a class is closed;
only the main program may say that, because the main program knows the
most about how everything is used.  The precise definition of main
program is not well-defined yet, but it's there so that a module
writer doesn't close himself off from the world without knowing how
his module is even being used.

And if you're going to use roles for everything because they're closed
and they will gain you 2% of speed on one particular backend, then
we'll have to make the same rule for them too.  I know it sounds like
we're babying our programmers.  We are, because it's such a
widespread superstition.

And just to reinforce that it's a superstition:  a theory defines a
vtable.  If you extend the class in an incompatible way, you have to
make a new instance of its theory, defining new vtable slots.  Once
the new vtable is created, it is just as fast as the old one.  There
is no speed loss whatsoever for keeping your class open.

Luke

[1] This is a concrete example that I actually witnessed.


Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread Larry Wall
On Wed, Oct 26, 2005 at 08:48:12PM -0400, Rob Kinyon wrote:
: If a role is an immutable class, that means that its internals cannot
: be changed. Hence, the compiler can trust that it will be the same at
: the end as at the beginning. Which means it's optimized. Which means
: my objects run faster if I create them from roles than if I create
: them from classes. And, given that this seems to be the sole
: difference between them (mutability vs. immutability), why would I use
: classes as my standard?

Because it might be a premature optimization to the extent that it
restricts flexibility before you know whether it's going to affect
performance.  Part of the power of Ruby on Rails reputedly comes from
the fact that Ruby leaves its classes open by default.

Larry


Re: Ways to add behavior

2005-10-26 Thread Larry Wall
On Wed, Oct 26, 2005 at 04:56:23PM -0600, Luke Palmer wrote:
:  Then ^T $x binds T to the kind of $x.  And $x.kind == $y.kind asks
:  if two objects are of the same type,
: 
: Don't you mean $x.kind eqv $y.kind?
: 
: Ugh.

Now that infix::: has come available, maybe I mean:

$x.kind :: $y.kind

Now all we need is infix:: to calculate the value of the relationship
of two items, and we can write:

$a : $b :: $c : $d

:-) * .5

Larry


Re: Ways to add behavior

2005-10-26 Thread Larry Wall
On Wed, Oct 26, 2005 at 06:34:48PM -0700, Larry Wall wrote:
: On Wed, Oct 26, 2005 at 04:56:23PM -0600, Luke Palmer wrote:
: :  Then ^T $x binds T to the kind of $x.  And $x.kind == $y.kind asks
: :  if two objects are of the same type,
: : 
: : Don't you mean $x.kind eqv $y.kind?
: : 
: : Ugh.
: 
: Now that infix::: has come available, maybe I mean:
: 
: $x.kind :: $y.kind

And maybe eq and == could degenerate to :: if both args aren't
coercable to the desired type.

Larry


Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread chromatic
On Wed, 2005-10-26 at 19:22 -0600, Luke Palmer wrote:

 But we find that many programmers make decisions that trade
 readability and extensibility for an extra 1% of speed, even when they
 are writing a command-line frontend to MPlayer[1].  If those people
 are module writers, then we have a bunch of modules on CPAN that are
 not friendly to the user who wants to use the module in the one way
 the writer didn't expect.

Worse, that's a *theoretical* 1% of speed based on non-profiled code.

 And if you're going to use roles for everything because they're closed
 and they will gain you 2% of speed on one particular backend, then
 we'll have to make the same rule for them too.  I know it sounds like
 we're babying our programmers.  We are, because it's such a
 widespread superstition.

I prefer to think of it as Helping to prevent them from writing
unreusable code.

 And just to reinforce that it's a superstition:  a theory defines a
 vtable.  If you extend the class in an incompatible way, you have to
 make a new instance of its theory, defining new vtable slots.  Once
 the new vtable is created, it is just as fast as the old one.  There
 is no speed loss whatsoever for keeping your class open.

Even further, don't forget that someone, somewhere will really need to
do something you didn't think of.  Either he extends your class somehow
or works around it in an ugly, funky way.

Which one is faster to write?  Which one is faster to execute?  Which
one is more likely to be correct?  Which one is more maintainable?

-- c



Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread Rob Kinyon
On 10/26/05, Luke Palmer [EMAIL PROTECTED] wrote:
[snip]
 Okay, an open class means you can add methods to it, right?  So, let's
 say you have this class:

 class Foo {
 method foo() {...}
 method bar() {...}
 }

 And this code:

 my Foo $x = Foo.new;
 $x.foo();
 $x.bar();

 This might be compiled to the following pseudo intermediate code:

 my $x = Foo[0]();
 Foo[1]($x);
 Foo[2]($x);

 Now let's say you extend the class:

class Foo is also {
method baz() {...}
}

 Is there any reason that the preceding pseudo intermediate code is no
 longer valid?  I don't see one; baz() is just installed in slot 3.  So
 why would you say it was faster to have it closed?

What about:

class Foo is also {
method foo() { ... }
}

Where the second foo() is no longer what the first foo() did.
Furthermore, let's say you have:

class Bar isa Foo {
method floober() { ... }
}

If they were roles, then role Bar could alias all the methods it
inherits from role Foo. In other words, it can cache all the method
lookups at compile-time. That's a substantial savings. If they're open
classes, the runtime has to throw out all the cached lookups the
moment any of the classes upstream are modified.

Plus, the argument is a straw man. Instead of:

class Some::Class is also {
}

you would do:

class My::Version {
does Some::Class;
}

Problem solved.

Rob


Re: Ways to add behavior

2005-10-26 Thread chromatic
On Wed, 2005-10-26 at 14:52 -0400, Uri Guttman wrote:

  LW == Larry Wall [EMAIL PROTECTED] writes:

   LW One wants to coin a word like Qlass.  Unfortunately qlass is
   LW too easy to misread as glass.  Oy veh, I'm getting notions of
   LW the qlass is half empty for a partially instantiated object.
 
 [EMAIL PROTECTED],
 
 i think you need some immediate mental help. please step back from the
 keyboard before you commit such a sin again. the next time, i will ask
 gloria to stick you with a knitting needle.
 
 is the smiley :) or (: ?

I can't believe you missed the opportunity to write qloria.

-- c



Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread chromatic
On Wed, 2005-10-26 at 21:58 -0400, Rob Kinyon wrote:

 Plus, the argument is a straw man. Instead of:
 
 class Some::Class is also {
 }
 
 you would do:
 
 class My::Version {
 does Some::Class;
 }
 
 Problem solved.

Don't forget the fun of modifying all existing uses of Some::Class to
use My::Version instead, if that's even possible.

-- c



Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread Larry Wall
On Wed, Oct 26, 2005 at 07:35:05PM -0700, chromatic wrote:
: On Wed, 2005-10-26 at 21:58 -0400, Rob Kinyon wrote:
: 
:  Plus, the argument is a straw man. Instead of:
:  
:  class Some::Class is also {
:  }
:  
:  you would do:
:  
:  class My::Version {
:  does Some::Class;
:  }
:  
:  Problem solved.
: 
: Don't forget the fun of modifying all existing uses of Some::Class to
: use My::Version instead, if that's even possible.

That should mostly be handled by virtualized class names.

Larry


Re: Roles vs. Classes (was Re: Ways to add behavior)

2005-10-26 Thread Luke Palmer
On 10/26/05, Rob Kinyon [EMAIL PROTECTED] wrote:
 What about:

 class Foo is also {
 method foo() { ... }
 }

 Where the second foo() is no longer what the first foo() did.

Just overwrite the vtable.

 Furthermore, let's say you have:

 class Bar isa Foo {
 method floober() { ... }
 }

 If they were roles, then role Bar could alias all the methods it
 inherits from role Foo. In other words, it can cache all the method
 lookups at compile-time. That's a substantial savings. If they're open
 classes, the runtime has to throw out all the cached lookups the
 moment any of the classes upstream are modified.

This one is a little better.  It is expensive to rejig all the cached
methods, but that expense comes at the time when you reopen.  If you
never reopen, you never pay a penalty.

 Plus, the argument is a straw man. Instead of:

 class Some::Class is also {
 }

 you would do:

 class My::Version {
 does Some::Class;
 }

 Problem solved.

Unless your module is the one creating the Some::Classes, or unless
(as you point out above) there are existing subclasses of Some::Class,
or unless some other thing that you didn't think of, which is the
whole point of this discussion.  There is no omniscient library
writer; there is no omniscient language designer.  :-)

Luke


Re: Ways to add behavior

2005-10-25 Thread Larry Wall
On Mon, Oct 24, 2005 at 06:33:20AM -0700, Ashley Winters wrote:
: # behavior through prototype -- guessing realistic syntax
: Base.meta.add_method(
: do_it = method ($arg) {
: say doing $arg!;
: });
: 
: 
: # or, just add it to a single instance
: $x.meta.add_method(
: do_it = method ($arg) {
: say doing $arg!;
: });

I don't have a comment on your actual question, but I'd like to use
this opportunity to point out the symmetry of Base and $x at this
point, and the fact that .meta can't simply call .add_method in the
metaclass, or it would lose track of the original invocant, which is
needed to convey both class and instance information.  I'm not sure
it's even possible to say

$m = $x.meta;
$m.addmethod($arg);

The only way that can work is if $x.meta returns a shadow class that
is prebound only to $x.  (Though that might explain how .addmethod
knows it's only adding a method to the object.)

In the absence of that, what's going on seems more like

$x.META::addmethod($arg);

where META:: is smart enough to dispatch to the proper metaclass without
throwing away the invocant, and then the metaclass decides what to do
based on the instancehood of $x.

Larry


Re: Ways to add behavior

2005-10-25 Thread Stevan Little

Larry,

On Oct 25, 2005, at 4:37 PM, Larry Wall wrote:

On Mon, Oct 24, 2005 at 06:33:20AM -0700, Ashley Winters wrote:
: # behavior through prototype -- guessing realistic syntax
: Base.meta.add_method(
: do_it = method ($arg) {
: say doing $arg!;
: });
:
:
: # or, just add it to a single instance
: $x.meta.add_method(
: do_it = method ($arg) {
: say doing $arg!;
: });

I don't have a comment on your actual question, but I'd like to use
this opportunity to point out the symmetry of Base and $x at this
point, and the fact that .meta can't simply call .add_method in the
metaclass, or it would lose track of the original invocant, which is
needed to convey both class and instance information.  I'm not sure
it's even possible to say

$m = $x.meta;
$m.addmethod($arg);

The only way that can work is if $x.meta returns a shadow class that
is prebound only to $x.  (Though that might explain how .addmethod
knows it's only adding a method to the object.)


This is actually the principe behind the Ruby style singleton methods  
(the shadow class), it basically creates an anon-class which inherits  
from $x's original class, then it rebinds/blesses $x into the anon- 
class. It is very simple really :)


As for if this is/should be accessible through .meta, i am not sure  
that is a good idea. The reason being is that .meta brings with it  
the idea of metaclasses, which then relates to classes, and so now  
the user is thinking they are accessing the metaclass of the class of  
which $x is an instance.


I would suggest instead that we have a method, which is found in  
Object which allows instances to add methods to themselves (and only  
themselves). In Ruby this is called 'add_singleton_method' or  
something like that. I use that same name in the metamodel prototype  
too.



In the absence of that, what's going on seems more like

$x.META::addmethod($arg);

where META:: is smart enough to dispatch to the proper metaclass  
without

throwing away the invocant, and then the metaclass decides what to do
based on the instancehood of $x.


I am not sure I like this for 2 reasons.

1) META:: smells like ::SUPER, and that feels like re-dispatching to  
me, which is not really what we need to be doing.


2) there is not need to send this back to the metaclass level. The  
whole thing could be accomplished as an instance method of Object.  
Here is how it could be done.


class ShadowClass does Class {}

class Object is reopened {
method add_singleton_method (Str $label, Method $method) {
if ($?SELF.class.class != ShadowClass) {
my $shadow = ShadowClass.new();
$shadow.meta.superclasses([ $shadow ]);
$?SELF.class = $shadow;
}
$?SELF.class.meta.add_method($label, $method);
}
}

Stevan