A12: Single Dispatch over Mult Dispatch
(Note: throughout this message, "method" refers to "sub"s and "submethods" as well.) I'm having trouble coming up with a solid argument for why Single Method Dispatch (SMD) is our default, when we have MMD. At this point, I'm tempted to slap a C in front of all my methods, for the sake of future extensibility. So my basic idea is to solicit reasons why we shouldn't make C the default, and then allow for c for the obscure cases where one wants such behavior. Arguments in favor: = If you've bothered to define a signature for the method, you expect things that call it to match that signature. I would expect an error when I tried to call a method with parameters that didn't match the signature. This change would move that error from "Call doesn't match signature" to a "Method for name(signature) not found". = If you haven't defined a signature, MMD will match against the implied signature, which it always should, so no problem. = Making everything multi makes extending existing code much easier, for obvious reasons. Arguement against: = Likely makes things harder on the optimizer. Or more likely, makes MMD optimization a lot more important. But that's a p6i problem, not a p6l one. Another way to interpret this post is "When is SMD preferred over MMD? And is that enough to make it the default?" If I'm missing something basic feel free to correct me. -- Rod Adams
Re: A12: subtypes that lack methods or roles
Larry Wall wrote: > Jonathan Lang wrote: > : How would I declare a subtype of a class which messes with the > : dispatching mechanism to exclude certain methods and/or roles from > : it? > > Er, uh...tell you what. Why don't you provide some sample code to > go with your question, and we'll just tell Dan to make it work. :-) This goes along with my other thread about nested roles. In Perl/Tk - specifically HList, there's a bunch of methods, including: add, addchild, delete, headerCreate, headerConfigure, headerCGet, headerDelete, headerExists, headerSize, indicatorCreate, indicatorConfigure, indicatorCGet, indicatorDelete, indicatorExists, indicatorSize, itemCreate, itemConfigure, itemCGet, itemDelete, itemExists, ... In perl 6, I'd be tempted to handle it something like this: class HList { method add {...}; method addchild {...}; method delete {...}; # things relating to multicolumn lists does role header { has Int $.columns; method headerCreate {...}; method headerConfigure {...}; method headerCGet {...}; method headerDelete {...}; method headerExists {...}; method headerSize {...}; }; # things relating to the icon next to each tree entry does role indicator { has Flag $.indicator; method indicatorCreate {...}; method indicatorConfigure {...}; method indicatorCGet {...}; method indicatorDelete {...}; method indicatorExists {...}; method indicatorSize {...}; }; # things relating to individual "cells" in the list does role item { method itemCreate {...}; method itemConfigure {...}; method itemCGet {...}; method itemDelete {...}; method itemExists {...}; }; ... }; OK: I'm planning on creating a widget which must not make use of any of the indicator functionality of the HList; I don't just want to not use the functionality - I want to have its use forbidden (letting the optimizer go ahead and toss out the indicator role). So I'd like to create a subtype of HList which exceises that functionality. It's a subtype of HList in the sense that we're removing functionality in order to get there; however, we're removing functionality by saying that, in effect, this subtype does _not_ do the indicator role. So when the resulting thing attempts to call the indicatorCreate method, it first looks at the class methods, and doesn't find anything; it then looks at each of the roles, _except for the indicator role_. It doesn't find anything. It then looks at any inherited methods, etc., and ultimately doesn't find the method. It then throws an exception to alert the programmer that he's trying to use a routine that he's not supposed to use. So how to tell the subtype(?) to disregard the indicator role? While we're at it, I'd also like to remove the addchild method, since I don't want this thing to be used to create hierarchal structures - I'm looking for the tabular data capabilities in this case. = Jonathan "Dataweaver" Lang __ Do you Yahoo!? Yahoo! Photos: High-quality 4x6 digital prints for 25¢ http://photos.yahoo.com/ph/print_splash
Re: A12: Exporation
Uri Guttman asked: how would you handle %EXPORT_TAGS and @EXPORT_OK? Export-only-by-request (i.e. @EXPORT_OK) becomes the default. The tag names become arguments to C: sub foo is export(:BAR, :FOOLISH) {...} # Now in two named tagsets Every exportable is automatically also in the :ALL tagset. To export-by-default (i.e. the @EXPORT behaviour) you write: sub foo is export(:DEFAULT) {...} To export-in-all-cases (not currently possible) you write: sub foo is export(:MANDATORY) {...} See Perl6::Export for details and implementation (but bear in mind that those details are almost certain to change as a result of this very thread). Damian
Re: A12: "can", "does", and "isa" in roles
On Fri, Apr 23, 2004 at 06:56:35PM -0700, Jonathan Lang wrote: : $::_ can x; # asserts that the class must provide a method called x Fine idea, but that looks like run-time code that runs at the wrong time. It needs something out front to make it a declaration. Perhaps it's just: POST { $::_.can('x') } if that doesn't interact badly with its DBC meaning. Larry
Re: A12: subtypes that lack methods or roles
At 6:12 PM -0700 4/23/04, Larry Wall wrote: On Fri, Apr 23, 2004 at 03:07:23PM -0700, Jonathan Lang wrote: : How would I declare a subtype of a class which messes with the dispatching : mechanism to exclude certain methods and/or roles from it? Er, uh...tell you what. Why don't you provide some sample code to go with your question, and we'll just tell Dan to make it work. :-) No problem. Throwing an exception counts as working, right? :-P -- Dan --"it's like this"--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
A12: "can", "does", and "isa" in roles
One of the beauties of the original Traits paper was that its roles had ways of specifying assertions of what criteria must be met by whatever classes they were to be composed into. Meanwhile, it's been mentioned that roles and classes in P6 might look declarative in nature, but they are in fact procedural. So why not allow a few assertions to be made in roles? These would be assertions which get run by the class when it composes the roles, and returning false would raise an exception to the programmer, quite possibly providing at compile-time some detailed information as to what he left out of the class. So instead of having to hunt through a bunch of code inside a method to find that there's a reference to an attribute $.x, he'd get an error message triggered by an assertion that the class must have an attribute $.x. Or: role A { $::_ can x; # asserts that the class must provide a method called x method y () { # a whole bunch of code # a line that makes reference to $.x # a bunch of additional code } } class Foo { does A; }; This would produce a compile-time error "class Foo can't x as role A requires" instead of a compile-time error "$.x undefined" or somesuch, which is what you'd get without the "can" assertion. The code would work either way; the difference is in how much debugging is needed for a programmer to find and correct his mistake. IMHO, code which serves no other purpose than to produce speedy and intelligent error messages is still quite a valuable thing. = Jonathan "Dataweaver" Lang __ Do you Yahoo!? Yahoo! Photos: High-quality 4x6 digital prints for 25¢ http://photos.yahoo.com/ph/print_splash
Re: A12: Exporation
Larry wrote: On Sat, Apr 24, 2004 at 09:52:12AM +1000, Damian Conway wrote: : My proposal for that issue is just: : : module Bar; : : use Foo «foo»; : : sub foo is export {...} That's on the right track, but has some difficulties, insofar as it's not clear that the intent is to redefine "foo" retroactively rather than actively. Err. It's just a declaration that Bar has a subroutine named &foo and that that subroutine is exportable. The fact that that subroutine exists in Bar because it's imported from Foo is utterly orthogonal, isn't it? And it doesn't necessarily work for variables True. Just quietly, I would consider that a *feature*! ;-) But see below for a possible solution. does it tell the "use" whether you were intending to import «foo» as a package name or a lexical name. This is, IMO, the real issue. But, as you ponder below, it's an issue of how the "imporation" (;-) from Foo is specified, not how the "exporation" from Bar is handled. The main reason for separate declarations in normal use is to specify whether you want to import lexically or packagely. So a more minimal approach is to allow use Foo my &foo, my $foocount, our &bar; for the normal declarations (ignoring re-exportation issues), and then resort to ::= for renamings. If we make lexical importation the default, that reduces to use Foo «foo $foocount», our &bar; This seems to be by far the least annoying approach. Of course, for re-export you'd have to say use Foo my &foo is export, my $foocount is export(:MANDATORY), our &bar; I don't see why. Import to- and export from- a module could (and probably should) be entirely orthogonal. So perhaps exportation should be via mixin: use Foo «foo $foocount», our &bar; &foo does export; $foocount does export(:MANDATORY); sub localsub does export {...} my $localvar does export; sub AUTOLOAD {...} # implements &baz and &qux sub baz does export {...} # stub for autoloaded sub That separates the two concerns (import vs export) very cleanly, doesn't require much extra typing,seems to handle all kinds of referents (not just subroutines), and also supports exporting things that are not locally defined in *other* ways besides having been imported (such as things implemented as AUTOWHATEVERS). Damian
Re: A12: subtypes that lack methods or roles
On Fri, Apr 23, 2004 at 03:07:23PM -0700, Jonathan Lang wrote: : How would I declare a subtype of a class which messes with the dispatching : mechanism to exclude certain methods and/or roles from it? Er, uh...tell you what. Why don't you provide some sample code to go with your question, and we'll just tell Dan to make it work. :-) Larry
Re: A12: nested roles
On Fri, Apr 23, 2004 at 03:00:57PM -0700, Jonathan Lang wrote: : Can role definitions be nested? That is: : : role A { : role subRole1 {...}; : role subRole2 {...}; : ... : }; : : As I see it, this ought to be equivelent to : : role A::subRole1 {...}; : role A::subRole2 {...}; : role A { : does A::subRole1; does A::subRole2; : ... : }; : : The advantage of doing things this way is that you'd be able cluster : related attributes and methods together within a role (or within a class, : for that matter) - clusters which make sense within the main role, but : probably don't have enough importance to be created as "standalone" roles. I don't think a nested role would automatically "do" itself, but you could probably say: role A { does role subRole1 {...}; does role subRole2 {...}; ... }; At which point we all gang up on you and beat you to a pulp for being overly analytical. :-) Larry
Re: A12: Conflicting Attributes in Roles
On Fri, Apr 23, 2004 at 03:34:32PM -0700, Jonathan Lang wrote: : Larry Wall wrote: : > On Fri, Apr 23, 2004 at 02:37:58PM -0700, Jonathan Lang wrote: : > : Note that the problem extends past accessors: a role's methods can : > : access its attributes directly. So: : > : : > : role A {has Cat $.x; method m1 {return $.x;};} : > : role B {has Dog $.x; method m2 {return $.x;};} : > : class Foo {does Cat; does Dog;} : > : my Foo $bar; : > : $bar.m1; # returns $A::x, right? : > : $bar.m2; # returns $B::x, right? : > : : > : If the two $.x's are completely equivelent, you end up with redundant : > : data storage. : > : > Actually, it'd blow up at composition time anyway, since there's a : > default readonly accessor for each $.x variable. : : OK; so add "method x {...};" to class Foo to keep it from blowing up. Foo : still has to track two scalars internally. : : Actually, it's worse than that: let's add "has Elephant $.x;" to Foo : instead. Since class trumps role, does $bar.m1 now work with an Elephant, : or does it still work with a Cat? I think the attributes have to be considered to belong primarily to the role, and a role that references one of its own attributes knows that it is doing so to the exclusion of any other similarly named attribute in the class or in a different role. Accessing a role's attribute from within a class or another role should really only work as a fallback, if at all. I think people should be encouraged to use the methods where performance is not at a premium. Most of these will be private attributes in any event, so using the :method doesn't have to do virtual dispatch. But private attributes also belong primarily to the role, and only secondarily to the class or other roles. However, the roles do implicitly trust each other by virtue of being composed into the same class, so they can see each other's private methods. Note that this means you can write roles that are only meaningful when composed into a class with certain other roles or methods, and cannot be used as mixins, since a mixin would never see the private methods from an overridden base class. The only way to do it as a mixin is to have a composite role containing all the other roles, and then mix that one role in all at once. (Which is probably what you want to do anyway for efficiency, when you know you have to mix in multiple roles.) Larry
Re: A12: Exporation
On Sat, Apr 24, 2004 at 09:52:12AM +1000, Damian Conway wrote: : My proposal for that issue is just: : : module Bar; : : use Foo «foo»; : : sub foo is export {...} That's on the right track, but has some difficulties, insofar as it's not clear that the intent is to redefine "foo" retroactively rather than actively. And it doesn't necessarily work for variables, nor does it tell the "use" whether you were intending to import «foo» as a package name or a lexical name. What I've been envisioning in that regard involves making declarations that simultaneously look like declarations and can have their names "harvested" for use by the C. As a "placeholder", let's postulate a funny macro called "namely", that works something like this: module Bar; use Foo namely( my sub foo is export {...} my Int $foocount is export(:MANDATORY); our sub bar {...} my %huz ::= %zah; ); which, to the C, ends up looking something like use Foo «foo $foocount bar %zah» except that the exporter presumably has access to all the extra information it needs to make sure the types and renamings stay sane. The syntax is, of course, totally up for grabs, but please note that we can't use curlies instead of parentheses, or the scoping goes all wrong. The alternative approach is to have a means of marking the "use" as lazy, and a way of marking each individual declaration as an alias from a particular module. That can get rather more verbose though. use Foo :lazily; my sub foo is from(Foo) is export {...} my Int $foocount is from(Foo) is export(:MANDATORY); our sub bar is from(Foo) {...} my %huz ::= %Foo::zah; On the other hand, the renaming syntax is a little more toward. Maybe they're all renamings: my sub foo is export ::= Foo::foo; my Int $foocount is export(:MANDATORY) ::= $Foo::foocount; our sub bar ::= Foo::bar; my %huz ::= %Foo::zah; That gets rid of the spurious {...}, at least. At the expense of colon overload, though... And it's not like we can't do that already. It's the moral equivalent of Perl 5's glob aliasing. As such it's pretty darn ugly. Which means it's fine for exceptions, but lousy for normal use. The main reason for separate declarations in normal use is to specify whether you want to import lexically or packagely. So a more minimal approach is to allow use Foo my &foo, my $foocount, our &bar; for the normal declarations (ignoring re-exportation issues), and then resort to ::= for renamings. If we make lexical importation the default, that reduces to use Foo «foo $foocount», our &bar; Of course, for re-export you'd have to say use Foo my &foo is export, my $foocount is export(:MANDATORY), our &bar; For that to work, C and C would have to be sufficiently context sensitive to know when they were in use list. The alternative is a macro like namely(), which would also have the benefit of letting you use semicolons between declarations rather than commas. Larry
Re: A12: Exporation
Aaron Sherman wrote: At the end of A12, "Exportation" covered the idea that you will now say: sub foo() is export {...} Rather than the P5: @EXPORT=qw(foo); sub foo; Which is fine, except that in P5 we could say: use Foo qw(foo); @EXPORT=qw(foo); Now, I know that the Apoc on modules has not been written, and by that time Larry will have thought of this, but I thought I'd point out that some mechanism will have to exist in modules to indicate not only that they acquire certain subroutines, variables, etc. of other modules, but that they re-export them as their own. My proposal for that issue is just: module Bar; use Foo «foo»; sub foo is export {...} This works perfectly in Perl 5 under the Perl6::Export module (now on the CPAN): package Bar; use Perl6::Export; use Foo qw(foo); sub foo is export; Damian
Re: A12: Exporation
Exporation?! And I sent one to p6i about "missint math ops" boy, this is not my day :-( But still, you get the idea, I hope ;-) -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
Re: A12: Conflicting Attributes in Roles
Larry Wall wrote: > On Fri, Apr 23, 2004 at 02:37:58PM -0700, Jonathan Lang wrote: > : Note that the problem extends past accessors: a role's methods can > : access its attributes directly. So: > : > : role A {has Cat $.x; method m1 {return $.x;};} > : role B {has Dog $.x; method m2 {return $.x;};} > : class Foo {does Cat; does Dog;} > : my Foo $bar; > : $bar.m1; # returns $A::x, right? > : $bar.m2; # returns $B::x, right? > : > : If the two $.x's are completely equivelent, you end up with redundant > : data storage. > > Actually, it'd blow up at composition time anyway, since there's a > default readonly accessor for each $.x variable. OK; so add "method x {...};" to class Foo to keep it from blowing up. Foo still has to track two scalars internally. Actually, it's worse than that: let's add "has Elephant $.x;" to Foo instead. Since class trumps role, does $bar.m1 now work with an Elephant, or does it still work with a Cat? = Jonathan "Dataweaver" Lang __ Do you Yahoo!? Yahoo! Photos: High-quality 4x6 digital prints for 25¢ http://photos.yahoo.com/ph/print_splash
A12: subtypes that lack methods or roles
How would I declare a subtype of a class which messes with the dispatching mechanism to exclude certain methods and/or roles from it? = Jonathan "Dataweaver" Lang __ Do you Yahoo!? Yahoo! Photos: High-quality 4x6 digital prints for 25¢ http://photos.yahoo.com/ph/print_splash
A12: nested roles
Can role definitions be nested? That is: role A { role subRole1 {...}; role subRole2 {...}; ... }; As I see it, this ought to be equivelent to role A::subRole1 {...}; role A::subRole2 {...}; role A { does A::subRole1; does A::subRole2; ... }; The advantage of doing things this way is that you'd be able cluster related attributes and methods together within a role (or within a class, for that matter) - clusters which make sense within the main role, but probably don't have enough importance to be created as "standalone" roles. = Jonathan "Dataweaver" Lang __ Do you Yahoo!? Yahoo! Photos: High-quality 4x6 digital prints for 25¢ http://photos.yahoo.com/ph/print_splash
A12: Exporation
At the end of A12, "Exportation" covered the idea that you will now say: sub foo() is export {...} Rather than the P5: @EXPORT=qw(foo); sub foo; Which is fine, except that in P5 we could say: use Foo qw(foo); @EXPORT=qw(foo); Now, I know that the Apoc on modules has not been written, and by that time Larry will have thought of this, but I thought I'd point out that some mechanism will have to exist in modules to indicate not only that they acquire certain subroutines, variables, etc. of other modules, but that they re-export them as their own. I'm deliberately NOT proposing how that would be done, as I have significant faith that Larry can manage that small bit of magic on his own, and doesn't need me spewing random ideas and, even worse, syntax suggestions. -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
Re: A12: Conflicting Attributes in Roles
On Fri, Apr 23, 2004 at 02:37:58PM -0700, Jonathan Lang wrote: : Note that the problem extends past accessors: a role's methods can access : its attributes directly. So: : : role A {has Cat $.x; method m1 {return $.x;};} : role B {has Dog $.x; method m2 {return $.x;};} : class Foo {does Cat; does Dog;} : my Foo $bar; : $bar.m1; # returns $A::x, right? : $bar.m2; # returns $B::x, right? : : If the two $.x's are completely equivelent, you end up with redundant data : storage. Actually, it'd blow up at composition time anyway, since there's a default readonly accessor for each $.x variable. : : Then again, this may be more of a quirk than a problem... I'd like to think so. But then, I thought that about a lot of Perl 5 OO... Larry
RE: A12: Conflicting Attributes in Roles
At 2:37 PM -0700 4/23/04, Jonathan Lang wrote: Austin Hastings wrote: Jonathan Lang wrote: > role A {has Cat $.x;} > role B {has Dog $.x;} > class Foo {does Cat; does Dog;} > my Foo $bar; > $bar.x; # Is this a Cat or a Dog? If, however, two roles try to introduce a method of the same name (for some definition of name), then the composition of the class fails, and the compilation of the program blows sky high--we sincerely hope. It's much better to catch this kind of error at compile time if you can. And in this case, you can. Since classes are autogenerating accessors based in data members, it's doubly reasonable to assume that the same solution will apply: conflict -> death. Note that the problem extends past accessors: a role's methods can access its attributes directly. So: role A {has Cat $.x; method m1 {return $.x;};} role B {has Dog $.x; method m2 {return $.x;};} class Foo {does Cat; does Dog;} my Foo $bar; $bar.m1; # returns $A::x, right? $bar.m2; # returns $B::x, right? If the two $.x's are completely equivelent, you end up with redundant data storage. I'd think, assuming roles are allowed to add attributes (and, if so, I'd argue "what's the difference between a class and a role, then?" but someone'd hit me), that the attribute would be role-specific. In the above case you'd have two separate attributes. -- Dan --"it's like this"--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: A12: context-sensitive multi routines?
On Fri, Apr 23, 2004 at 02:20:20PM -0700, Jonathan Lang wrote: : "Then we simply claim that, under multiple dispatch, the "long name" of : any multi routine includes its signature, and that visibility is based on : the long name." (paragraph 3, "Multiple Dispatch") : : Is a routine's "returns" trait also included in a multi routine's "long : name"? That is, if I define : : multi method foo () returns scalar {...}; : multi method foo () returns list {...}; : multi method foo () returns hash {...}; : : would these be treated as three seperate routines, or as conflicting : declarations of the same one? It's not included in the primary invocants, but it might well be considered as a tiebreaker just as a secondary invocant would be. Mostly though it's just cleaner to have one routine return an object that knows what to do in a given context than to try to guess via "want" semantics. Then you don't have to worry about guessing wrong under the indirection of my $value = foo(); ... say $value.{'key'}; say $value.[2]; say $value; And in fact, since the object can respond in all of those contexts, you don't ever have to guess. And if one or another of those values is difficult to calculate, you can always do it lazily. Larry
RE: A12: Conflicting Attributes in Roles
Austin Hastings wrote: > Jonathan Lang wrote: > > role A {has Cat $.x;} > > role B {has Dog $.x;} > > class Foo {does Cat; does Dog;} > > my Foo $bar; > > $bar.x; # Is this a Cat or a Dog? > > > If, however, two roles try to introduce a method of the same name (for > some definition of name), then the composition of the class fails, and > the compilation of the program blows sky high--we sincerely hope. It's > much better to catch this kind of error at compile time if you can. And > in this case, you can. > > > Since classes are autogenerating accessors based in data members, it's > doubly reasonable to assume that the same solution will apply: conflict > -> death. Note that the problem extends past accessors: a role's methods can access its attributes directly. So: role A {has Cat $.x; method m1 {return $.x;};} role B {has Dog $.x; method m2 {return $.x;};} class Foo {does Cat; does Dog;} my Foo $bar; $bar.m1; # returns $A::x, right? $bar.m2; # returns $B::x, right? If the two $.x's are completely equivelent, you end up with redundant data storage. Then again, this may be more of a quirk than a problem... = Jonathan "Dataweaver" Lang __ Do you Yahoo!? Yahoo! Photos: High-quality 4x6 digital prints for 25¢ http://photos.yahoo.com/ph/print_splash
A12: context-sensitive multi routines?
"Then we simply claim that, under multiple dispatch, the "long name" of any multi routine includes its signature, and that visibility is based on the long name." (paragraph 3, "Multiple Dispatch") Is a routine's "returns" trait also included in a multi routine's "long name"? That is, if I define multi method foo () returns scalar {...}; multi method foo () returns list {...}; multi method foo () returns hash {...}; would these be treated as three seperate routines, or as conflicting declarations of the same one? = Jonathan "Dataweaver" Lang __ Do you Yahoo!? Yahoo! Photos: High-quality 4x6 digital prints for 25¢ http://photos.yahoo.com/ph/print_splash
Re: A12: default accessors and encapsulation
On Fri, Apr 23, 2004 at 03:23:09PM -0400, Austin Hastings wrote: : > And if you override the accessor, you can: : > : > multi method foo(Str $blah = undef) is rw($new) { : > (my($old),$.foo)=($.foo,$blah//$new); : > .update_the_world_in_some_cool_way(); : > return $old : > } : : I don't understand this. It's what we on the cabal have been calling an out-of-band parameter. We have at times contemplated them for various purposes, none of which seem to have panned out. Instead we've ended up with things like $CALLER::_ and such. : What's the $new doing? It looks to me like it's being a parameter that doesn't interfere with the official signature. : And if you've only got one of them, do you need multi, or just an optional : argument? It's just an optional argument, but... : method foo(Str ?$new) is rw { : my $old = $.foo; : if (defined($new)) { : $.foo = $new; : .update_the_world(); : } : return $old; : } ...but it doesn't ruin the signature symmetry between getter and setter like yours. It does share the misfeature that you have to write special switching code internally to deal with it, which the proxy solution automatically dispatches for you. It also assumes you even want the old value, which you often don't, if the proxy is destined to be the left side of an ordinary assignment in void context. And, in fact, if it weren't in void context, you'd want the new value, not the old one, which means you better hang onto that proxy... I suppose in the cases where the attribute can serve as its own proxy, we could have a hook that captures control on setting, and lets you add side effects en passant without making you responsible to actually set the variable like a STORE hook would. If you wanted to remove the actual attribute you'd have to graduate it to a STORE closure on a real proxy though (with whatever syntactic sugar makes that most palatable). Larry
Re: A12: Typed undef
On Fri, Apr 23, 2004 at 12:46:07PM -0700, Dave Whipp wrote: : I'm not sure how much of this is relevant to C, but it might be nice : to have the ability to have an undef that says "if used, then trap" (using : the current "use fail" mode -- if that still exists) I suppose one could give a typed undef whatever semantics you like with an appropriate AUTOMETH definition. : ps. as an aside, it would be really nice to have support for : getting/handling numeric exceptions -- even for things like an overflow : ("carry") on a primitive "int". As a bonus, an "int" with saturation : semantics (cf the normal modulo semantics) would be nice, too. I think that : would need parrot-level support to be efficient. I expect so. Low-level types tend to be rather, well, low-level. Larry
Re: A12: Typed undef
On Fri, 2004-04-23 at 15:46, Dave Whipp wrote: > Just wondering, are we going to have semantics similar to the old NaN Vs > Signaling-Nan in IEEE floating point? An IEE NaN has an N-bit field where > the source of the NaN can place a value representing the reason for the NaN. > It can also set a flag which selects between two behaviors: Didn't we decide that NaN was a reserved word and should never be spoken again, especially with respect to undef? ;-) Seriously, though, I think there's some detail in terms of standard library that have to get covered before it makes sense to explore this in much depth. -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
Re: A12: Typed undef
"Larry Wall" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > On Fri, Apr 23, 2004 at 02:50:42PM -0400, Austin Hastings wrote: > : Sure, but "You haven't provided a value yet." doesn't seem very ... > : exceptional. > > The important thing will be "You didn't provide a value at line 42, though > you didn't actually try to use it till line 582." Just wondering, are we going to have semantics similar to the old NaN Vs Signaling-Nan in IEEE floating point? An IEE NaN has an N-bit field where the source of the NaN can place a value representing the reason for the NaN. It can also set a flag which selects between two behaviors: * normal NaN: If you attempt to use the NaN in any calculation, then you'll get back the original NaN (the defined semantics are actually a bit fuzzy here -- an implementation is permitted to lose any information that you embedded in your NaN. But presumably, if your hardware inserts a value, it also knows not to trash it). * Signaling NaN: If you attempt to use the NaN in any calculation then you get an FP exception. If you have set your processor to trap on exceptions, then you get a trap. I'm not sure how much of this is relevant to C, but it might be nice to have the ability to have an undef that says "if used, then trap" (using the current "use fail" mode -- if that still exists) Dave. ps. as an aside, it would be really nice to have support for getting/handling numeric exceptions -- even for things like an overflow ("carry") on a primitive "int". As a bonus, an "int" with saturation semantics (cf the normal modulo semantics) would be nice, too. I think that would need parrot-level support to be efficient.
Re: A12: Delegation using arrays
On Fri, Apr 23, 2004 at 03:13:09PM -0400, Austin Hastings wrote: : Can I declare a const reference and have it optimized away? : : class Queue { : has @:elements; : has $:array_delegate : handles : = \@:elements : is const; : } I suppose, depending on what you mean by "optimize". I would guess this is one of those potential optimizations that nobody ever gets the tuits to do. : So what are the ways to fail? : : -> Subtype incompatibility, as above : -> Invocation signature: Does the @:handlers list become a wierd sort of : tunable multimethod dispatch? : -> C keyword? : -> C obviously : -> Others? Ain't that enough? :-) Larry
Re: A12: Typed undef
On Fri, Apr 23, 2004 at 03:18:22PM -0400, Austin Hastings wrote: : > -Original Message- : > From: Larry Wall [mailto:[EMAIL PROTECTED] : > : > On Fri, Apr 23, 2004 at 02:50:42PM -0400, Austin Hastings wrote: : > : Sure, but "You haven't provided a value yet." doesn't seem very ... : > : exceptional. : > : > The important thing will be "You didn't provide a value at line 42, though : > you didn't actually try to use it till line 582." : : So the "typed undef" doesn't get built or inserted or whatever until some : reference is made to the object? : : my Dog $spot; : my Dog $rover; : : At this point, no calls have been made to the 'default undef constructor', : right? : : $spot = $rover.clone(); : : At this point, $rover gets typed-undef, then cloned? I was talking about unthrown exceptions objects. I have no opinions on how lazy undef wants to be for ordinary objects. Larry
RE: A12: default accessors and encapsulation
> -Original Message- > From: Aaron Sherman [mailto:[EMAIL PROTECTED] > Sent: Friday, 23 April, 2004 03:12 PM > To: John Siracusa > Cc: Perl 6 Language > Subject: Re: A12: default accessors and encapsulation > > > On Tue, 2004-04-20 at 10:13, John Siracusa wrote: > > On 4/19/04 7:20 PM, Larry Wall wrote: > > > On Mon, Apr 19, 2004 at 06:53:29PM -0400, John Siracusa wrote: > > > : Yeah, that's exactly what I don't want to type over and over :) > > > > > > I really don't understand what you're getting at here. First you > > > complain that you'd rather write an ordinary method, and then you > > > complain that you have to. Have I met someone lazier than me? :-) > > > > Possibly :) Here's what I'm saying. In the first version of a > class, there > > will probably be a lot of simple get/set attributes. It's > convenient not to > > have to write any explicit methods for those. > > > > If I accept the default accessors that you get "for free" when > a class "has > > $.foo is rw", then that means the users of my class can do $obj.foo = > > whatever in order to set the foo attribute. > > And if you override the accessor, you can: > > multi method foo(Str $blah = undef) is rw($new) { > (my($old),$.foo)=($.foo,$blah//$new); > .update_the_world_in_some_cool_way(); > return $old > } I don't understand this. What's the $new doing? And if you've only got one of them, do you need multi, or just an optional argument? method foo(Str ?$new) is rw { my $old = $.foo; if (defined($new)) { $.foo = $new; .update_the_world(); } return $old; }
RE: A12: Typed undef
> -Original Message- > From: Larry Wall [mailto:[EMAIL PROTECTED] > > On Fri, Apr 23, 2004 at 02:50:42PM -0400, Austin Hastings wrote: > : Sure, but "You haven't provided a value yet." doesn't seem very ... > : exceptional. > > The important thing will be "You didn't provide a value at line 42, though > you didn't actually try to use it till line 582." So the "typed undef" doesn't get built or inserted or whatever until some reference is made to the object? my Dog $spot; my Dog $rover; At this point, no calls have been made to the 'default undef constructor', right? $spot = $rover.clone(); At this point, $rover gets typed-undef, then cloned? =Austin
Re: A12: default accessors and encapsulation
On Tue, 2004-04-20 at 10:13, John Siracusa wrote: > On 4/19/04 7:20 PM, Larry Wall wrote: > > On Mon, Apr 19, 2004 at 06:53:29PM -0400, John Siracusa wrote: > > : Yeah, that's exactly what I don't want to type over and over :) > > > > I really don't understand what you're getting at here. First you > > complain that you'd rather write an ordinary method, and then you > > complain that you have to. Have I met someone lazier than me? :-) > > Possibly :) Here's what I'm saying. In the first version of a class, there > will probably be a lot of simple get/set attributes. It's convenient not to > have to write any explicit methods for those. > > If I accept the default accessors that you get "for free" when a class "has > $.foo is rw", then that means the users of my class can do $obj.foo = > whatever in order to set the foo attribute. And if you override the accessor, you can: multi method foo(Str $blah = undef) is rw($new) { (my($old),$.foo)=($.foo,$blah//$new); .update_the_world_in_some_cool_way(); return $old } and while that's verbose, it's only a bit more verbose than: multi method foo(Str $blah) { (my($old),$.foo)=($.foo,$blah); return $old; } which is what you would have write ANYWAY to add your new functionality. -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
RE: A12: Delegation using arrays
> -Original Message- > From: Larry Wall [mailto:[EMAIL PROTECTED] > > On Fri, Apr 23, 2004 at 02:07:16PM -0400, Austin Hastings wrote: > : I guess I'm more strongly attached to the sigil than I > realized. IMO, if you > : have > : > : $obj handles 'a'; > : > : and put an arrayref in $obj, then you get what's coming: > iteration. But if > : you have > : > : @obj handles 'a'; > : > : then you know it's an array, or array subtype, and delegate > array-things to > : it. > : > : So I prefer cases 1:s, 1:n, and a:a instead of 1:s, 1:a, and a:n. > > But a delegating attribute is not an alias for its delegatee, or if it is, > should maybe not be thought of as one. The question is, if you've gone > and delegated to another object, should this class be mucking around with > the innards of the array object as if it owned it? I don't think so. > I think it's better to have the reference in a scalar variable to remind > you of that it's a different object. On the other hand, the list of > handlers *is* a valid concern for this class, and it shouldn't have to > go poking down through a reference to get at that list. It has a valid > use for the @ sigil. Aha! A light comes on: Delegation is not the same as subordination. The C delegation syntax declares "formal" delegation, meaning that the handler is treated as a separate object. Thus, by default delegate objects are stored in scalar references. However, you may delegate to many objects by using the @handler or %handler syntaxes. That's an explanation/ideology I can sink my teeth into. Can I declare a const reference and have it optimized away? class Queue { has @:elements; has $:array_delegate handles = \@:elements is const; } > > : > : Also, it's not clear: > : > : > : > : "first one that succeeds" > : > : > : > : Does that mean "First one for which a matching > : > : method exists" or does it mean "First one for which > : > : a method exists that does not C or return > : > : undef or some other badness"? > : > > : > The latter is the intent. > : > : Then array handling is doing some sort of .+method > : dispatch instead of "plain old dispatch", no? > > No, it's plain old, I expect. > > : I think this should be made explicit. At first glance, > : I'd hate to lose C or C > : as an option just because than means "keep searching for > : handlers". > : > : Can you tell us why the initial spec calls for continuing > : search? > > It doesn't. The question in question had an "or", which > seem in your thinking to have mutated into an "and". The > "badness" in the question in question is provided by "next > METHOD", not by returning false or undef. So if a method > knows it can handle something, all it does is return the > value, whatever that is. Okay. So one way to fail would be a subtype violation: class Row { has @:flavors handles ; } type OddRow ::= Row where $:row_num mod 2 == 1; type EvenRow ::= Row where $:row_num mod 2 == 0; $even_row = new Row(row_num => 0); $odd_row = new Row(row_num => 1); @:flavors = ( $even_row, $odd_row ); $row.print_row; Right? (I know, this could be done with a multimethod.) So what are the ways to fail? -> Subtype incompatibility, as above -> Invocation signature: Does the @:handlers list become a wierd sort of tunable multimethod dispatch? -> C keyword? -> C obviously -> Others? =Austin
Re: A12: Typed undef
On Fri, Apr 23, 2004 at 02:50:42PM -0400, Austin Hastings wrote: : Sure, but "You haven't provided a value yet." doesn't seem very ... : exceptional. The important thing will be "You didn't provide a value at line 42, though you didn't actually try to use it till line 582." : Sure -- the class of the object may object to the object being undef. (Sorry : :-) But does Perl object to an undef object of the class of the object : object? : : That is: : : $foo = (undef as Dog).collar(); Haven't the foggiest. I just pretend to be a language designer. Larry
Re: A12: Conflicting Attributes in Roles
On Fri, 2004-04-23 at 14:28, Aaron Sherman wrote: > I would expect wildcard delegation not to care about method conflicts at > all, since what's being done is, by its nature, much more dynamic > anyway. I misunderstood roles when I said this... I now get why this is a problem, sorry. -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
RE: A12: Typed undef
> -Original Message- > From: Larry Wall [mailto:[EMAIL PROTECTED] > > Interestingly, the opaque shortcut used to be > > $class.bless(undef, *%_); > > But I made it 0 instead merely because it's shorter. That does, however, > free up "undef" as a way of asking for an explicitly undefined but > blessed value. ^^ This is pretty much the whole answer. Sweet! ^^ > > : There are potentially two flavors of undef: > : > : undef > : > : undef but class = C > > There are potentially many flavors of undef already. I've already said > that many undef flavors contain an unthrown exception stating why the > value in question is undefined, such that if you try to use the value > as defined, you can throw an intelligent exception that will point the > user back to the real problem. Sure, but "You haven't provided a value yet." doesn't seem very ... exceptional. > That is one of the real innovations in Perl 6, as opposed to the > borrowings. > > : Given that the foo and bar methods are declared to return C, should the > : 'return undef' code emit a 'pure' undef, or a undef-of-type-C? > > Don't know the answer to that one. One possible answer with a certain > amount of appeal is that it is completely illegal to return a bare undef. > It either has to be an unthrown exception, or a proto-object. I was hoping for "Perl will type-convert the undef for you". :-) > : And if so, should it be legal to have an undef invocant? A typed-undef > : invocant? > > Depends on what it's pretending not to be, I suspect. Sure -- the class of the object may object to the object being undef. (Sorry :-) But does Perl object to an undef object of the class of the object object? That is: $foo = (undef as Dog).collar(); > : This sort of wanders towards the question: Is undef a value, or a > : meta-value? That is, can a UDT rely on scalar undef as part of > its range (a > : la NaN/Inf in the numbers space) or must undef be considered part of the > : Perl domain, "you're not a Thingy yet." > > I'd say the concept of defined/undefined as a constraint depends entirely > on whether the object in question returns true or false to .defined(), > regardless of its other characteristics. Perl is otherwise agnostic to > its thinginess, at least until you ask it to care. > : (The mapping of undef <-> SQL's NULL comes to mind.) > Hmm, yes, that might fall out rather neatly, as long as it's clear to > the reader when you mean NULL rather than undef. It's almost a funny > kind of junction.
RE: A12: Conflicting Attributes in Roles
> -Original Message- > From: Larry Wall [mailto:[EMAIL PROTECTED] > > On Fri, Apr 23, 2004 at 01:05:21PM -0400, Austin Hastings wrote: > : That seems like a good disambiguation marker, too: > : > : class Trog does Tree does Dog {...} > : > : # error: conflicting 'bark' methods > : > : class Trog > : is PersistentObject > : handles «meta dispatch SERIALIZE» > : does Tree > : handles «bark» > : does Dog > : {...} > > That works in the case of an explicitly named method, since that > effectively makes .bark a method in the current class. It would not > work for a wildcard delegation though, unless Dog were specifically > marked not to handle .bark. > Junctions to the rescue! class Trog does Tree handles «bark» does Dog handles none«bark» {...} =Austin
Re: A12: Delegation using arrays
On Fri, Apr 23, 2004 at 02:07:16PM -0400, Austin Hastings wrote: : I guess I'm more strongly attached to the sigil than I realized. IMO, if you : have : : $obj handles 'a'; : : and put an arrayref in $obj, then you get what's coming: iteration. But if : you have : : @obj handles 'a'; : : then you know it's an array, or array subtype, and delegate array-things to : it. : : So I prefer cases 1:s, 1:n, and a:a instead of 1:s, 1:a, and a:n. But a delegating attribute is not an alias for its delegatee, or if it is, should maybe not be thought of as one. The question is, if you've gone and delegated to another object, should this class be mucking around with the innards of the array object as if it owned it? I don't think so. I think it's better to have the reference in a scalar variable to remind you of that it's a different object. On the other hand, the list of handlers *is* a valid concern for this class, and it shouldn't have to go poking down through a reference to get at that list. It has a valid use for the @ sigil. : > : Also, it's not clear: : > : : > : "first one that succeeds" : > : : > : Does that mean "First one for which a matching method exists" or does it : > : mean "First one for which a method exists that does not C : > or return : > : undef or some other badness"? : > : > The latter is the intent. : : Then array handling is doing some sort of .+method dispatch instead of : "plain old dispatch", no? No, it's plain old, I expect. : I think this should be made explicit. At first glance, I'd hate to lose : C or C as an option just because than means : "keep searching for handlers". : : Can you tell us why the initial spec calls for continuing search? It doesn't. The question in question had an "or", which seem in your thinking to have mutated into an "and". The "badness" in the question in question is provided by "next METHOD", not by returning false or undef. So if a method knows it can handle something, all it does is return the value, whatever that is. Larry
Re: A12: Conflicting Attributes in Roles
On Fri, 2004-04-23 at 14:17, Larry Wall wrote: > : does Tree > : handles «bark» > : does Dog > That works in the case of an explicitly named method, since that > effectively makes .bark a method in the current class. It would not > work for a wildcard delegation though, unless Dog were specifically > marked not to handle .bark. That's fine. I would expect wildcard delegation not to care about method conflicts at all, since what's being done is, by its nature, much more dynamic anyway. -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
Re: A12: Conflicting Attributes in Roles
On Fri, Apr 23, 2004 at 01:05:21PM -0400, Austin Hastings wrote: : That seems like a good disambiguation marker, too: : : class Trog does Tree does Dog {...} : : # error: conflicting 'bark' methods : : class Trog : is PersistentObject : handles «meta dispatch SERIALIZE» : does Tree : handles «bark» : does Dog : {...} That works in the case of an explicitly named method, since that effectively makes .bark a method in the current class. It would not work for a wildcard delegation though, unless Dog were specifically marked not to handle .bark. Larry
RE: A12: Typed undef
> -Original Message- > From: Juerd [mailto:[EMAIL PROTECTED] > > Austin Hastings skribis 2004-04-23 13:33 (-0400): > > I should then be able to call class methods of Dog via $spot > > without further initialization: > > print defined($spot); # FALSE > > $rover = $spot.new; > > @breeds = $spot.list_breeds; > > But shouldn't you then just use "my Class $spot = Dog" then? Or maybe > just "my $spot := Dog"? Hmm, no. The point is that typed-undef should know what to do, by default, when calling class methods. And maybe it should even call non-class (i.e., "object") methods, with a typed-undef invocant. > > This is, as pointed out, just sugar for Dog::new and Dog::list_breeds, but > > it brings up the spectre of undef invocants: > > :: or .? I'm confused. It's :: to indicate class::function naming. > > $c->foo->bar->baz; # If foo or bar fails, what happens? > > -> or .? Even more confused now. $c.foo.bar.baz Sorry, I've been PHPing a lot. =Austin
Re: A12: Delegation using arrays
On Fri, Apr 23, 2004 at 10:39:33AM -0700, Larry Wall wrote: : On the other hand, maybe making %:handlers special is wrong, and it I meant @:handlers there, of course. We all seem to be having a little trouble with syntax today, doesn't us? Larry
Re: A12: Typed undef
Interestingly, the opaque shortcut used to be $class.bless(undef, *%_); But I made it 0 instead merely because it's shorter. That does, however, free up "undef" as a way of asking for an explicitly undefined but blessed value. : There are potentially two flavors of undef: : : undef : : undef but class = C There are potentially many flavors of undef already. I've already said that many undef flavors contain an unthrown exception stating why the value in question is undefined, such that if you try to use the value as defined, you can throw an intelligent exception that will point the user back to the real problem. That is one of the real innovations in Perl 6, as opposed to the borrowings. : Given that the foo and bar methods are declared to return C, should the : 'return undef' code emit a 'pure' undef, or a undef-of-type-C? Don't know the answer to that one. One possible answer with a certain amount of appeal is that it is completely illegal to return a bare undef. It either has to be an unthrown exception, or a proto-object. : And if so, should it be legal to have an undef invocant? A typed-undef : invocant? Depends on what it's pretending not to be, I suspect. : This sort of wanders towards the question: Is undef a value, or a : meta-value? That is, can a UDT rely on scalar undef as part of its range (a : la NaN/Inf in the numbers space) or must undef be considered part of the : Perl domain, "you're not a Thingy yet." I'd say the concept of defined/undefined as a constraint depends entirely on whether the object in question returns true or false to .defined(), regardless of its other characteristics. Perl is otherwise agnostic to its thinginess, at least until you ask it to care. : (The mapping of undef <-> SQL's NULL comes to mind.) Hmm, yes, that might fall out rather neatly, as long as it's clear to the reader when you mean NULL rather than undef. It's almost a funny kind of junction. Larry
RE: A12: Delegation using arrays
> -Original Message- > From: Larry Wall [mailto:[EMAIL PROTECTED] > > On Fri, Apr 23, 2004 at 01:15:51PM -0400, Austin Hastings wrote: > : A12 sez: > : > : If your delegation object happens to be an array: > : > : has @:handlers handles 'foo'; > : > : then something cool happens. In this case > : Perl 6 assumes that your array contains a list of potential > : handlers, and you just want to call the first one that > : succeeds. > : > : This is not clear, and I'm not liking it at the moment anyway. > It has the > : effect of saying: > : > : "If you HAS-A attribute that is an array, you cannot delegate > to it, but if > : you IS-A array, no worries." > : > : So Queue classes that start out: > : > : class Queue is Array {...} > : > : can get push/pop/splice whatever methods for free, but: > : > : class Queue is PersistentObject > : { > : has @:elements handles «push pop splice»; > : > : can not work (unless one of the things inside @:elements > happens to be an > : array). > > has $:elements handles «push pop splice»; > > can hold an array in that case. This surprises me. case 1:s has $:obj handles 'a'; $:obj = new Foo; $self.a(); # Foo::a case 1:n has $:obj handles 'a'; $:obj = «new» (Foo, Bar, Baz); $self.a(); # one(Foo::a, Bar::a, Baz::a) case 1:a has $:obj handles 'a'; $:obj = «new» (Foo, Bar, Baz); $self.a(); # Array::a case a:n has @:obj handles 'a'; @:obj = «new» (Foo, Bar, Baz); $self.a(); # one(Foo::a, Bar::a, Baz::a) case a:a has @:obj handles 'a'; @:obj = «new» (Foo, Bar, Baz); $self.a(); # Array::a I guess I'm more strongly attached to the sigil than I realized. IMO, if you have $obj handles 'a'; and put an arrayref in $obj, then you get what's coming: iteration. But if you have @obj handles 'a'; then you know it's an array, or array subtype, and delegate array-things to it. So I prefer cases 1:s, 1:n, and a:a instead of 1:s, 1:a, and a:n. > : Also, it's not clear: > : > : "first one that succeeds" > : > : Does that mean "First one for which a matching method exists" or does it > : mean "First one for which a method exists that does not C > or return > : undef or some other badness"? > > The latter is the intent. Then array handling is doing some sort of .+method dispatch instead of "plain old dispatch", no? I think this should be made explicit. At first glance, I'd hate to lose C or C as an option just because than means "keep searching for handlers". Can you tell us why the initial spec calls for continuing search? =Austin
Re: A12: Typed undef
[EMAIL PROTECTED] (Austin Hastings) writes: > > which doesn't quite work, because $spot is undefined. What probably happens > is that the my cheats and puts a version of undef in there that knows it > should dispatch to the Dog class if you call .self:new() on it. Anyway, > we'll make it work one way or another, so that it becomes the equivalent of: > > > I want to point out this is a pretty good idea overall, not as just some > "magic" behavior. It would make some of the current p6i nargery a bit simpler, too. -- In this talk, I would like to speculate a little, on ... the development of intelligent life. I shall take this to include the human race, even though much of its behaviour throughout history has been pretty stupid... - Stephen Hawking
Re: A12: Typed undef
Juerd writes: > Austin Hastings skribis 2004-04-23 13:33 (-0400): > > I should then be able to call class methods of Dog via $spot without further > > initialization: > > print defined($spot); # FALSE > > $rover = $spot.new; > > @breeds = $spot.list_breeds; > > But shouldn't you then just use "my Class $spot = Dog" then? Or maybe > just "my $spot := Dog"? Well, maybe, but what if you're being passed it in via a sub? And what if you don't know the type. Eg. sub foo ($x is copy) { $x //= $x.new; } That would clearly die if you said: foo(undef); But what if that undef was cascaded from somewhere else? It allows you to have an *undefined* object floating around that knows what it *should* be. To be clear, I don't know exactly what benefit that has just yet, but it seems like one of those things that has potential. On the other hand, A12 said that $x.new when $x is undef should in turn be undef. That also seems like something potentially useful. > > This is, as pointed out, just sugar for Dog::new and Dog::list_breeds, but > > it brings up the spectre of undef invocants: > > :: or .? I'm confused. Dog::new is the name of the method; Dog.new is how you call it. So the answer is yes. > > $c->foo->bar->baz; # If foo or bar fails, what happens? > > -> or .? Even more confused now. You'll have to give Austin some rope in the syntax area. His brain occasionally stops working (hmm, I know that feeling %-), but you can usually figure out what he means. :-p Luke
Re: A12: Delegation using arrays
On Fri, Apr 23, 2004 at 11:28:02AM -0600, Luke Palmer wrote: : Though the hash "handles" handler hardly seems useful to me. Perhaps : someone can explain what that's intended to accomplish. No idea. It just seemed like it ought to be made to mean something. On the other hand, maybe making %:handlers special is wrong, and it should delegate by default to an Array object. In which case we'd need a different declaration for cascading handlers, and there's no pressure to make %:hash mean anything special. If this were English, we'd just make it "handle" instead. But that's a rather subtle distinction. Don't anyone suggest »handles... :-) Larry
Re: A12: Typed undef
Austin Hastings skribis 2004-04-23 13:33 (-0400): > I should then be able to call class methods of Dog via $spot without further > initialization: > print defined($spot); # FALSE > $rover = $spot.new; > @breeds = $spot.list_breeds; But shouldn't you then just use "my Class $spot = Dog" then? Or maybe just "my $spot := Dog"? > This is, as pointed out, just sugar for Dog::new and Dog::list_breeds, but > it brings up the spectre of undef invocants: :: or .? I'm confused. > $c->foo->bar->baz; # If foo or bar fails, what happens? -> or .? Even more confused now. Juerd
A12: Typed undef
Mention is made of a typed undef in A12: which doesn't quite work, because $spot is undefined. What probably happens is that the my cheats and puts a version of undef in there that knows it should dispatch to the Dog class if you call .self:new() on it. Anyway, we'll make it work one way or another, so that it becomes the equivalent of: I want to point out this is a pretty good idea overall, not as just some "magic" behavior. Specifically, if I say: my Dog $spot; I should then be able to call class methods of Dog via $spot without further initialization: print defined($spot); # FALSE $rover = $spot.new; @breeds = $spot.list_breeds; This is, as pointed out, just sugar for Dog::new and Dog::list_breeds, but it brings up the spectre of undef invocants: class C { method ctor {...} method foo returns C {...; return undef; ...} method bar returns C {...; return undef; ...} method baz {...} } my C $c .= ctor; # $c is defined and all is well. $c->foo->bar->baz; # If foo or bar fails, what happens? There are potentially two flavors of undef: undef undef but class = C Given that the foo and bar methods are declared to return C, should the 'return undef' code emit a 'pure' undef, or a undef-of-type-C? And if so, should it be legal to have an undef invocant? A typed-undef invocant? This sort of wanders towards the question: Is undef a value, or a meta-value? That is, can a UDT rely on scalar undef as part of its range (a la NaN/Inf in the numbers space) or must undef be considered part of the Perl domain, "you're not a Thingy yet." (The mapping of undef <-> SQL's NULL comes to mind.) =Austin
Re: A12: Delegation using arrays
On Fri, Apr 23, 2004 at 01:15:51PM -0400, Austin Hastings wrote: : A12 sez: : : If your delegation object happens to be an array: : : has @:handlers handles 'foo'; : : then something cool happens. In this case : Perl 6 assumes that your array contains a list of potential : handlers, and you just want to call the first one that : succeeds. : : This is not clear, and I'm not liking it at the moment anyway. It has the : effect of saying: : : "If you HAS-A attribute that is an array, you cannot delegate to it, but if : you IS-A array, no worries." : : So Queue classes that start out: : : class Queue is Array {...} : : can get push/pop/splice whatever methods for free, but: : : class Queue is PersistentObject : { : has @:elements handles «push pop splice»; : : can not work (unless one of the things inside @:elements happens to be an : array). has $:elements handles «push pop splice»; can hold an array in that case. : Also, it's not clear: : : "first one that succeeds" : : Does that mean "First one for which a matching method exists" or does it : mean "First one for which a method exists that does not C or return : undef or some other badness"? The latter is the intent. Larry
Re: A12: Delegation using arrays
Austin Hastings writes: > A12 sez: > > If your delegation object happens to be an array: > > has @:handlers handles 'foo'; > > then something cool happens. In this case > Perl 6 assumes that your array contains a list of potential > handlers, and you just want to call the first one that > succeeds. > > This is not clear, and I'm not liking it at the moment anyway. It has the > effect of saying: > > "If you HAS-A attribute that is an array, you cannot delegate to it, but if > you IS-A array, no worries." Well, the @ sign has to mean something, right? I mean, / <@foo> / doesn't turn the stringified value of @foo into a regex and match against it. I figure you can delegate from a queue like: class Queue { has Array $:elements handles Âpush pop spliceÂ; } And if you need the @ sigil for, say, a regex, you can still say: / <@$:elements> / Though the hash "handles" handler hardly seems useful to me. Perhaps someone can explain what that's intended to accomplish. Luke
Re: A12: Strings
On Thu, Apr 22, 2004 at 10:34:25AM -0400, Aaron Sherman wrote: : But, what happens if I: : : { : use bytes; : my string $line = $filehandlelikething.getline; : } That might depend on how $filehandlelikething was opened. A filehandle is going to return a string of the type requested when you opened it. As you've written it there, it would presumably try to do a downconversion depending on the definition of "string", which is not a built-in type. Alternately, it could be argued that automatic downconversion is a bad default, and the default should just be to die on a type mismatch unless a coercion is explicitly defined between the two types. (C is the built-in string object type, which probably forces no conversion, presuming conversion is lazy. The builtin C type I'm not so sure about. It might force an octets view. Or maybe we only have bstr, cstr, gstr and lstr, to force bytes, codepoints, graphemes, and letters, and str is an alias to the correct type under the current lexical Unicode support level.) : Does my saying "string" enforce anything, or do I have to: : : { : use bytes; : my string $line is bytes = $filehandlelikething.getline; : } If you want to force a conversion, it's more likely to look like my $line = $filehandlelikething.getline as bstr; or some such. That would be a downconversion, and potentially lossy or "exceptional". If what you want is to treat the internal representation of the string as a sequence of bytes, you'd have to say something else, probably a method on Str to get it to divulge its innards. In which case you're almost certainly on your own as to the interpretation of those bytes. Assume that Perl 6 will change its internal implementation of strings regularly just to keep you on your toes. :-) Larry
A12: Delegation using arrays
A12 sez: If your delegation object happens to be an array: has @:handlers handles 'foo'; then something cool happens. In this case Perl 6 assumes that your array contains a list of potential handlers, and you just want to call the first one that succeeds. This is not clear, and I'm not liking it at the moment anyway. It has the effect of saying: "If you HAS-A attribute that is an array, you cannot delegate to it, but if you IS-A array, no worries." So Queue classes that start out: class Queue is Array {...} can get push/pop/splice whatever methods for free, but: class Queue is PersistentObject { has @:elements handles «push pop splice»; can not work (unless one of the things inside @:elements happens to be an array). Also, it's not clear: "first one that succeeds" Does that mean "First one for which a matching method exists" or does it mean "First one for which a method exists that does not C or return undef or some other badness"? =Austin
RE: A12: Conflicting Attributes in Roles
> -Original Message- > From: Aaron Sherman [mailto:[EMAIL PROTECTED] > > On Fri, 2004-04-23 at 11:44, Brent 'Dax' Royal-Gordon wrote: > > Aaron Sherman wrote: > > > > class c { does a for <>; does b for <>; } > > > Funny how similar that is to > > > > class c { does a handles <>; does b handles <>; } > > In "Relationship to Roles" A12 makes the point that delegation and roles > are not the same thing. > > To tie them together with C MIGHT be wise and might not. I'll > have to think about that and see what others post on the topic. This seems good at first blush: "handles" means "when I'm asked to do this, it is taken care of by this other" That seems like a good disambiguation marker, too: class Trog does Tree does Dog {...} # error: conflicting 'bark' methods class Trog is PersistentObject handles «meta dispatch SERIALIZE» does Tree handles «bark» does Dog {...} =Austin
Re: A question about binary does
At 2:21 PM -0500 4/22/04, Abhijit A. Mahabal wrote: This is actually a couple of questions: 1: can you extend roles by saying: role Set is extended {} Parrot will allow this, so if Larry says OK you're fine. It may be rather significantly expensive, however. (Not nearly as bad as, say, adding an attribute at runtime to a heavily instantiated class, but...) 2: if yes, does this change variables for which you said $var does Set? Well, it changes the *classes* for which you said $var does Set. When you throw a role on an object we're making an anonymous sub-class, so altering the role alters the anonymous subclass rather than the object in the subclass. In other words, is the singleton class like a closure or a first-class class? I'm not sure how the above questions relate to this, but singleton classes are real first-class classes. -- Dan --"it's like this"--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: A12: a doubt about .meta, .dispatcher and final methods
On Fri, 2004-04-23 at 12:02, Aldo Calpini wrote: > if Perl5 objects are to be implemented somewhat 'transparently' in Perl6, > things like: > > $obj->{meta} > > will become: > > $obj.meta > > when used from Perl6. or not? True enough, but this was just a quick exploration of the likelihood that there would be conflict. An exhaustive analysis I leave up to those who have time to untar all of CPAN :-) Seriously though, it's also not as much of a concern as the fact that the free accessors are going to conflict left and right with modules that implement their own accessors, often with slightly different semantics than the auto-accessors in Perl 6 will provide. Converting CPAN over to Perl 6 is going to be a major pain in the butt, so that's not really what I was solving for (Perl 5 mode will solve for that in the short term). I just wanted to add some sense of "if I were writing a module, how likely would it be that I would spontaneously use meta?". -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
Re: A question about binary does
On Fri, Apr 23, 2004 at 09:42:51AM -0700, Larry Wall wrote: : : return $self.keys.grep { exists $other{$^a} } : : grepping a hash? Sorry--looked at that cross-eyed. Of course you can grep the keys... Larry
Re: A question about binary does
On Thu, Apr 22, 2004 at 02:21:17PM -0500, Abhijit A. Mahabal wrote: : This is actually a couple of questions: : 1: can you extend roles by saying: role Set is extended {} Perhaps. Classes and objects that have already composed the role would have to be notified that they need to recalculate collisions and flush any method caches, so it depends on the not-yet-written notification system in Parrot. But roles are currently implemented in Parrot as funny-looking classes, so it may naturally fall out of the ability to extend any open class. : 2: if yes, does this change variables for which you said $var does Set? : In other words, is the singleton class like a closure or a first-class : class? I could argue that one both ways. : role Set{ : method add ($elt) { $self.{$elt} = 1 } That'd be: method add ($self: $elt) { $self.{$elt} = 1 } or method add ($elt) { .{$elt} = 1 } But you don't get $self for free. : method remove ($elt) {...} : method intersection($other where Set) { : # can I write that as: method intersection (Set $other) ? Yes. : return $self.keys.grep { exists $other{$^a} } grepping a hash? : } : } : : class Set_class does Set {} : : class Collector{ : has %.coins does Set;# brand new singleton class Might have to be written as run-time rather than declarative: has %.coins will build { $_ does Set }; # brand new singleton class : has Set_class %.stamps; # use existing class : } : : my Collector $collector .= new; : $collector.coins.add(new Coin()); #okay : $collector.stamps.add(new Stamp()); #okay : : # much later during compilation : : role Set is extended{ # is this: die if any collision in any class I believe so. : method difference ($other where Set) {...} : } : : $collector.stamps.difference(...); # okay (Okay if the role extension didn't die.) : $collector.coins.difference(...); # Is that legal? I think so. : # In other words, is the singleton class like a closure or like a : first-class class? I suspect that roles composed into classes recalculate collisions and die if necessary. But roles used as mixins simply hide other methods of the same name, just as they would had the difference method been in the role in the first place. So I guess they don't behave like closures. That leaves open the question of how to write it if you *do* want it to behave like a closure. I don't think there is anything in the engine currently that can take a "snapshot" of the class in the closure sense. Perhaps there needs to be. Or maybe if you want a closure of a class you just .clone the class. Arguably, if you're going to add things into a role or class, you should increment the version number, and just rely on versioning. In that case you get closure semantics, since objects would know whether they were bound to the old version or the new version. Since you can get closure semantics that way, it seems like a good argument for making role extensions work the other way. Larry
Re: Apo 12
On Thu, Apr 22, 2004 at 04:46:39PM -0400, Aaron Sherman wrote: : Prototyping in P6 would seem to me to be easy, but not quite the : default. You'd want an intermediary that did the MetaClass negotiation : as you "derived" from an existing object. Or will that be in the core? : Can you say: : : my Object $obj1; : MyClassExtenderClass.add_a_print_method($obj1.metaclass); : my ::{$obj1.class} $obj2; : : ? How far you can take that will probably depend on the implementation of the notification system within Parrot, which we have to rely on for any kind of pull-the-semantic-carpet-out-from-under behavior modification. Larry
Re: A12: a doubt about .meta, .dispatcher and final methods
Aaron Sherman wrote: > However, in existing CPAN modules that I happen to have in my cache at > the moment: > > [...] > > So it's not THAT bad. hmmm... I think you should probably also grep for modules that do something like: my $self = { meta => 'something', dispatcher => $something, # ... }; return bless $self; if Perl5 objects are to be implemented somewhat 'transparently' in Perl6, things like: $obj->{meta} will become: $obj.meta when used from Perl6. or not? cheers, Aldo
Re: A12: Conflicting Attributes in Roles
On Fri, 2004-04-23 at 11:44, Brent 'Dax' Royal-Gordon wrote: > Aaron Sherman wrote: > > class c { does a for <>; does b for <>; } > Funny how similar that is to > > class c { does a handles <>; does b handles <>; } In "Relationship to Roles" A12 makes the point that delegation and roles are not the same thing. To tie them together with C MIGHT be wise and might not. I'll have to think about that and see what others post on the topic. I have not read the delegation section enough, either... something I need to fix. It certainly seems powerful, as it merges the "has" and "is" relationship in some very interesting ways, and eliminates some overhead that would appear in many classes that would have otherwise had to re-dispatch methods pertaining to their encapsulees. -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
Re: A12: Conflicting Attributes in Roles
Aaron Sherman wrote: seen the "does b". You could assert the other way around: class c { does a for <>; does b for <>; } which is kind of nifty looking, but some may blanch at the dual meaning for "for" Funny how similar that is to class c { does a handles <>; does b handles <>; } -- Brent "Dax" Royal-Gordon <[EMAIL PROTECTED]> Perl and Parrot hacker Oceania has always been at war with Eastasia.
Re: A12: a doubt about .meta, .dispatcher and final methods
(re-post. for some reason the alias didn't work.) Larry Wall skribis 2004-04-23 8:24 (-0700): > On the third hand, maybe we should go for $obj._meta_ or some such. I don't like _foo_ names. Once you shart having things with underscores, it's only a matter of time before someone decides that _foo, foo_, _foo, __foo, ___foo, and __foo__ should all have something specific to say about what the foo is. __LINE__, __PACKAGE__, etcetera are fine with me (although I do use CLASS.pm to be able to type CLASS and get something that often eq __PACKAGE__), but I wouldn't like other uses of underscores for important things in the core language. > On the sixth hand, by that argument, since .dispatcher is aiming at > a Class, it should be an uppercase C<>. :-) Doesn't unicode have that, then? :) Juerd
Re: A12: a doubt about .meta, .dispatcher and final methods
At 8:24 AM -0700 4/23/04, Larry Wall wrote: On Fri, Apr 23, 2004 at 10:37:00AM -0400, Aaron Sherman wrote: : It's a fine point... in the past, P5 and P6 have up-cased such : constructs in order to warn of their semi-keywordishness (e.g. DESTROY : or BUILD). I'm wondering why Larry chose to leave dispatcher and meta : lower in this case. Hmm, yes. Well, I chose those for a very strong reason--I hadn't thought about the issue yet. :-) I often throw things into Apocalypses that are "placeholders" when I know there wants to be something there, but I don't necessarily know what the right name is yet. Generally I think of the uppercase names as ones that get called automatically most of the time. But there's also a history of uppercasing reserved names in general. (Though most of these are turning into ordinary variable names like $*OUT and @*ARGS). So we could uppercase these. On the other hand, $obj.META.does is ugly. But maybe it should be ugly. On the third hand, maybe we should go for $obj._meta_ or some such. On the fourth hand, maybe it's okay to stick with .meta. On the fifth hand, since it's aiming at a MetaClass, maybe it should be C<.Meta>. On the sixth hand, by that argument, since .dispatcher is aiming at a Class, it should be an uppercase C<>. :-) On the seventh hand, why not make it a property that can be put on any method, which punts the problem out a whole 'nother level? :) -- Dan --"it's like this"--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: A12: a doubt about .meta, .dispatcher and final methods
On Fri, Apr 23, 2004 at 10:37:00AM -0400, Aaron Sherman wrote: : It's a fine point... in the past, P5 and P6 have up-cased such : constructs in order to warn of their semi-keywordishness (e.g. DESTROY : or BUILD). I'm wondering why Larry chose to leave dispatcher and meta : lower in this case. Hmm, yes. Well, I chose those for a very strong reason--I hadn't thought about the issue yet. :-) I often throw things into Apocalypses that are "placeholders" when I know there wants to be something there, but I don't necessarily know what the right name is yet. Generally I think of the uppercase names as ones that get called automatically most of the time. But there's also a history of uppercasing reserved names in general. (Though most of these are turning into ordinary variable names like $*OUT and @*ARGS). So we could uppercase these. On the other hand, $obj.META.does is ugly. But maybe it should be ugly. On the third hand, maybe we should go for $obj._meta_ or some such. On the fourth hand, maybe it's okay to stick with .meta. On the fifth hand, since it's aiming at a MetaClass, maybe it should be C<.Meta>. On the sixth hand, by that argument, since .dispatcher is aiming at a Class, it should be an uppercase C<>. :-) : However, in existing CPAN modules that I happen to have in my cache at : the moment: : : $ grep -ri 'sub meta' . : ./Convert-ASN1-0.18/inc/Module/Install/Metadata.pm:sub Meta { shift } : $ grep -ri 'sub dispa' . : ./Module-Build-0.23/lib/Module/Build/Base.pm:sub dispatch { : ./Module-Build-0.23/lib/Module/Build/Platform/MacOS.pm:sub dispatch { : ./Module-Build-0.23/blib/lib/Module/Build/Platform/MacOS.pm:sub dispatch { : ./Module-Build-0.23/blib/lib/Module/Build/Base.pm:sub dispatch { : : So it's not THAT bad. Yeah, well, we do have to worry about future proofing. Whether that's done culturally or technologically is another matter. I guess another consideration is whether there's any valid reason for a class to want to redefine .meta knowing that it's supposed to return the metaclass. If so, that would tend to argue it should be kept .meta. But that's a weak argument, as arguments go. : Good catch. Yup. Larry
Re: A12: Conflicting Attributes in Roles
On Wed, 2004-04-21 at 12:17, chromatic wrote: > * Add a disambiguatey method to PoliceDog that dispatches > appropriately. (Insert handwavey "well you *could* do it this way or > you *might* do it that way.") I agree, but given that the average user should probably not have to interact with the dispatching system just to say "my class uses class a's foo, not class b's foo", can I suggest: class a { method foo {...} } class b { method foo {...} } class c { does a; does b but a.foo; } the "but" disarms the compilation failure that A12 introduced, but only for that method. Every time you have such a conflict, you will have to disarm in this way. What MIGHT be a problem is: class c { does a but b.bar; does b but a.foo; } which requires the compiler to accept b.bar even though it has not yet seen the "does b". You could assert the other way around: class c { does a for <>; does b for <>; } which is kind of nifty looking, but some may blanch at the dual meaning for "for" -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
Re: A12: syntax to call Attributes
On Wed, 2004-04-21 at 12:44, Abhijit A. Mahabal wrote: > On Wed, 21 Apr 2004, Brent 'Dax' Royal-Gordon wrote: > > Which actually brings up an interesting question: > > > > class Silly { > > has $.thing=1; > > has @.thing=(2, 3); > > has %.thing=(4 => 5, 6 => 7); > > } > > I had assumed that'd be illegal: each of $.thing, @.thing and %.thing > autogenerates a method named thing. I would hope that is illegal, for my > head would hurt otherwise keeping track of what a particular "thing" > means. Certainly makes sense to me. The default constructor for Class should be able to handle this case quite cleanly by throwing an exception the moment you try to re-define an existing accessor, which would only yield a warning elsewhere. Now, just thinking out loud, but that should leave: class c1 { has @.joe } class c2 { is c1; has $.joe } alone because you're not replacing an accessor, you're defining one that will be hit first by the dispatcher. You are essentially saying that c2's joe is a scalar, not an array which makes fine sense. Similarly, if joe were a method in c1, it would still be "replaced" in the same way. This might lead to some surprises, but I think if folks understand the relationship here correctly, it will not be an issue. -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
Re: A12: a doubt about .meta, .dispatcher and final methods
On Fri, 2004-04-23 at 04:25, Aldo Calpini wrote: > class MyClass { > has LethalWeapon $.dispatcher; > method meta { say "$_ is doing meta!" } > } > > both of them would make my class pretty useless, I think, since it could > not (correctly, at least) dispatch methods anymore. and I won't be able > to access metadata. It's a fine point... in the past, P5 and P6 have up-cased such constructs in order to warn of their semi-keywordishness (e.g. DESTROY or BUILD). I'm wondering why Larry chose to leave dispatcher and meta lower in this case. However, in existing CPAN modules that I happen to have in my cache at the moment: $ grep -ri 'sub meta' . ./Convert-ASN1-0.18/inc/Module/Install/Metadata.pm:sub Meta { shift } $ grep -ri 'sub dispa' . ./Module-Build-0.23/lib/Module/Build/Base.pm:sub dispatch { ./Module-Build-0.23/lib/Module/Build/Platform/MacOS.pm:sub dispatch { ./Module-Build-0.23/blib/lib/Module/Build/Platform/MacOS.pm:sub dispatch { ./Module-Build-0.23/blib/lib/Module/Build/Base.pm:sub dispatch { So it's not THAT bad. Good catch. -- Aaron Sherman <[EMAIL PROTECTED]> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
A12: a doubt about .meta, .dispatcher and final methods
hello, sorry if this has been discussed before, I did a quick search in the Archive and the summaries but can't find a similar topic. I've just read A12, and while I really like the inherent orthogonality of the whole object system as it is (will be) implemented, there is something that puzzles me. from what I read, it seems that every class will implicitly call "does Dispatch" (which provides a .dispatcher method) and "is Object" (which provides a .meta method). (or more probably, class Object "does Dispatch" itself). so, if this is true, I guess I could never write a class that does: class MyClass { has LethalWeapon $.dispatcher; method meta { say "$_ is doing meta!" } } both of them would make my class pretty useless, I think, since it could not (correctly, at least) dispatch methods anymore. and I won't be able to access metadata. what would Perl6 do in such a case? I think it should complain, and probably don't let me compile such a class, but what is the underlying implementation for this? are .dispatcher, .meta (and maybe some others too) "special" methods that can't be, in any case, overloaded? and eventually, can I use a similar mechanism in my own classes, that is, write a "final" method (something like: you can derive from me however you like, but you can't redefine this method of mine)? cheers, Aldo