Re: enums and bitenums

2003-12-13 Thread Andy Wardley
Larry Wall wrote:
 Well, we can't use - because we're using that for something else.
 But it's certainly true that we'll have to have some mechanism for
 disambiguating Color.green from Blackberry.green.  After all,
 
 Blackberry.green == Color.red
 
 Or maybe it's
 
 Blackberry::green == Color::red

[...]

 I don't know the syntax for
 disambiguating on the green end yet.  Maybe one of
 
 $foo ~~ Color::green
 $foo ~~ Color.green
 $foo ~~ Color[green]
 
 Or maybe something else.

How about a single colon?

 Color:green 

This is the same syntax employed in XML namespaces and URIs, for example:

xml xmlns:color=http://example.com/xml/color.xsd;
  color:green/
/xml

Don't tell me, we can't use : because we're using that for something
else.  :-)

Presumably, the parser could be smart enough to entuit the 
role on either side of a comparison if the other is specified.

   $foo:Color ~~ Color:green

   $foo ~~ Color:green  # assumes $foo:Color

   $foo:Color ~~ green  # assumes Color:green

 I'm thinking the ordinary method
 
 $foo.Color
 
 implies
 
 $foo.as(Color)

What if your $foo object has a regular method called Color?  Would it 
get called in preference?

A



Re: enums and bitenums

2003-12-13 Thread Paul Hodges

--- Larry Wall [EMAIL PROTECTED] wrote:
 On Fri, Dec 12, 2003 at 03:10:30PM -0800, Paul Hodges wrote:
 : Ok, wait a sec. Does that mean different references to the same
 : critter can have differing sets of aspects?
 : 
 : my Dog $Spot;
 : my $doggie = Dog.new();
 : my $meandog  = \$doggie.as(AttackDog);
 : my $nicedog  = \$doggie.as(LapDog);

Forgive me, I'm trying to get accustomed to the new syntax, so let me
rewrite

 : if $me.away {
 : if $visitor.nephew {
 :$Spot = $nicedog; 
 : } else {
 :$Spot = $meandog; 
 : }
 : }

as

  $Spot = $visitor.nephew ?? $nicedog :: $meandog;

Which brings up a small side note: that's a successfully applied
boolean context for $visitor.nephew, right?

 : Now, if I'm away and someone show up, I presume that if it's my
 : nephew then $Spot.seeVisitor() will invoke the LapDog role's .wag()
 : method, but otherwise I expect it to invoke the AttackDog role's
 : .Bark() method. I realize there are other ways to get here
 : but would this *work*???
 
 We might be able to make it work, though as you say, there are other
 ways to get there, and the chances are that at least one of them will
 be a better way.

lol -- yeah. This is the kind of code I find six months after writing
it and wonder what sort of delerium I was suffering that day. 

So what exactly does it mean to have a typed reference? $meandog
still a Dog, just using an AttackDog role, right? So it's type is
DogAttackDog? Inheritance thinking starts crowding in here and
blurring my understanding of what's going on.

 Certainly when the Dog object's class is composed, it
 will have to do something about the conflicting .seeVisitor methods
 in the two roles. 

Ah! The class has to reconcile the roles used to build it.
That would cause the same conflict between AttackDog.Bark() and
LapDog.Bark(), if each had one, but that certainly falls back to a
matter of design, and that there are better ways to build it.

I wish I had generated a better example, but for the sake of
consistency, I'll work with what we've already got, so how about
predefining defaults to resolve known conflicts?

   class Dog does LapDog {...};
   Dog.bark is default(LapDog); # I lowercased .bark() here
   class Dog does AttackDog;

   my Dog $Spot = Dog.new();
   $Spot.bark(); # yip, yip
   $Spot.AttackDog.bark();   # sick 'em!

I just noticed I had uppercased my method(s), and it was annoying me.
Anyway, that syntax looks really freaky to me. I can look at it and
know what it was *meant* to do, but how would it be implemented?
  
  Dog.bark but= LapDog;

didn't look any better, though. :(
Obviously I'm not awake yet, but maybe these rambles will be useful to
somebody?

 It might well be better to encode that choice as
 part of the dog's state rather than in the references to it. 

I'd say that was almost guaranteed to be the better way to go in
practice. I've just seen too many cases where I was handed poorly
designed legacy code and expected to hack it into some new
functionality, oh and we need that by three today? 

My workplace considers refactoring to be reinventing the wheel. Just
add another motor and axle over here!! sheesh, lol

 On the other hand, it might just fall out of our implementation
 that it does the right thing with typed references, if the method
 dispatch to the conflicting methods in the Dog class can have access
 to the reference types to break ties.

And since the type of the ref could be DogLapDogAttackDogPet, that
should work. :)

 : And btw, just a refresher on this assigning a ref thing -- would
 : the syntax have to change at *all*?
 
 Dunno.  I don't see anything obviously wrong with it, but then I
 never could see very well...

Yeah, right. :)

 Larry

Paul

__
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/


RE: enums and bitenums

2003-12-13 Thread Austin Hastings


 -Original Message-
 From: Larry Wall [mailto:[EMAIL PROTECTED]
 Sent: Friday, December 12, 2003 7:39 PM
 To: Perl6
 Subject: Re: enums and bitenums


 On Fri, Dec 12, 2003 at 03:10:30PM -0800, Paul Hodges wrote:
 : Ok, wait a sec. Does that mean different references to the same critter
 : can have differing sets of aspects?
 :
 : my Dog $Spot;
 : my $doggie = Dog.new();
 : my $meandog  = \$doggie.as(AttackDog);
 : my $nicedog  = \$doggie.as(LapDog);
 : if $me.away {
 : if $visitor.nephew {
 :$Spot = $nicedog;
 : } else {
 :$Spot = $meandog;
 : }
 : }
 :
 : Now, if I'm away and someone show up, I presume that if it's my nephew
 : then $Spot.seeVisitor() will invoke the LapDog role's .wag() method,
 : but otherwise I expect it to invoke the AttackDog role's .Bark()
 : method. I realize there are other ways to get here but would this
 : *work*???

 We might be able to make it work, though as you say, there are other
 ways to get there, and the chances are that at least one of them will
 be a better way.  Certainly when the Dog object's class is composed, it
 will have to do something about the conflicting .seeVisitor methods
 in the two roles.

Hmm. What does that do for run-time behavior?

If you have to worry about (essentially) every possible role's namespace
conflicting with every other, the whole thing risks getting less useful
quickly.

 It might well be better to encode that choice as
 part of the dog's state rather than in the references to it.

Treat 'em as a stack. Last one applied dominates. But make sure there's a
way to unstack the roles when finished.

 On the
 other hand, it might just fall out of our implementation that it does
 the right thing with typed references, if the method dispatch to
 the conflicting methods in the Dog class can have access to the reference
 types to break ties.

That's cool.




RE: enums and bitenums

2003-12-13 Thread Austin Hastings


 -Original Message-
 From: Luke Palmer [mailto:[EMAIL PROTECTED]
 Sent: Saturday, December 13, 2003 9:30 AM
 To: Andy Wardley; Larry Wall; Perl6; [EMAIL PROTECTED]
 Subject: Re: enums and bitenums
 
 
 Andy Wardley writes:
  Larry Wall wrote:
   Well, we can't use - because we're using that for something else.
   But it's certainly true that we'll have to have some mechanism for
   disambiguating Color.green from Blackberry.green.  After all,
   
   Blackberry.green == Color.red
   
   Or maybe it's
   
   Blackberry::green == Color::red
  
  [...]
  
   I don't know the syntax for
   disambiguating on the green end yet.  Maybe one of
   
   $foo ~~ Color::green
   $foo ~~ Color.green
   $foo ~~ Color[green]
   
   Or maybe something else.
  
  How about a single colon?
  
   Color:green 
 
  This is the same syntax employed in XML namespaces and URIs, 
 for example:
  
  xml xmlns:color=http://example.com/xml/color.xsd;
color:green/
  /xml
  
  Don't tell me, we can't use : because we're using that for something
  else.  :-)
 
 Well, yes.  It's used in the operator position already for the indirect
 object syntax, so I don't think that'll fly.


Also, as Larry pointed out there's likely to be the need to talk about multiple values.
Color[green|red] is better in a lot of ways than Color::green|Color::red.


 Keeping with the color example, let's think about what this is doing:
 
 $foo ~~ green
 
 That ought to work even if you set green by saying:
 
 $foo.Color = (0,1,0);
 
 So it seems more that green is doubling as a predicate and a value.
 Indeed, you could think of setting something to green as setting it to
 pure green (0,1,0), but testing green as anything that looks
 greenish - $r,$g,$b { $g  $r + $b }.
 
 Maybe it's a subtype[1] of the property with a default value?
 
 That gets me thinking about how to declare that.  If a subtype is like a
 parameter to the class that the class didn't really declare, I could
 imagine a syntax like this:
 
 constraint Color[green] { $.g  $.r + $.b }
 
 That makes me woosy, though.  Maybe digging up the adverbial modifier
 Cwhere should stir some ideas.
 
 constraint green is Color { $.g  $.r + $.b }
 
 my Color where green $spinach;

I don't understand where you were going with that.

 Maybe we'd better leave that one buried.


Speaking of predicate/value mixups:

  role green 
does Color[$.g  $.r + $.b]
does {
  method .VALUE { return (0,1,0); }
};

Then:

  my Color $g = green;
  
  my Color $c = (random(), random(), random());

  if $c == $g {
print That's GREEN!;
  }
  elsif $c ~~ green {
print Well, it's greenish;
  }


 For some reason, subtypes don't feel like roles to me.  They're not so
 much behaviors are they are constraints... on behavior.  Like the
 opposite of roles, actually. 
 
 Oh, we were talking about enums, right?  Um.  Yeah. 
 
 Luke
 
 [1] There's a term to add to the vocab sheet.  AFAIK, a subtype is a
 variation on a normal type that has some constraint applied to it.
 Think vague.
 



Re: enums and bitenums

2003-12-13 Thread Larry Wall
On Sat, Dec 13, 2003 at 01:42:58PM +, Andy Wardley wrote:
: How about a single colon?
: 
:  Color:green 

Vaguely possible, but the lexer would have to distinguish

Color:green
Color: green
Color :green

It may yet do that, but probably not for this reason.

: This is the same syntax employed in XML namespaces and URIs, for example:
: 
: xml xmlns:color=http://example.com/xml/color.xsd;
:   color:green/
: /xml
: 
: Don't tell me, we can't use : because we're using that for something
: else.  :-)

Depends on how we treat whitespace, and whether : becomes part of
the name.

: Presumably, the parser could be smart enough to entuit the 
: role on either side of a comparison if the other is specified.
: 
:$foo:Color ~~ Color:green
: 
:$foo ~~ Color:green  # assumes $foo:Color
: 
:$foo:Color ~~ green  # assumes Color:green

I want more than that.  I want

$foo ~~ green

to work, provided there's only one definition of green in scope.
That's why I'd like enums to have a mandatory type, so that they
can in fact act like subtypes.

:  I'm thinking the ordinary method
:  
:  $foo.Color
:  
:  implies
:  
:  $foo.as(Color)
: 
: What if your $foo object has a regular method called Color?  Would it 
: get called in preference?

Following the Traits paper's rule, if the class itself defines a
method Color, that takes precedence over any Color methods from roles.
But if the class merely inherits a Color method, the role would
override the inherited method.  That being said, I don't think the
situation would arise often in practice if people follow the custom
of naming normal methods in lowercase and classes/roles in uppercase.

Or we could go the other way, and say that, presuming it's known that Color
is a class/role name at compile time, .Color is forced to mean .as(Color)
instantly.  It could be argued that this doesn't work so well with run-time
properties.  But you can't name a property unless a declaration is in
scope to begin with.

Of course, we could also just completely ignore the fact that Color is
a class name if there's a dot in front of it, and force everyone to
say as(Color) if that's what they mean.  That makes the indirect object
syntax a little less useful.  Instead of

$bar = Color $foo:

you'd have to say the completely non-English-like

$bar = as $foo: Color

which is perhaps not a great loss if it encourages people to say

$bar = $foo.as(Color)

instead.

Hmm.  Now I'm thinking about the problem of expanding references in
list context, since by default a reference doesn't.  If you say

print $ref

it doesn't do what you want, but

print $ref.as(Array)

might work a lot better, though of course

print @$ref

does the same thing.  But suppose instead of $ref we have a big long
expression returning an array reference.  Then the .as() form becomes
much more readable.  So it might well be that all the prefix context
operators have .as() counterparts:

~($x)   $x.as(Str)
?($x)   $x.as(Bit)
+($x)   $x.as(Num)
int($x) $x.as(Int)
$($x)   $x.as(Scalar)
@($x)   $x.as(Array)
%($x)   $x.as(Hash)

Though .as() would probably have to be somewhat magical to get the
compiler's context analyzer to realize the context of $x in the way
that the prefix operators do.  (And of course it would have to punt
on that analysis if you say $x.as($y) or some such.)

Larry


Re: enums and bitenums

2003-12-13 Thread Larry Wall
On Sat, Dec 13, 2003 at 12:22:00PM -0500, Austin Hastings wrote:
:  We might be able to make it work, though as you say, there are other
:  ways to get there, and the chances are that at least one of them will
:  be a better way.  Certainly when the Dog object's class is composed, it
:  will have to do something about the conflicting .seeVisitor methods
:  in the two roles.
: 
: Hmm. What does that do for run-time behavior?
: 
: If you have to worry about (essentially) every possible role's namespace
: conflicting with every other, the whole thing risks getting less useful
: quickly.

But with the standard approach it merely seems like the whole thing
is still useful when in fact your semantics are already clobbered
but you just don't know it yet.  Better to find out sooner than later.

:  It might well be better to encode that choice as
:  part of the dog's state rather than in the references to it.
: 
: Treat 'em as a stack. Last one applied dominates. But make sure there's a
: way to unstack the roles when finished.

Accidental stacks considered harmful.  We're trying to get rid of the
accidental ones while preserving the ability to have intentional ones.

Larry


Re: enums and bitenums

2003-12-13 Thread Larry Wall
On Sat, Dec 13, 2003 at 07:16:21AM -0800, Paul Hodges wrote:
:   $Spot = $visitor.nephew ?? $nicedog :: $meandog;
: 
: Which brings up a small side note: that's a successfully applied
: boolean context for $visitor.nephew, right?

Yes, but $visitor.nephew is no longer .does(nephew) in my current view.
You have to say

$Spot = $visitor ~~ nephew ?? $nicedog :: $meandog;

if nephew is to do any kind of implicit subtype matching.  You can also
be explicit with .does(), of course.

:  : Now, if I'm away and someone show up, I presume that if it's my
:  : nephew then $Spot.seeVisitor() will invoke the LapDog role's .wag()
:  : method, but otherwise I expect it to invoke the AttackDog role's
:  : .Bark() method. I realize there are other ways to get here
:  : but would this *work*???
:  
:  We might be able to make it work, though as you say, there are other
:  ways to get there, and the chances are that at least one of them will
:  be a better way.
: 
: lol -- yeah. This is the kind of code I find six months after writing
: it and wonder what sort of delerium I was suffering that day. 
: 
: So what exactly does it mean to have a typed reference? $meandog
: still a Dog, just using an AttackDog role, right? So it's type is
: DogAttackDog? Inheritance thinking starts crowding in here and
: blurring my understanding of what's going on.

There are going to be some limits on what you can do.  We don't have
enough parallel universes to allow all uses of all junction types--in
the absence of quantum computing the combinatorics are not in our favor...

:  Certainly when the Dog object's class is composed, it
:  will have to do something about the conflicting .seeVisitor methods
:  in the two roles. 
: 
: Ah! The class has to reconcile the roles used to build it.
: That would cause the same conflict between AttackDog.Bark() and
: LapDog.Bark(), if each had one, but that certainly falls back to a
: matter of design, and that there are better ways to build it.
: 
: I wish I had generated a better example, but for the sake of
: consistency, I'll work with what we've already got, so how about
: predefining defaults to resolve known conflicts?
: 
:class Dog does LapDog {...};
:Dog.bark is default(LapDog); # I lowercased .bark() here
:class Dog does AttackDog;
: 
:my Dog $Spot = Dog.new();
:$Spot.bark(); # yip, yip
:$Spot.AttackDog.bark();   # sick 'em!
: 
: I just noticed I had uppercased my method(s), and it was annoying me.
: Anyway, that syntax looks really freaky to me. I can look at it and
: know what it was *meant* to do, but how would it be implemented?
:   
:   Dog.bark but= LapDog;
: 
: didn't look any better, though. :(
: Obviously I'm not awake yet, but maybe these rambles will be useful to
: somebody?

As a example of the problem with defaults, if nothing else.  :-)

:  It might well be better to encode that choice as
:  part of the dog's state rather than in the references to it. 
: 
: I'd say that was almost guaranteed to be the better way to go in
: practice. I've just seen too many cases where I was handed poorly
: designed legacy code and expected to hack it into some new
: functionality, oh and we need that by three today? 
: 
: My workplace considers refactoring to be reinventing the wheel. Just
: add another motor and axle over here!! sheesh, lol

With multis you can be refactoring while you're also adding motors
and axles.   :-)

:  On the other hand, it might just fall out of our implementation
:  that it does the right thing with typed references, if the method
:  dispatch to the conflicting methods in the Dog class can have access
:  to the reference types to break ties.
: 
: And since the type of the ref could be DogLapDogAttackDogPet, that
: should work. :)

Touché.

Larry


Re: enums and bitenums

2003-12-13 Thread Paul Hodges

--- Larry Wall [EMAIL PROTECTED] wrote:
 On Sat, Dec 13, 2003 at 07:16:21AM -0800, Paul Hodges wrote:
 :   $Spot = $visitor.nephew ?? $nicedog :: $meandog;
 : 
 : Which brings up a small side note: that's a successfully applied
 : boolean context for $visitor.nephew, right?
 
 Yes, but $visitor.nephew is no longer .does(nephew) in my current
 view. You have to say
 
 $Spot = $visitor ~~ nephew ?? $nicedog :: $meandog;
 
 if nephew is to do any kind of implicit subtype matching.  You can
 also be explicit with .does(), of course.

I knew that, lol -- but again, that's why I lurk here. I'm trying keep
my habits chasing the curve of whatever's being worked out.

 : So what exactly does it mean to have a typed reference? $meandog
 : still a Dog, just using an AttackDog role, right? So it's type is
 : DogAttackDog? Inheritance thinking starts crowding in here and
 : blurring my understanding of what's going on.
 
 There are going to be some limits on what you can do.  We don't have
 enough parallel universes to allow all uses of all junction types--in
 the absence of quantum computing the combinatorics are not in our
 favor...

Amen, brutha. Accordingly, do we have an idea what it actually means to
add a type to something? I mean, I get that we could say

  print yup if $Spot ~~ AttackDog;

but is there still

  print ref $Spot;

and if so what does it print???

 : Obviously I'm not awake yet, but maybe these rambles will be useful
 : to somebody?
 
 As a example of the problem with defaults, if nothing else.  :-)

lol -- hey, if I can be a bad example, at least my life has *some*
purpose. :)

 : My workplace considers refactoring to be reinventing the wheel.
 : Just add another motor and axle over here!! sheesh, lol
 
 With multis you can be refactoring while you're also adding motors
 and axles.   :-)

oooOoohh.. Hey! I *LOVE* that! :op



__
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/


Re: enums and bitenums

2003-12-13 Thread Larry Wall
On Sat, Dec 13, 2003 at 03:43:00PM -0800, Paul Hodges wrote:
: Amen, brutha. Accordingly, do we have an idea what it actually means to
: add a type to something? I mean, I get that we could say
: 
:   print yup if $Spot ~~ AttackDog;
: 
: but is there still
: 
:   print ref $Spot;
: 
: and if so what does it print???

It still prints Dog.  The current composition of the Dog class for this
object is largely anonymous.  If it has a name, it's something like
%Dog::__COMPOSITION__{AttackDog  Pet}.  But every dog thinks its a Dog.

Larry


Re: enums and bitenums

2003-12-12 Thread Andy Wardley
Larry Wall wrote:
 Anyway, this all implies that use of a role as a method name defaults to
 returning whether the type in question matches the subtype.  That is,
 when you say:
 
 $foo.true
 $bar.red
[...]
 $bar.red
[...]
 $baz.Byte
 
 it's asking whether the Int property fulfills the Byte constraint, but
 that's getting kind of strange.

If the roles are first class objects then their traits are defined
as methods, right?

Boolean.true($foo)
Color.red($bar)
Int.byte($baz)

Then assuming that certain objects inherit certain roles, you could
use something like the Perl 5 $self-SUPER::new() syntax.  Only it would
look more like this:

$foo-Boolean.true
$bar-Color.red
$baz-Int.byte

 Another implication is that, if properties are subtypes, we can't use
 the same name as a cast method.  Since
 
 $baz.Byte
 
 only returns true or false, we'd need something like (yuck)
 
 $baz.asByte
[...or...]
 $baz.as(Byte)

Or:
  $baz-Byte

That would make something like this:

  $foo-Color.red

the same kind of thing as:

  $foo.as(Color).red

A



Re: enums and bitenums

2003-12-12 Thread Eirik Berg Hanssen
Larry Wall [EMAIL PROTECTED] writes:

 On Thu, Dec 11, 2003 at 04:18:19PM -0700, Luke Palmer wrote:
 : Larry Wall writes:
 :  Anyway, this all implies that use of a role as a method name defaults to
 :  returning whether the type in question matches the subtype.

  Why?  Why should it be a method?  I would have though the smart
match operator would do the job better -- as well as be less painful
than the .does() method.  Hey, given that it removes the ambiguities,
I would call it less painful than use of a role as a method name.


 : If that's the case, how do we attach out-of-band properties on objects
 : that don't expect them, but only some of them (as was the original
 : intent for properties, IIRC):
 : 
 : my role onlyonced;
 : sub onlyonce($arg is rw) {
 : die onlyonce called twice on the same value if $arg.onlyonced;
 : $arg but= onlyonced;
 : }
 : 
 : Either that doesn't work at all, because you get an onlyonced not
 : found error, or it works because onlyonced is a declared role.  But
 : in the latter case I worry about namespace pollution.
 
 Okay, maybe I understand your worry now.  Are you worried that
 every object implicitly has boolean methods corresponding to every
 class/role/property name in scope?  I can see where that might
 cause some heartburn.

  ... and ditching those boolean methods might spare us those
heartburns.  What do we need them for, anyway, if the smart match
operator tests for out-of-band properties?

my role onlyonced;
sub onlyonce($arg is rw) {
die onlyonce called twice on the same value if $arg~~onlyonced;
$arg but= onlyonced;
}

  I for one would appreciate the visual clue that we access properties
and subclasses as roles ($foo~~bareword), while we access attributes
(with accessors) as methods ($foo.bareword).  Different things should
look different, right?


Eirik
-- 
[EMAIL PROTECTED]
  Just this .sig then
  nothing more


Re: enums and bitenums

2003-12-12 Thread Larry Wall
On Fri, Dec 12, 2003 at 04:05:25PM +0100, Eirik Berg Hanssen wrote:
: Larry Wall [EMAIL PROTECTED] writes:
: 
:  On Thu, Dec 11, 2003 at 04:18:19PM -0700, Luke Palmer wrote:
:  : Larry Wall writes:
:  :  Anyway, this all implies that use of a role as a method name defaults to
:  :  returning whether the type in question matches the subtype.
: 
:   Why?  Why should it be a method?  I would have though the smart
: match operator would do the job better -- as well as be less painful
: than the .does() method.  Hey, given that it removes the ambiguities,
: I would call it less painful than use of a role as a method name.

Having slept on it overnight, I've come to the same conclusion.

:  : If that's the case, how do we attach out-of-band properties on objects
:  : that don't expect them, but only some of them (as was the original
:  : intent for properties, IIRC):
:  : 
:  : my role onlyonced;
:  : sub onlyonce($arg is rw) {
:  : die onlyonce called twice on the same value if $arg.onlyonced;
:  : $arg but= onlyonced;
:  : }
:  : 
:  : Either that doesn't work at all, because you get an onlyonced not
:  : found error, or it works because onlyonced is a declared role.  But
:  : in the latter case I worry about namespace pollution.
:  
:  Okay, maybe I understand your worry now.  Are you worried that
:  every object implicitly has boolean methods corresponding to every
:  class/role/property name in scope?  I can see where that might
:  cause some heartburn.
: 
:   ... and ditching those boolean methods might spare us those
: heartburns.  What do we need them for, anyway, if the smart match
: operator tests for out-of-band properties?

And also, smart match is the right place to put dwimmery, not method lookup.

: my role onlyonced;
: sub onlyonce($arg is rw) {
: die onlyonce called twice on the same value if $arg~~onlyonced;
: $arg but= onlyonced;
: }
: 
:   I for one would appreciate the visual clue that we access properties
: and subclasses as roles ($foo~~bareword), while we access attributes
: (with accessors) as methods ($foo.bareword).  Different things should
: look different, right?

I still think that you can access the role itself as a method, but only
if it's really there.  In that case the different thing is trying to be
the same.  A simple property should behave like an attribute when it can.

Larry


Re: enums and bitenums

2003-12-12 Thread Larry Wall
On Fri, Dec 12, 2003 at 09:36:45AM +, Andy Wardley wrote:
: Larry Wall wrote:
:  Anyway, this all implies that use of a role as a method name defaults to
:  returning whether the type in question matches the subtype.  That is,
:  when you say:
:  
:  $foo.true
:  $bar.red
: [...]
:  $bar.red
: [...]
:  $baz.Byte
:  
:  it's asking whether the Int property fulfills the Byte constraint, but
:  that's getting kind of strange.
: 
: If the roles are first class objects then their traits are defined
: as methods, right?
: 
: Boolean.true($foo)
: Color.red($bar)
: Int.byte($baz)

Potentially, though roles are more properly thought of as types than classes.
That is, they're abstract sets of values.  You can instantiate one sufficiently
well to take a reference to it, so that you can do

$someobject but= $somerole;

But it's not really an object in its own right, and it's not clear that
you can call any of the methods it defines unless it's part of an object.

: Then assuming that certain objects inherit certain roles, you could
: use something like the Perl 5 $self-SUPER::new() syntax.  Only it would
: look more like this:
: 
: $foo-Boolean.true
: $bar-Color.red
: $baz-Int.byte

Well, we can't use - because we're using that for something else.
But it's certainly true that we'll have to have some mechanism for
disambiguating Color.green from Blackberry.green.  After all,

Blackberry.green == Color.red

Or maybe it's

Blackberry::green == Color::red

I'm not sure how subtypes are related to types yet, syntactically speaking.
Might even be

Blackberry[green] == Color[red]

:  Another implication is that, if properties are subtypes, we can't use
:  the same name as a cast method.  Since
:  
:  $baz.Byte
:  
:  only returns true or false, we'd need something like (yuck)
:  
:  $baz.asByte
: [...or...]
:  $baz.as(Byte)
: 
: Or:
:   $baz-Byte
: 
: That would make something like this:
: 
:   $foo-Color.red
: 
: the same kind of thing as:
: 
:   $foo.as(Color).red

I'm thinking the ordinary method

$foo.Color

implies

$foo.as(Color)

meaning that we're viewing $foo through the Color filter.  If you want to
match against a value, however, you'd have to say

$foo.Color == green

or

$foo.Color ~~ green

In the latter case, you can just say

$foo ~~ green

as long as green is unambiguous.  I don't know the syntax for
disambiguating on the green end yet.  Maybe one of

$foo ~~ Color::green
$foo ~~ Color.green
$foo ~~ Color[green]

Or maybe something else.

The interesting question to me is what

$ref = \$foo.as(Color);

returns.  It looks like a typed reference to me, but it's still
a reference to the object in $foo, or can behave as one somehow.
I don't think it should generate a reference to the bare role, because
roles aren't intended to be first class objects (though you can force
them to be, I think).  Roles are supposed to encapsulate abstractions
without implying objecthood.  I think roles are a little bit like
quarks--they're fine in theory, but it's scary to have loose ones
floating around.

So it seems to me that $foo.Color has to return some kind of typed ref
to $foo, so that things like

$foo.Color = purple;

can work as expected.  Staring at that, it seems apparent that .Color
is simply an lvalue subroutine just like any other rw attribute.  An
lvalue sub can be thought of as a typed reference, I suppose.  It gets
more interesting if the role has multiple attributes though.  What
would

\$foo.RGB

return, I wonder, such that

$foo.RGB = ($r,$g,$b)

would work?

Larry


RE: enums and bitenums

2003-12-12 Thread Austin Hastings


 -Original Message-
 From: Larry Wall [mailto:[EMAIL PROTECTED]
 Sent: Thursday, December 11, 2003 1:04 PM

 [Warning: speculation ahead.]

Noted.

 I've been thinking that enums might just be subtypes of roles/properties.
 After all, when you say

 0 but true

 it might really mean

 0 but Boolean[1]

 whereas

 1 but false

 means

 1 but Boolean[0]

 That is, type boolean can be thought of as enum(false,true).

 So we might have a role declaration somewhere that says something like:

 role *Boolean[Bit ?$val] does Property {
   bit $.boolean = $val;
 }
 role *false does Boolean[0];
 role *true does Boolean[1];

 That's what the semantics might look like, but of course people would
 probably want an enum or bitenum wrapper macro for real code.  No reason
 it couldn't be a standard macro though.  Or even part of the
 grammar--we've
 never shied away from defining one construct in terms of another for
 teaching purposes.  We define Cuse in terms of CBEGIN and Crequire,
 and Crequire in terms of Cdo.  Perl 6 will do more of that, because
 it makes things easy to learn.


Supertypes, eh? An enum is a limited-range thingy (int, usually), which fits
the description of a role, but also has magic words involved.

  package RGB;

  enum Color does Int[0..0xFF_FF_FF] {
has $Red   = 0xFF_00_00;
has $Green = 0x00_FF_00;
has $Blue  = 0x00_00_FF;
  }

Since the possible values are possibles, I don't like Chas unless we
provide that Chas means possible value in an enum-decl.

Is Cenum a primitive type only?

Or can we enumerate objects? As in,

  class RGB {
has byte $.red;
has byte $.green;
has byte $.blue;
  }

  enum Color does RGB {
has $Red= RGB[red = 0xFF, blue = 0x00, green = 0x00];
has $Green  = RGB[red = 0xFF, blue = 0x00, green = 0x00];  # Squares
mean compile time (const)?
has $Blue   = RGB[red = 0xFF, blue = 0x00, green = 0x00];
  }


 A lot of this is negotiable, but I think it's a feature that you
 can't have an enum without it being associated with a unique type
 name/property.  It's also appealing to me that enum values live
 in the type namespace, since they're really subtypes (that is, types
 that restrict values ranges of real types).  There's nothing says
 a subtype has to have only one value:

 role Bit[Int ?$val] does Int[0|1];

 Of course, I'm handwaving a lot here by using a junction.  For
 integer subtypes you'd typically want a range:

 role Byte[Int ?$val] does Int[0..255];

I don't understand the purpose of your [Int ?$val] parameter. Doesn't the
Cdoes Int[0..255] declare the constraint entirely?

   role PHB does Employee[$.job_title == manager  $.experience  5];



 That implies that the argument to Int[] has to be able to take a range.
 I confess I don't know what the real declaration of Int looks like
 yet.  Certainly the first arg isn't simply an Int.  That only works
 for enums. The arg has to represent some kind of generic constraint.
 Pity the optimizer...

  macro does is parsed(/ class [ given_block ] /) {...}

 Anyway, this all implies that use of a role as a method name defaults to
 returning whether the type in question matches the subtype.  That is,
 when you say

 $foo.true

 it's asking whether the Boolean property fulfills the true constraint.
 When you say

 $bar.red

 it's asking whether the Color property fulfills the red constraint.
 I suppose when you say

 $baz.Byte

 it's asking whether the Int property fulfills the Byte constraint, but
 that's getting kind of strange.

This is bad. Better to treat a role as a matchable constraint, and ask:

  if $foo ~~ true {...}

  given $bar { when red {...}}

  unless $baz ~~ Byte {...}

We've already got a constraint matching syntax. But for cases where you want
to be explicit, or when you risk confusion using ~~, we can recycle Cdoes
somehow:


  if $foo.does(true)
or
  if $foo.can(true)
or
  if $foo.would(true)
or

   role ChuckWood does WoodChuck[does .chuck(Wood)];   # Internal Cdoes
for has-method-p?

   my $how_much is Quantity of Wood = $woodchuck.can_chuck if
$woodchuck.could(ChuckWood)

(Sorry)

 Another implication is that, if properties are subtypes, we can't use
 the same name as a cast method.  Since

 $baz.Byte

 only returns true or false, we'd need something like (yuck)

 $baz.asByte

 Since class names are valid as bare names, perhaps we can improve
 that to

 $baz.as(Byte)

 (That doesn't mean you have to write an as method that contains a
 switch.  More likely as is a multi method within the class of $baz.)

Ugh.

UghUgh.

If a role is just a constraint, then there's no need to have a method at
all -- the type doesn't change.

  role FitsInByte does Int[0..255];

  my Byte $b;
  my Int  $i;

  $b = $i if $i ~~ FitsInByte;

Which leaves the .as() method for conversions:

  role ClassByte does Class[Byte];
  multi method Int::as(Int $i: ClassByte) returns Byte { $i % 256; }

  my Byte $b = 

RE: enums and bitenums

2003-12-12 Thread Austin Hastings


 -Original Message-
 From: Larry Wall [mailto:[EMAIL PROTECTED]
 Sent: Friday, December 12, 2003 1:44 PM



 Potentially, though roles are more properly thought of as types
 than classes.
 That is, they're abstract sets of values.  You can instantiate
 one sufficiently
 well to take a reference to it, so that you can do

 $someobject but= $somerole;

 But it's not really an object in its own right, and it's not clear that
 you can call any of the methods it defines unless it's part of an object.

Presumably it will share whatever behavior Classes use to provide static
methods?

 : Then assuming that certain objects inherit certain roles, you could
 : use something like the Perl 5 $self-SUPER::new() syntax.  Only it would
 : look more like this:
 :
 : $foo-Boolean.true
 : $bar-Color.red
 : $baz-Int.byte

 Well, we can't use - because we're using that for something else.
 But it's certainly true that we'll have to have some mechanism for
 disambiguating Color.green from Blackberry.green.  After all,

 Blackberry.green == Color.red

 Or maybe it's

 Blackberry::green == Color::red

 I'm not sure how subtypes are related to types yet, syntactically
 speaking.
 Might even be

 Blackberry[green] == Color[red]

This syntax suggests a javascript-like similarity between classes (or
objects) and arrays. Do you want that?
Perhaps pretending hashiness would be truer to both Perl's roots and the
syntax used to construct things:

  my member_function = \Class{memberfunction};

  Blackberry{green} == Color{green}


 :  Another implication is that, if properties are subtypes, we can't use
 :  the same name as a cast method.  Since
 : 
 :  $baz.Byte
 : 
 :  only returns true or false, we'd need something like (yuck)
 : 
 :  $baz.asByte
 : [...or...]
 :  $baz.as(Byte)
 :
 : Or:
 :   $baz-Byte
 :
 : That would make something like this:
 :
 :   $foo-Color.red
 :
 : the same kind of thing as:
 :
 :   $foo.as(Color).red

 I'm thinking the ordinary method

 $foo.Color

 implies

 $foo.as(Color)

 meaning that we're viewing $foo through the Color filter.  If you want to
 match against a value, however, you'd have to say

 $foo.Color == green

 or

 $foo.Color ~~ green

 In the latter case, you can just say

 $foo ~~ green

 as long as green is unambiguous.  I don't know the syntax for
 disambiguating on the green end yet.  Maybe one of

 $foo ~~ Color::green
 $foo ~~ Color.green
 $foo ~~ Color[green]

 Or maybe something else.

 The interesting question to me is what

 $ref = \$foo.as(Color);

 returns.

I'll suggest:

  $ref = \$foo.as(Color);

be the same as:

  $ref = \$foo;
  $ref but= of Color; # Cof affects type assumptions, doesn't merely add
stuff.

So that $ref is typechecked as a Color, not as a Foo.

 It looks like a typed reference to me, but it's still
 a reference to the object in $foo, or can behave as one somehow.
 I don't think it should generate a reference to the bare role, because
 roles aren't intended to be first class objects (though you can force
 them to be, I think).  Roles are supposed to encapsulate abstractions
 without implying objecthood.  I think roles are a little bit like
 quarks--they're fine in theory, but it's scary to have loose ones
 floating around.

 So it seems to me that $foo.Color has to return some kind of typed ref
 to $foo, so that things like

 $foo.Color = purple;

 can work as expected.  Staring at that, it seems apparent that .Color
 is simply an lvalue subroutine just like any other rw attribute.  An
 lvalue sub can be thought of as a typed reference, I suppose.  It gets
 more interesting if the role has multiple attributes though.  What
 would

 \$foo.RGB

 return, I wonder, such that

 $foo.RGB = ($r,$g,$b)

 would work?

 Larry



Re: enums and bitenums

2003-12-12 Thread Paul Hodges
Larry said:
 The interesting question to me is what
 
 $ref = \$foo.as(Color);
 
 returns.  It looks like a typed reference to me, but it's still
 a reference to the object in $foo, or can behave as one somehow.
 I don't think it should generate a reference to the bare role,
 because roles aren't intended to be first class objects (though
 you can force them to be, I think).  Roles are supposed to
 encapsulate abstractions without implying objecthood.  I think
 roles are a little bit like quarks--they're fine in theory, but
 it's scary to have loose ones floating around.

Ok, wait a sec. Does that mean different references to the same critter
can have differing sets of aspects?

my Dog $Spot;
my $doggie = Dog.new();
my $meandog  = \$doggie.as(AttackDog);
my $nicedog  = \$doggie.as(LapDog);
if $me.away {
if $visitor.nephew {
   $Spot = $nicedog; 
} else {
   $Spot = $meandog; 
}
}

Now, if I'm away and someone show up, I presume that if it's my nephew
then $Spot.seeVisitor() will invoke the LapDog role's .wag() method,
but otherwise I expect it to invoke the AttackDog role's .Bark()
method. I realize there are other ways to get here but would this
*work*???

And btw, just a refresher on this assigning a ref thing -- would the
syntax have to change at *all*?


__
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/


Re: enums and bitenums

2003-12-12 Thread Smylers
Larry Wall writes:

 I think roles are a little bit like quarks--they're fine in theory,
 but it's scary to have loose ones floating around.

Wow.

(And please can whoever looks after the quote of the day on Perl.com add
that one to the hopper ...)

Smylers



Re: enums and bitenums

2003-12-12 Thread Eirik Berg Hanssen
Larry Wall [EMAIL PROTECTED] writes:

 On Fri, Dec 12, 2003 at 04:05:25PM +0100, Eirik Berg Hanssen wrote:

 :   I for one would appreciate the visual clue that we access properties
 : and subclasses as roles ($foo~~bareword), while we access attributes
 : (with accessors) as methods ($foo.bareword).  Different things should
 : look different, right?
 
 I still think that you can access the role itself as a method, but only
 if it's really there.  In that case the different thing is trying to be
 the same.  A simple property should behave like an attribute when it can.

  When I wrote that, I still had in mind the boolean methods
corresponding to every class/role/property name in scope -- but I
think you mean something else when you speak of accessing the role.
Specifically, I think you mean what I would call accessing the role's
(main) attribute.  If so, we are still in agreement.  If not, I am
very much confused. :-)

  Red and Reddish (per your example) are not properties, given your
definition in the other thread.  So you are not arguing for Red and
Reddish to be accessible as methods, I gather.

  I can see this, I suppose:

$bar but= $foo.Color if $foo ~~ Color;
if $bar ~~ Reddish {
print $bar.hex_code; # hex_code is a method of the role,
 # and so can be accessed directly.

$bar.Color.red = 0;  # red is not a method of the role,
 # and must be accessed through the
 # role's main attribute (for which
 # red is an lvalue method, it seems).
}

  But this would all come about because the role defines an attribute
by the same name, not because method lookup scans the role namespace.
Or so I would hope.

  And then it is no different from being able to access as a method
any public attribute (or other method) that the role defines -- if the
role is really there.

  Or am I very much confused?


Eirik
-- 
Rudolph is at _least_ as real as a Cantor set or an untried recipe.
-- Joshua W. Burton [EMAIL PROTECTED]
([EMAIL PROTECTED])


Re: enums and bitenums

2003-12-12 Thread Larry Wall
On Fri, Dec 12, 2003 at 10:30:06PM +0100, Eirik Berg Hanssen wrote:
: Larry Wall [EMAIL PROTECTED] writes:
: 
:  On Fri, Dec 12, 2003 at 04:05:25PM +0100, Eirik Berg Hanssen wrote:
: 
:  :   I for one would appreciate the visual clue that we access properties
:  : and subclasses as roles ($foo~~bareword), while we access attributes
:  : (with accessors) as methods ($foo.bareword).  Different things should
:  : look different, right?
:  
:  I still think that you can access the role itself as a method, but only
:  if it's really there.  In that case the different thing is trying to be
:  the same.  A simple property should behave like an attribute when it can.
: 
:   When I wrote that, I still had in mind the boolean methods
: corresponding to every class/role/property name in scope -- but I
: think you mean something else when you speak of accessing the role.
: Specifically, I think you mean what I would call accessing the role's
: (main) attribute.  If so, we are still in agreement.  If not, I am
: very much confused. :-)
: 
:   Red and Reddish (per your example) are not properties, given your
: definition in the other thread.  So you are not arguing for Red and
: Reddish to be accessible as methods, I gather.

Not any more.

:   I can see this, I suppose:
: 
: $bar but= $foo.Color if $foo ~~ Color;
: if $bar ~~ Reddish {
: print $bar.hex_code; # hex_code is a method of the role,
:  # and so can be accessed directly.
: 
: $bar.Color.red = 0;  # red is not a method of the role,
:  # and must be accessed through the
:  # role's main attribute (for which
:  # red is an lvalue method, it seems).
: }
: 
:   But this would all come about because the role defines an attribute
: by the same name, not because method lookup scans the role namespace.
: Or so I would hope.

Yes.

:   And then it is no different from being able to access as a method
: any public attribute (or other method) that the role defines -- if the
: role is really there.
: 
:   Or am I very much confused?

No, I don't think you're confused.  Of course, I could be confused
about that...

Larry


Re: enums and bitenums

2003-12-12 Thread Larry Wall
On Fri, Dec 12, 2003 at 03:10:30PM -0800, Paul Hodges wrote:
: Ok, wait a sec. Does that mean different references to the same critter
: can have differing sets of aspects?
: 
: my Dog $Spot;
: my $doggie = Dog.new();
: my $meandog  = \$doggie.as(AttackDog);
: my $nicedog  = \$doggie.as(LapDog);
: if $me.away {
: if $visitor.nephew {
:$Spot = $nicedog; 
: } else {
:$Spot = $meandog; 
: }
: }
: 
: Now, if I'm away and someone show up, I presume that if it's my nephew
: then $Spot.seeVisitor() will invoke the LapDog role's .wag() method,
: but otherwise I expect it to invoke the AttackDog role's .Bark()
: method. I realize there are other ways to get here but would this
: *work*???

We might be able to make it work, though as you say, there are other
ways to get there, and the chances are that at least one of them will
be a better way.  Certainly when the Dog object's class is composed, it
will have to do something about the conflicting .seeVisitor methods
in the two roles.  It might well be better to encode that choice as
part of the dog's state rather than in the references to it.  On the
other hand, it might just fall out of our implementation that it does
the right thing with typed references, if the method dispatch to
the conflicting methods in the Dog class can have access to the reference
types to break ties.

: And btw, just a refresher on this assigning a ref thing -- would the
: syntax have to change at *all*?

Dunno.  I don't see anything obviously wrong with it, but then I never
could see very well...

Larry


enums and bitenums

2003-12-11 Thread Stéphane Payrard
Hi,

I don't remember anything about enums and bitenums in the
apocalypses. This is probably not very difficult to roll out
something using macros but I feel that should belong to the
standard language.


--
  stef


Re: enums and bitenums

2003-12-11 Thread Larry Wall
On Thu, Dec 11, 2003 at 02:48:06PM +0100, Stéphane Payrard wrote:
: Hi,
: 
: I don't remember anything about enums and bitenums in the
: apocalypses. This is probably not very difficult to roll out
: something using macros but I feel that should belong to the
: standard language.

[Warning: speculation ahead.]

I've been thinking that enums might just be subtypes of roles/properties.
After all, when you say

0 but true

it might really mean

0 but Boolean[1]

whereas

1 but false

means

1 but Boolean[0]

That is, type boolean can be thought of as enum(false,true).

So we might have a role declaration somewhere that says something like:

role *Boolean[Bit ?$val] does Property {
bit $.boolean = $val;
}
role *false does Boolean[0];
role *true does Boolean[1];

That's what the semantics might look like, but of course people would
probably want an enum or bitenum wrapper macro for real code.  No reason
it couldn't be a standard macro though.  Or even part of the grammar--we've
never shied away from defining one construct in terms of another for
teaching purposes.  We define Cuse in terms of CBEGIN and Crequire,
and Crequire in terms of Cdo.  Perl 6 will do more of that, because
it makes things easy to learn.

A lot of this is negotiable, but I think it's a feature that you
can't have an enum without it being associated with a unique type
name/property.  It's also appealing to me that enum values live
in the type namespace, since they're really subtypes (that is, types
that restrict values ranges of real types).  There's nothing says
a subtype has to have only one value:

role Bit[Int ?$val] does Int[0|1];

Of course, I'm handwaving a lot here by using a junction.  For
integer subtypes you'd typically want a range:

role Byte[Int ?$val] does Int[0..255];

That implies that the argument to Int[] has to be able to take a range.
I confess I don't know what the real declaration of Int looks like
yet.  Certainly the first arg isn't simply an Int.  That only works
for enums. The arg has to represent some kind of generic constraint.
Pity the optimizer...

Anyway, this all implies that use of a role as a method name defaults to
returning whether the type in question matches the subtype.  That is,
when you say

$foo.true

it's asking whether the Boolean property fulfills the true constraint.
When you say

$bar.red

it's asking whether the Color property fulfills the red constraint.
I suppose when you say

$baz.Byte

it's asking whether the Int property fulfills the Byte constraint, but
that's getting kind of strange.

Another implication is that, if properties are subtypes, we can't use
the same name as a cast method.  Since

$baz.Byte

only returns true or false, we'd need something like (yuck)

$baz.asByte

Since class names are valid as bare names, perhaps we can improve
that to

$baz.as(Byte)

(That doesn't mean you have to write an as method that contains a
switch.  More likely as is a multi method within the class of $baz.)

Another possibility is that .Byte would have to be context sensitive.
In which case we have the small problem that

if $foo.boolean { print true } else { print false }

prints true even if $foo is 0.  You'd have to say

if +$foo.boolean { print true } else { print false }

to force a numeric context on the type.  (Or use $foo.true.)

Alternately, we use the type name as a cast always, and distinguish
the boolean test:

if $baz.does(Byte) { my $byte = $baz.Byte }

I kinda like that.

Since does is a generalization of isa, we probably need to generalize
smart matching to test does rather than isa for class/type names.

On the other hand, it'd be a major pain to have to write $foo.does(true).
I suppose a cast could return undef if it fails, which means that
$foo.true would return 1 or undef.  Except $foo.false would return 0 or
undef.  Urg.

I suspect the right solution from a linguistic point of view is to make it 
context sensitive but also make it easy to disambiguate.

Explicitly:

$bar.does(Color)# does $bar know how to be a Color?
$bar.as(Color)  # always cast to Color

Implicitly boolean:

$bar ~~ Color   # $bar.does(Color)
?$bar.Color # $bar.does(Color)
if $bar.Color   # if $bar.does(Color)

Implicitly non-boolean:

+$bar.Color # +$bar.as(Color)
~$bar.Color # ~$bar.as(Color)
$($bar.Color)   # $($bar.as(Color))
@($bar.Color)   # @($bar.as(Color))

Then $foo.true and $foo.false work as expected.  Still have to be careful
about ?$foo.boolean though.

Interestingly, we have

$foo = $bar.Color || 0xfff;

that is equivalent to

$foo = $bar.does(Color) ?? $bar.as(Color) :: 0xfff;

which means $foo could validly end up 0.  Of course, // gets there by
a different route:

$foo = $bar.Color // 0xfff;

means

$foo = defined($bar.as(Color)) ?? $bar.as(Color) :: 0xfff;

I think I'm happy with that.  Maybe.

Larry


Re: enums and bitenums

2003-12-11 Thread Michael Lazzaro
On Thursday, December 11, 2003, at 10:04 AM, Larry Wall wrote:
Explicitly:

$bar.does(Color)# does $bar know how to be a Color?
$bar.as(Color)  # always cast to Color
Implicitly boolean:

$bar ~~ Color   # $bar.does(Color)
?$bar.Color # $bar.does(Color)
if $bar.Color   # if $bar.does(Color)
Implicitly non-boolean:

+$bar.Color # +$bar.as(Color)
~$bar.Color # ~$bar.as(Color)
$($bar.Color)   # $($bar.as(Color))
@($bar.Color)   # @($bar.as(Color))


So Cas would be for casting, not coercion, right?

Suppose you have a class Foo, such that:

  class Foo does (Bar, Baz) {
  ...
  }
... or however that looks.  May I then presume that

$foo.Bar.zap# ($foo.as(Bar)).zap)

calls the method Czap of role CBar, with $foo as the invocant?

MikeL



Re: enums and bitenums

2003-12-11 Thread Luke Palmer
Larry Wall writes:
 Anyway, this all implies that use of a role as a method name defaults to
 returning whether the type in question matches the subtype.  That is,
 when you say
 
 $foo.true
 
 it's asking whether the Boolean property fulfills the true constraint.
 When you say
 
 $bar.red

So are you saying that, eg.

class Something does Color {...}
my Something $flib;

if $flib.red  { print Flib is red }
if $flib.true { print Should be an error before now }

Since Something doesn't Boolean, true would be a method not found
error? 

If that's the case, how do we attach out-of-band properties on objects
that don't expect them, but only some of them (as was the original
intent for properties, IIRC):

my role onlyonced;
sub onlyonce($arg is rw) {
die onlyonce called twice on the same value if $arg.onlyonced;
$arg but= onlyonced;
}

Either that doesn't work at all, because you get an onlyonced not
found error, or it works because onlyonced is a declared role.  But
in the latter case I worry about namespace pollution.

It's clear that I don't entirely understand all of this yet (er, as much
as there is to understand... yet).

Luke


Re: enums and bitenums

2003-12-11 Thread Larry Wall
On Thu, Dec 11, 2003 at 02:01:17PM -0800, Michael Lazzaro wrote:
: So Cas would be for casting, not coercion, right?
: 
: Suppose you have a class Foo, such that:
: 
:   class Foo does (Bar, Baz) {
:   ...
:   }
: 
: ... or however that looks.  May I then presume that
: 
: $foo.Bar.zap# ($foo.as(Bar)).zap)
: 
: calls the method Czap of role CBar, with $foo as the invocant?

Seems like that would be the case.

Larry


Re: enums and bitenums

2003-12-11 Thread Larry Wall
On Thu, Dec 11, 2003 at 04:18:19PM -0700, Luke Palmer wrote:
: Larry Wall writes:
:  Anyway, this all implies that use of a role as a method name defaults to
:  returning whether the type in question matches the subtype.  That is,
:  when you say
:  
:  $foo.true
:  
:  it's asking whether the Boolean property fulfills the true constraint.
:  When you say
:  
:  $bar.red
: 
: So are you saying that, eg.
: 
: class Something does Color {...}
: my Something $flib;
: 
: if $flib.red  { print Flib is red }
: if $flib.true { print Should be an error before now }
: 
: Since Something doesn't Boolean, true would be a method not found
: error? 

Well, true is perhaps a bad example, since everything is boolean one
way or another.  Built-in types inherit a true method that depends on the
actual value, not on a property.

: If that's the case, how do we attach out-of-band properties on objects
: that don't expect them, but only some of them (as was the original
: intent for properties, IIRC):
: 
: my role onlyonced;

That might need to be my property to get everything defaulted for
a property kind of role.  But maybe not.

: sub onlyonce($arg is rw) {
: die onlyonce called twice on the same value if $arg.onlyonced;
: $arg but= onlyonced;
: }
: 
: Either that doesn't work at all, because you get an onlyonced not
: found error, or it works because onlyonced is a declared role.

I think it works because it's declared, and because you're using it
in a boolean context, so it's not really testing the value of the
property, but it's presence.  The .onlyonced method merely tests
whether the object does onlyonced.

: But in the latter case I worry about namespace pollution.

Which namespace are you worried about polluting?  It seems to me that
restricting the name to a lexical namespace and to the current object is
about as good as you can get.  We're not polluting the class's namespace,
nor are we polluting the global namespace.  (Though there are times where
that's the right thing to do.)

Or are you thinking that you might want to apply a property more than
once to the same object?  (That would make about as much sense as
inheriting more than once directly from the same base class.)

Or are you worried that these have to be declared at all?  I think we
need to declare them or we can't use them as bare identifiers.  There
are no barewords in Perl 6, so they have to be something predeclared,
or otherwise syntactically distinguished.  We could syntactically
distinguish them in the presence of Cbut, but that doesn't let us
use them anywhere else, and it makes Cbut into more of a macro than
an operator, which seems unclean.  Letting them be bare identifiers
under the predeclared classname rule seems to be the most appropriate
way to do it, if indeed properties can be unified with roles (and
roles with classes).  And I suspect they can be unified, and ought
to be unified.  My goal isn't so much to make sticky notes as hard to
use as subtypes, but to make subtypes as easy to use as sticky notes.
I think it ought to be easy for any object to pretend to be some other
kind of object.  Allomorphism is not just for untyped Perl scalars.

That being said, there has to be a little discipline to it, or we'll
find ourselves in property hell.  I think roles provide a nice level
of discipline.

: It's clear that I don't entirely understand all of this yet (er, as much
: as there is to understand... yet).

Well, I don't entirely understand either.  One thing I do understand
is that people get scared when I start thinking out loud.  :-)

Larry


Re: enums and bitenums

2003-12-11 Thread Uri Guttman
 LW == Larry Wall [EMAIL PROTECTED] writes:

   Or are you worried that these have to be declared at all?  I think
   we need to declare them or we can't use them as bare identifiers.
   There are no barewords in Perl 6, so they have to be something
   predeclared, or otherwise syntactically distinguished.  We could
   syntactically distinguish them in the presence of Cbut, but that
   doesn't let us use them anywhere else, and it makes Cbut into more
   of a macro than an operator, which seems unclean.  Letting them be
   bare identifiers under the predeclared classname rule seems to be
   the most appropriate way to do it, if indeed properties can be
   unified with roles (and roles with classes).  And I suspect they can
   be unified, and ought to be unified.  My goal isn't so much to make
   sticky notes as hard to use as subtypes, but to make subtypes as
   easy to use as sticky notes.  I think it ought to be easy for any
   object to pretend to be some other kind of object.  Allomorphism is
   not just for untyped Perl scalars.

   Well, I don't entirely understand either.  One thing I do understand
   is that people get scared when I start thinking out loud.  :-)

sounds like you are working on the grand unification. does string theory
have any place here? and i rarely understand your thinking until it is
set in concrete and then chopped up with a jackhammer into little itty
bitty pieces by damian. :)

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: enums and bitenums

2003-12-11 Thread Larry Wall
On Thu, Dec 11, 2003 at 04:18:19PM -0700, Luke Palmer wrote:
: Larry Wall writes:
:  Anyway, this all implies that use of a role as a method name defaults to
:  returning whether the type in question matches the subtype.  That is,
:  when you say
:  
:  $foo.true
:  
:  it's asking whether the Boolean property fulfills the true constraint.
:  When you say
:  
:  $bar.red
: 
: So are you saying that, eg.
: 
: class Something does Color {...}
: my Something $flib;
: 
: if $flib.red  { print Flib is red }
: if $flib.true { print Should be an error before now }
: 
: Since Something doesn't Boolean, true would be a method not found
: error? 

Didn't answer your question.  No, because methods that happen to be
class names are special, in this worldview.

: If that's the case, how do we attach out-of-band properties on objects
: that don't expect them, but only some of them (as was the original
: intent for properties, IIRC):
: 
: my role onlyonced;
: sub onlyonce($arg is rw) {
: die onlyonce called twice on the same value if $arg.onlyonced;
: $arg but= onlyonced;
: }
: 
: Either that doesn't work at all, because you get an onlyonced not
: found error, or it works because onlyonced is a declared role.  But
: in the latter case I worry about namespace pollution.

Okay, maybe I understand your worry now.  Are you worried that
every object implicitly has boolean methods corresponding to every
class/role/property name in scope?  I can see where that might
cause some heartburn.

Larry


roles (Was: enums and bitenums)

2003-12-11 Thread Jonathan Lang
I'm invoking the principle that the only stupid question is the one not
asked: 

Larry Wall wrote:
 if indeed properties can be unified with roles (and roles with 
 classes).  

Based on the source material pointed to as your inspiration for roles, I'm
a little confused as to how roles and classes could be unified.  From what
I read in the source material, a key point of a role (well, they weren't
actually calling it a 'role' there, but I'm not recalling the term that
they did use) is that you get to bypass the diamond inheritence problem
by relegating member variables to classes, so that when you use multiple
roles to construct a class you don't have to worry about deciding which
version of the variable to access in any given method.  Without that
restraint, exactly how does a role differ from a multiple inheritence
model?  

---

Incidently, I think I've caught on to _one_ of the concepts in the
upcoming object-orientation proposal: linguistically, there's a triad of
basic verbs - namely be, do, and have.  If I'm following things
properly, one could think of an object's properties as things that it has,
its methods as things that it does, and its roles as things that it is. 
So

  my Dog $Spot has $spots;

would be a way to create an object inheriting from type Dog which has a
property called $.spots (is there a way to do @.spots?); 

  my Dog $Spot will rollover {...}; 

would be a way to create an object inheriting from type Dog which has a
method called rollover (will is used because does is essentially a
synonym for will do, and do is a built-in method which often gets
called implicitly to represent the object's primary function); and

  my Dog $Spot is pet; 

would be a way to create an object inheriting from type Dog which has a
role called pet.  

In a similar way, roles can specify things which must be included in order
for the role to be complete.  Just like is, will, and has could be
thought of as ways of including roles, methods, and variables in an
object, like, must, and needs could be used respectively to specify
that the object must have the methods and variables in question added to
it to be considered complete.  like probably needs some clarification,
in that saying that an object is like a role means that the object takes
all of that role's methods and variables as requirements (that is, it
requires methods with the same name and signature and properties with the
same name and type), in addition to whatever requirements said role
normally contributes.  

Am I following?  

=
Jonathan Dataweaver Lang

__
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/


Re: roles (Was: enums and bitenums)

2003-12-11 Thread Paul Hodges

--- Jonathan Lang [EMAIL PROTECTED] wrote:
 Incidently, I think I've caught on to _one_ of the concepts in the
 upcoming object-orientation proposal: linguistically, there's a triad
 of basic verbs - namely be, do, and have.  If I'm following
 things properly, one could think of an object's properties as things
 that it has, its methods as things that it does, and its roles as
 things that it is. 

Beautiful. This has a lot of potential, although some of it is
potential to twist young minds. It makes me want to add commas
where commas should not be. 

  my Dog $Spot is Pet, will { Sit() }, has @.fleas;

See what I mean? :op
But seriously, how much of that actually is valid?I doubt @.fleas will
fly (no pun intended, honest).



__
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/


Re: roles (Was: enums and bitenums)

2003-12-11 Thread chromatic
On Thu, 2003-12-11 at 18:15, Jonathan Lang wrote:

 Based on the source material pointed to as your inspiration for roles, I'm
 a little confused as to how roles and classes could be unified.  From what
 I read in the source material, a key point of a role (well, they weren't
 actually calling it a 'role' there, but I'm not recalling the term that
 they did use) is that you get to bypass the diamond inheritence problem
 by relegating member variables to classes, so that when you use multiple
 roles to construct a class you don't have to worry about deciding which
 version of the variable to access in any given method.

That's true, but that's incidental to the point of roles.  It falls out
from the important thing about roles.

   Without that restraint, exactly how does a role differ from a multiple inheritence
 model?

Roles are a *more general* means of polymorphism and code reuse than
inheritance.  Inheritance is a *means* of performing a role, but it's
not the only one.

What's important about a role is that it marks the most important
question (at least for polymorphic purposes):  does this thing do what
I'm about to ask it to do?

It can do that role because of inheritance, but it can also do it
because you've reimplemented all of the necessary methods, because
you've aggregated an object that perform that role, or because you're
delegating to an object that performs the role.

If the only tool in your toolbox is isa(), you must either fake up some
inheritance scheme or go without the three other allomorphic
techniques.  That's a shame.

Roles exist because you can't fit all of the useful behavior in a system
into a rigid class hierarchy -- some bits apply across classes --
without creating a mess.

Again, inheritance is only one way a class can fulfill a role.  It's not
the only way and it's not necessarily the best way.

See Class::Roles on the CPAN.

-- c



Re: roles (Was: enums and bitenums)

2003-12-11 Thread Jonathan Lang
Paul Hodges wrote:
 Jonathan Lang [EMAIL PROTECTED] wrote:
  Incidently, I think I've caught on to _one_ of the concepts in the
  upcoming object-orientation proposal: linguistically, there's a triad
  of basic verbs - namely be, do, and have.  If I'm following
  things properly, one could think of an object's properties as things
  that it has, its methods as things that it does, and its roles as
  things that it is. 
 
 Beautiful. This has a lot of potential, although some of it is
 potential to twist young minds. It makes me want to add commas
 where commas should not be. 
 
   my Dog $Spot is Pet, will { Sit() }, has @.fleas;
 
 See what I mean? :op

Technically, it would be will do { Sit() } or does { Sit() } or even
does sit(); but yes, I can see what you mean.  

 But seriously, how much of that actually is valid?I doubt @.fleas will
 fly (no pun intended, honest).

I don't see why not; must every member of an aobject be a scalar?  Can't
any of them be lists or hashes?  


=
Jonathan Dataweaver Lang

__
Do you Yahoo!?
New Yahoo! Photos - easier uploading and sharing.
http://photos.yahoo.com/