Re: enums and bitenums
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
Vocabulary
So I'm seeing a lot of inconsistent OO-vocabulary around here, and it makes things pretty hard to understand. So here's how Perl 6 is using said inconsistent terms, AFAIK: - attribute A concrete data member of a class. Used with Chas. - property An out-of-band sticky note to be placed on a single object. Used with Cbut. - trait A compile time sticky note to be placed on a wide variety of things. Used with Cis. - role A collection of methods to be incorporated into a class sans inheritance (and maybe some other stuff, too). Used with Cdoes. So for example: class Dog does Boolean# role is extended # trait is Mammal # [1] { has $.tail; # attribute has @.legs; # attribute } my $fido = Dog.new but false; # property Hope that clears things up. Luke [1] This is a base class, which is an overloaded use of Cis. Though, upon A12 release, we'll probably find out that it's not overloaded but instead, elegantly unified, somehow.
Re: enums and bitenums
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: Vocabulary
On Fri, Dec 12, 2003 at 04:23:02AM -0700, Luke Palmer wrote: So I'm seeing a lot of inconsistent OO-vocabulary around here, and it makes things pretty hard to understand. So here's how Perl 6 is using said inconsistent terms, AFAIK: - attribute A concrete data member of a class. Used with Chas. - property An out-of-band sticky note to be placed on a single object. Used with Cbut. I think an important aspect of properties that you left out here is that they are run-time. - trait A compile time sticky note to be placed on a wide variety of things. Used with Cis. - role A collection of methods to be incorporated into a class sans inheritance (and maybe some other stuff, too). Used with Cdoes. s/class/object/ Roles are like sticky behavior (as I understand them) just as properties are sticky state. And I assume that roles are run-time so that you can have your objects obtain new behavior (fullfill new roles) as needed without having to use eval all the time. I think I'm getting it but I'm not sure. Does something like this work? my role Teach { ... } my role Operate { ... } my role Learn { ... } my Person $frank; { temp $frank_the_teacher = $frank does Teach; ... } { temp $frank_the_doctor = $frank does Operate; ... } { temp $frank_the_student = $frank does Learn; ... } I.e., we can use dynamic scoping to control how long an object fulfills a particular role? Maybe it could also be written like so: my Person $frank; { my role Teach { ... }; $frank does Teach; ... } { my role Operate { ... }; $frank does Operate; ... } { my role Learn { ... } $frank does Learn; ... } so that when the role goes out of scope, the object no longer possesses the abilities of that role. I confuse myself everytime I think about this stuff. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: enums and bitenums
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: Vocabulary
On Fri, Dec 12, 2003 at 04:23:02AM -0700, Luke Palmer wrote: : So I'm seeing a lot of inconsistent OO-vocabulary around here, and it : makes things pretty hard to understand. Agreed. : So here's how Perl 6 is using said inconsistent terms, AFAIK: : : - attribute : A concrete data member of a class. Used with Chas. Declared with Chas is a little more precise. : - property : An out-of-band sticky note to be placed on a single object. : Used with Cbut. Maybe applied with? : - trait : A compile time sticky note to be placed on a wide variety of things. : Used with Cis. Fine. (Though I like to hyphenate compile-time when it's an adjective, and not when it's a noun. Same for run-time, just to be consistent.) : - role : A collection of methods to be incorporated into a class sans A role can also supply one or more attributes. : inheritance (and maybe some other stuff, too). Used with Cdoes. Here it gets a little fuzzier. A role can be applied to a class at compile time via does, or to an object at run time via but. A property is a simple kind of role that supplies a single attribute. The type of a property is identical to its role name. Roles can have subtypes that function as enums when the subtypes are constrained to a single value. You can use one of these subtypes without specifically implying the role name. So saying $bar but Red might give you a value with the property Color. You can write the corresponding boolean test using the smart match operator: $bar ~~ Red and it (smartly) picks out the Color property to compare with, provided it's unambiguous. You can use that syntax to compare against any subtype or junction of subtypes: $bar ~~ RedishWhiteish # pinkish : So for example: : : class Dog : does Boolean# role : is extended # trait : is Mammal # [1] : { : has $.tail; # attribute : has @.legs; # attribute : } : : my $fido = Dog.new : but false; # property : : Hope that clears things up. Yes, it does. : Luke : : [1] This is a base class, which is an overloaded use of Cis. Though, : upon A12 release, we'll probably find out that it's not overloaded but : instead, elegantly unified, somehow. If not, it'll be easy to turn it into an isa. Larry
Re: enums and bitenums
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
-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: Vocabulary
-Original Message- From: Jonathan Scott Duff [mailto:[EMAIL PROTECTED] Sent: Friday, December 12, 2003 11:13 AM To: Luke Palmer Cc: Language List Subject: Re: Vocabulary On Fri, Dec 12, 2003 at 04:23:02AM -0700, Luke Palmer wrote: So I'm seeing a lot of inconsistent OO-vocabulary around here, and it makes things pretty hard to understand. So here's how Perl 6 is using said inconsistent terms, AFAIK: - attribute A concrete data member of a class. Used with Chas. - property An out-of-band sticky note to be placed on a single object. Used with Cbut. I think an important aspect of properties that you left out here is that they are run-time. - trait A compile time sticky note to be placed on a wide variety of things. Used with Cis. - role A collection of methods to be incorporated into a class sans inheritance (and maybe some other stuff, too). Used with Cdoes. s/class/object/ Roles are like sticky behavior (as I understand them) just as properties are sticky state. And I assume that roles are run-time so that you can have your objects obtain new behavior (fullfill new roles) as needed without having to use eval all the time. This seems needlessly restrictive. If we're defining roles as having mixin capabilities, we should be able to use them in classes. Laziness. role Work {...}; role Management {...}; class Employee {...}; class Worker is Employee does Work; class Manager is Employee does Management; role PHB does Manager[does no Work]; I think I'm getting it but I'm not sure. Does something like this work? my role Teach { ... } my role Operate { ... } my role Learn { ... } my Person $frank; { temp $frank_the_teacher = $frank does Teach; ... } { temp $frank_the_doctor = $frank does Operate; ... } { temp $frank_the_student = $frank does Learn; ... } I.e., we can use dynamic scoping to control how long an object fulfills a particular role? Maybe it could also be written like so: my Person $frank; { my role Teach { ... }; $frank does Teach; ... } { my role Operate { ... }; $frank does Operate; ... } { my role Learn { ... } $frank does Learn; ... } so that when the role goes out of scope, the object no longer possesses the abilities of that role. I confuse myself everytime I think about this stuff. That's brilliant, if twisted. The object persists, but the behaviors expire. There's a paradigm there, man. Write a book. (It's double-e Eevil, too, but that's Damian's problem. :-) =Austin
FW: Vocabulary
-Original Message- From: Luke Palmer [mailto:[EMAIL PROTECTED] Sent: Friday, December 12, 2003 6:23 AM So I'm seeing a lot of inconsistent OO-vocabulary around here, and it makes things pretty hard to understand. So here's how Perl 6 is using said inconsistent terms, AFAIK: - attribute A concrete data member of a class. Used with Chas. - property An out-of-band sticky note to be placed on a single object. Used with Cbut. - trait A compile time sticky note to be placed on a wide variety of things. Used with Cis. Did I miss something with IS and OF? That is, I think: Cis means storage type, while Cof means trait or class: my @a is Herd of Cat; declares a Herd (presumably a base class of some collection type) with the trait that, in this case, members will be of Class Cat. Did this change when I wasn't looking? - role A collection of methods to be incorporated into a class sans inheritance (and maybe some other stuff, too). Used with Cdoes. No comment, since this is still hovering (see Larry's reply). So for example: class Dog does Boolean# role is extended # trait is Mammal # [1] The only difference I can see here between Cdoes Boolean and Cis extended would be the declaration of Boolean or extended (unless Cis can only be used with built-in traits, which seems unnecessarily restrictive...) { has $.tail; # attribute has @.legs; # attribute } my $fido = Dog.new but false; # property Hope that clears things up. Luke [1] This is a base class, which is an overloaded use of Cis. Though, upon A12 release, we'll probably find out that it's not overloaded but instead, elegantly unified, somehow. Thanks for bringing this out. =Austin
RE: Vocabulary
-Original Message- From: Larry Wall [mailto:[EMAIL PROTECTED] Sent: Friday, December 12, 2003 12:17 PM : - role : A collection of methods to be incorporated into a class sans A role can also supply one or more attributes. So a role can constrain values and add behavior and attributes. Presumably it can do both at the same time? enum ParityMode values P_ODD P_EVEN P_NONE; role Byte does Int[0..255] # Value constraint does { # extending by adding attributes methods, and by overriding the STORE method has ParityMode $.parity_mode = NONE; has bit $.parity; # .CONFORM is redundant with Value constraint above, which autogenerates this. method CONFORM(Int $i) { SUPER 0 = $i = 255; } method STORE(Int $i: $v) { $i = .CONFORM($v) || fail; set_parity; } method set_parity {...} }; : inheritance (and maybe some other stuff, too). Used with Cdoes. Here it gets a little fuzzier. A role can be applied to a class at compile time via does, or to an object at run time via but. Good. I like the mixin being available at either time. This makes properties a lot more useful since I can provided default or normal values: role Celebrated does Date does { method celebrated($d) { return $d.date; } } class Birthday does Celebrated { has $.date; } my Birthday $d = Birthday.new('February', 29, 2004) but Celebrated('March', 01, 2004); print My birthday is celebrated $d.celebrated; I presume that the linear order (compile time) or chronological order of applying roles decides the order in which overlaid methods are Cwraped/overlaid. Which is it, by the way? Or is there MTOWTDI, such as a method modifier for specifying polymorph behavior? method CONFORM is wrapped { ... call ... } A property is a simple kind of role that supplies a single attribute. The type of a property is identical to its role name. Roles can have subtypes that function as enums when the subtypes are constrained to a single value. This seems really clunky for enums. It works okay for boolean, but even doing month-names is going to suck pretty hard: role Month; role January does Month[0]; role February does Month[1]; role March does Month[2]; role April does Month[3]; role May does Month[4]; role June does Month[5]; role July does Month[6]; role Augustdoes Month[7]; role September does Month[8]; role October does Month[9]; role November does Month[10]; role December does Month[11]; role Month does Int[January..December]; You can use one of these subtypes without specifically implying the role name. So saying $bar but Red might give you a value with the property Color. This is smart and helpful. I like it. However, there needs to be a way to specify what to do when multiple roles share the same values. For example, if I have NeededBy and Estimated roles: my $birthday = 02/29/2004 but March; my $ship_date = 01/01/01 but NeededBy(February); You can write the corresponding boolean test using the smart match operator: $bar ~~ Red and it (smartly) picks out the Color property to compare with, provided it's unambiguous. You can use that syntax to compare against any subtype or junction of subtypes: $bar ~~ RedishWhiteish # pinkish Disambiguation? $bar ~~ NeededBy(February) or $bar.NeededBy ~~ February =Austin
RE: enums and bitenums
-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
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: Vocabulary
A role can also supply one or more attributes. : inheritance (and maybe some other stuff, too). Used with Cdoes. The smalltalk paper you mentionned which talked about roles (under the name of traits) said that roles were stateless. What are the consequences of using stateful roles? A related question. Will getter and setter methods will have the same name as the underlying accessed attributes? -- stef
Re: Vocabulary
At 9:16 AM -0800 12/12/03, Larry Wall wrote: On Fri, Dec 12, 2003 at 04:23:02AM -0700, Luke Palmer wrote: : - property : An out-of-band sticky note to be placed on a single object. : Used with Cbut. Maybe applied with? : - trait : A compile time sticky note to be placed on a wide variety of things. : Used with Cis. Fine. (Though I like to hyphenate compile-time when it's an adjective, and not when it's a noun. Same for run-time, just to be consistent.) I would really, *really* like to kill the whole It's a sticky note! metaphor dead. If I understand the changes proposed in properties as part of the whole shift to roles thing they aren't anything like sticky notes at all, as they dynamically subclass the object. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: enums and bitenums
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
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: Vocabulary
On Fri, Dec 12, 2003 at 07:12:40PM +0100, Stéphane Payrard wrote: : : A role can also supply one or more attributes. : : : inheritance (and maybe some other stuff, too). Used with Cdoes. : : The smalltalk paper you mentionned which talked about roles (under : the name of traits) said that roles were stateless. Though they did point out that state was one of the thing they wanted to look into. : What are the consequences of using stateful roles? That's what we're trying to figure out. :-) It seems to me that as long as the attributes declared in the role are elaborated into the real object at class composition time, there's really very little problem with doing that part of it. You have to watch for collisions just as you do with method names, of course. The tricky part comes later when you start to use it. The trickiest thing will be to know if some change in the rest of the object has invalidated your role's state such that you have to recompute it. : A related question. Will getter and setter methods will have the : same name as the underlying accessed attributes? Yes, the getter/setter method is the same name as the attribute. (There's only one method, but it can be an lvalue method for rw attributes). Larry
Re: enums and bitenums
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
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
Re: FW: Vocabulary
On Fri, Dec 12, 2003 at 04:31:32PM -0500, Austin Hastings wrote: : - trait :A compile time sticky note to be placed on a wide variety : of things. Used with Cis. : : Did I miss something with IS and OF? : : That is, I think: : : Cis means storage type, while Cof means trait or class: : : my @a is Herd of Cat; : : declares a Herd (presumably a base class of some collection type) with the trait that, in this case, members will be of Class Cat. : : Did this change when I wasn't looking? No, it hasn't changed. Generally Cis specifies the storage class when you're applying it to a variable. We've just been using it a little weirdly on things that aren't variables, such as class declarations. : - role :A collection of methods to be incorporated into a class sans : inheritance (and maybe some other stuff, too). Used with Cdoes. : : No comment, since this is still hovering (see Larry's reply). Flutter, flutter. : So for example: : : class Dog : does Boolean# role : is extended # trait : is Mammal # [1] : : The only difference I can see here between Cdoes Boolean and Cis extended would be the declaration of Boolean or extended (unless Cis can only be used with built-in traits, which seems unnecessarily restrictive...) Traits are seeming a lot more like roles than like superclasses these days. But they may still be different beasties. A role will have some rules about how it's composed into a class, while a trait can presumably do anything it jolly well pleases. They may unify at some point, but maybe only at a temperature of billions of degrees. Larry
Re: Vocabulary
It was Friday, December 12, 2003 when Luke Palmer took the soap box, saying: : So I'm seeing a lot of inconsistent OO-vocabulary around here, and it : makes things pretty hard to understand. Awesome. I've taken your original, plus comments so far and created perlvocab.pod. Lets give it a couple go-rounds and it can be stored in CVS for safe keeping (and maintaining). Send me diffs if you like. Document below sig. Casey West -- Usenet is like Tetris for people who still remember how to read. -- Button from the Computer Museum, Boston, MA =pod =head1 NAME perlvocab - Perl Vocabulary and Glossary =head1 SYNOPSIS This document authoritatively defines many potentially ambiguous terms in Perl. =head1 DESCRIPTION =head2 Object Oriented Terminology =over 4 =item attribute A concrete data member of a class. Declared with Chas. =item property A run-time, out-of-band sticky note to be placed on a single object, applied with with Cbut. A property is a simple kind of role that supplies a single attribute. The type of a property is identical to its role name. Roles can have subtypes that function as enums when the subtypes are constrained to a single value. You can use one of these subtypes without specifically implying the role name. So saying $bar but Red might give you a value with the property Color. You can write the corresponding boolean test using the smart match operator: $bar ~~ Red and it (smartly) picks out the Color property to compare with, provided it's unambiguous. You can use that syntax to compare against any subtype or junction of subtypes: $bar ~~ RedishWhiteish # pinkish =item trait A compile-time sticky note to be placed on a wide variety of things. Used with Cis. =item role A collection of methods and/or attributes to be incorporated into a class sans inheritance (and maybe some other stuff, too). A role can be applied to a class at compile time via Cdoes, or to an object at run time via Cbut. So for example: class Dog does Boolean# role is extended # trait is Mammal # base class { has $.tail; # attribute has @.legs; # attribute } my $fido = Dog.new but false; # property In this example, CMammal is a base class, which is an overloaded use of Cis. Though, upon A12 release, we'll probably find out that it's not overloaded but instead, elegantly unified, somehow. =head1 AUTHOR Luke Palmer, Original Document Contributions by Larry Wall, and Jonathan Scott Duff Compilation by Casey West =cut
Re: Vocabulary
On Fri, Dec 12, 2003 at 05:17:37PM -0500, Austin Hastings wrote: : -Original Message- : From: Larry Wall [mailto:[EMAIL PROTECTED] : Sent: Friday, December 12, 2003 12:17 PM : : : - role : : A collection of methods to be incorporated into a class sans : : A role can also supply one or more attributes. : : So a role can constrain values and add behavior and attributes. Presumably : it can do both at the same time? I suspect so. Some added behaviors may only make sense on a constrained set of values. : enum ParityMode values P_ODD P_EVEN P_NONE; : : role Byte : does Int[0..255] # Value constraint : does { # extending by adding attributes methods, and by : overriding the STORE method : has ParityMode $.parity_mode = NONE; : has bit $.parity; : :# .CONFORM is redundant with Value constraint above, : which autogenerates this. : method CONFORM(Int $i) { SUPER 0 = $i = 255; } : method STORE(Int $i: $v) { $i = .CONFORM($v) || fail; set_parity; } : method set_parity {...} : }; Yes, though CONFORM is likely to be spelled PRE. And I'm not sure your STORE is gonna work by clobbering the invocant reference like that. More likely you have to assign to .value or some such accessor provided by Int. Or since roles compose into the class, it may be okay for roles to access attribute variables directly, and set $.value (presuming that's the attribute provided by Int). Depends on how fancy we want to get with the cross checking at composition time. : : inheritance (and maybe some other stuff, too). Used : with Cdoes. : : Here it gets a little fuzzier. A role can be applied to a class : at compile time via does, or to an object at run time via but. : : Good. I like the mixin being available at either time. This makes properties : a lot more useful since I can provided default or normal values: : : role Celebrated : does Date : does { : method celebrated($d) { return $d.date; } : } : : class Birthday does Celebrated { : has $.date; : } : : my Birthday $d = Birthday.new('February', 29, 2004) but : Celebrated('March', 01, 2004); : : print My birthday is celebrated $d.celebrated; More generally, you can write the rest of the class knowing that the role is there if it's compiled in. : I presume that the linear order (compile time) or chronological order of : applying roles decides the order in which overlaid methods are : Cwraped/overlaid. The original Traits paper specifies that it's illegal to compose two methods of the same name into the class, and you have to rename one of them to get them both visible. This is why the authors specifically rejected mixins, because they hide errors like this. As for the relationship of Trait methods to other methods declarations, an explicit method declaration in the class proper overrides the composed methods, while composed methods override anything else in the inheritance hierarchy. : Which is it, by the way? Or is there MTOWTDI, such as a method modifier for : specifying polymorph behavior? The default way might well be the way specified in the Traits paper. However, their underlying language didn't support any kind of multi dispatch. Perl 6 will be able to multi any set of names in the same namespace as long as the arguments are differentiable by type. So it might be possible to insert a stub method declaration in the class proper that says treat all composed methods of this name as multis. That presumes the methods take differing arguments, of course. : method CONFORM is wrapped { ... call ... } That would be another way to do it, except that you might still have to switch on something to tell it which role method to call. : A property is a simple kind of role that supplies a single attribute. : The type of a property is identical to its role name. Roles can have : subtypes that function as enums when the subtypes are constrained to a : single value. : : This seems really clunky for enums. It works okay for boolean, but even : doing month-names is going to suck pretty hard: : : role Month; : : role January does Month[0]; : role February does Month[1]; : role March does Month[2]; : role April does Month[3]; : role May does Month[4]; : role June does Month[5]; : role July does Month[6]; : role Augustdoes Month[7]; : role September does Month[8]; : role October does Month[9]; : role November does Month[10]; : role December does Month[11]; : : role Month does Int[January..December]; That's why I suggested some syntactic sugar for it. But I admit that treating each enum as a subtype is a stretch. They could be constant methods, for instance. In any event, the various enum names should probably be hidden in the Month role and not be exported by default. : You can use one of these subtypes without specifically implying the role : name.