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