Re: Extending classes in a lexical scope?
- Original Message > As far as I know, "Perl6Array" should _not_ be showing up in > Perl 6's namespace, and if it is doing so, that's a reportable > bug. I was just being sloppy. I was using that in PIR, not Rakudo, and I mistyped the type -- er, I wrote the wrong class name in writing that email. Cheers, Ovid -- Buy the book - http://www.oreilly.com/catalog/perlhks/ Tech blog- http://use.perl.org/~Ovid/journal/ Twitter - http://twitter.com/OvidPerl Official Perl 6 Wiki - http://www.perlfoundation.org/perl6
Re: Extending classes in a lexical scope?
On Mon, Jan 12, 2009 at 02:02:38PM -0800, Larry Wall wrote: > > As for Perl6Array, that's a rakudo type, not a Perl 6 type, so I > can't speak for it. I'd just as soon that the name not show up in > Perl 6's namespace, if I had my druthers. As far as I know, "Perl6Array" should _not_ be showing up in Perl 6's namespace, and if it is doing so, that's a reportable bug. The only reason that Rakudo even uses "Perl6Array" instead of "Array" is that Parrot already defines an "Array" class, and as yet Parrot doesn't allow other HLLs to create classes with the same names as existing ones (TT #71). So, Rakudo works around this issue by internally prefixing some classes with "Perl6" -- but it really is intended to be purely internal. When Parrot fixes its class registry bug then we'll get rid of these internal workarounds as well. Pm
Re: Extending classes in a lexical scope?
On Mon, Jan 12, 2009 at 04:38:07PM -0800, Jon Lang wrote: : No, you don't understand me. The Foo/Bar example I was giving was : independent of your example. Rephrasing in your terms, consider the : possibility of a class that's derived from Array, for whatever reason; : call it "Ring". Now you decide that you want to redefine Array to : include a shuffle method, and so you implement an "Array version 2.0". : Would you be given a "Ring version 2.0" that derives from Array : version 2.0, or would you have to explicitly ask for it? When a Ring object refers to Array that reference is supposed to be virtual, so at least going that direction, the Ring object will be implemented in terms of Array 2.0, if that is the meaning of Array to the current object. Extending that back into BUILD time, this implies that in "class Ring is Array", the new Ring object needs to know how to make Array virtual even though the object isn't constructed yet. Neat trick, if we can pull it off... Possibly when we compile the Ring protoobject in a lexical scope with Array ::= Array:ver<2.0>, at that point we can record with the new Ring alias that any new Ring object made with that protoobject must use Array:ver<2.0>. Or something like that. For the situation to arise, the lexical scope must know about Ring objects somehow. This would handle the explicit use Ring; case, but I'm not so sure about indirect Ring objects that come in from elsewhere. They might have already been constructed with Array:ver<1.0>. Not sure what we can do about that. It doesn't seem like the kind of info you want to carry around with every object, so you end up attaching it to the type. If you get an object of two different versions, at some point you end up re-inventing version control merges for object attributes, and then you're probably just hosed. Or you just call it a "sync" and pretend it's no problem. :) Larry
Re: Extending classes in a lexical scope?
Ovid wrote: > - Original Message > >> From: Jon Lang > >> > Actually, I'd prefer to go much further than this: >> > >> > use Core 'MyCore'; >> > >> > And have that override core classes lexically. >> > >> > That solves the "but I want it MY way" issue that many Perl and Ruby >> programmers have, but they don't shoot anyone else in the foot. >> >> Since 'use' imports its elements into the current lexical scope, the >> version-based approach can do this. >> >> The only catch that I can think of has to do with derived classes: >> does the existence of a customized version of a class result in >> same-way-customized versions of the classes that are derived from the >> original class? That is, if I added an "updated" version of Foo, and >> Bar has previously been defined as being derived from Foo, would I get >> a default "updated version" of Bar as well? Or would I have to >> explicitly update each derived class to conform to the updated base >> class? > > > I'm not sure I understand you. If 'Bar' inherits from 'Foo' and 'Foo' has > extended the core Array class to lexically implement a .shuffle method, then > I would expect 'Bar' to have that also. No, you don't understand me. The Foo/Bar example I was giving was independent of your example. Rephrasing in your terms, consider the possibility of a class that's derived from Array, for whatever reason; call it "Ring". Now you decide that you want to redefine Array to include a shuffle method, and so you implement an "Array version 2.0". Would you be given a "Ring version 2.0" that derives from Array version 2.0, or would you have to explicitly ask for it? As long as you limit your use of class inheritance, the above remains manageable. But consider something like the Tk widgets implemented as a class hierarchy; then consider what happens if you reversion one of the root widgets. If you manually have to reversion each and every widget derived from it, and each and every widget derived from those, and so on and so forth, in order for your changes to the root to propagate throughout the class hierarchy... Instead, I'd rather see an approach where you need only reversion the base class and those specific derived classes where problems would otherwise arise due to your changes. -- Jonathan "Dataweaver" Lang
Re: Extending classes in a lexical scope?
On Mon, Jan 12, 2009 at 02:43:37PM -0800, Ovid wrote: : Actually, I'd prefer to go much further than this: : : use Core 'MyCore'; : : And have that override core classes lexically. We're already speccing a way to substitute a different prelude from the command line, in order to desugar -n and -p switches. There could certainly be a use-ish way to do that too. And maybe "substitute" is the wrong concept here. It probably needs to be nestable, so that we are installing an additional lexical wrapper outside the current scope, but inside whatever the previous prelude scope provided. Maybe call it "underriding" instead of "overriding". :) So given something like: #!/usr/bin/perl6 -p use prelude MyPrelude; Then OUTER of MyPrelude might be a -p looping scope, and OUTER of the -p scope might be the standard Perl 6 Prelude. And this happens a compilation time, so the compiler knows while it's parsing that any reference to Array mean MyArray, including any implicit references. The mechanism by which we freeze a snapshot of the language (nice mixed metaphor there) for the prelude is also the mechanism by which we freeze a snapshot so we know what language eval() defaults to. It doesn't default to standard Perl 6, but rather the language existing at the moment the eval is compiled, which might have little resemblence to standard Perl 6. I really do believe in lexically-scoped language mutations: it's not just a bullet point--it's what Perl 6 is Really All About, in my ever-so-humble opinion. To make that work right, every part of your lexical scope needs to know *exactly* what language it's in, including the parts that are intentionally inexact; any parts of the language that are generic need to be explicitly parameterized, not nebulously defined by some environment variable or by some rc file or even by the current perl implementation. As far as I'm concerned, everything else about Perl 6 is a bikeshed in comparison, because everything else about Perl 6 can change gracefully over time if we get this part right. The current lexical context determines the types that are visible, as well as the multimethods that are visible on those types, including the operations used to parse and mutute the language itself. Seems simple enough... :) Larry
Re: Extending classes in a lexical scope?
- Original Message > From: Jon Lang > > Actually, I'd prefer to go much further than this: > > > > use Core 'MyCore'; > > > > And have that override core classes lexically. > > > > That solves the "but I want it MY way" issue that many Perl and Ruby > programmers have, but they don't shoot anyone else in the foot. > > Since 'use' imports its elements into the current lexical scope, the > version-based approach can do this. > > The only catch that I can think of has to do with derived classes: > does the existence of a customized version of a class result in > same-way-customized versions of the classes that are derived from the > original class? That is, if I added an "updated" version of Foo, and > Bar has previously been defined as being derived from Foo, would I get > a default "updated version" of Bar as well? Or would I have to > explicitly update each derived class to conform to the updated base > class? I'm not sure I understand you. If 'Bar' inherits from 'Foo' and 'Foo' has extended the core Array class to lexically implement a .shuffle method, then I would expect 'Bar' to have that also. There are two things involved: 1. Liskov should be respected, when appropriate (http://www.oreillynet.com/onlamp/blog/2008/02/the_liskov_substitution_princi.html) 2. 'Bar' is coupled to 'Foo' and needs to know 'Foo's implementation (a charming anti-inheritance argument). See #1 :) Or did you mean something completely different? Note that Liskov is great, but has issues at times when composition is unclear. Cheers, Ovid -- Buy the book - http://www.oreilly.com/catalog/perlhks/ Tech blog- http://use.perl.org/~Ovid/journal/ Twitter - http://twitter.com/OvidPerl Official Perl 6 Wiki - http://www.perlfoundation.org/perl6
Re: Extending classes in a lexical scope?
Ovid wrote: > Actually, I'd prefer to go much further than this: > > use Core 'MyCore'; > > And have that override core classes lexically. > > That solves the "but I want it MY way" issue that many Perl and Ruby > programmers have, but they don't shoot anyone else in the foot. Since 'use' imports its elements into the current lexical scope, the version-based approach can do this. The only catch that I can think of has to do with derived classes: does the existence of a customized version of a class result in same-way-customized versions of the classes that are derived from the original class? That is, if I added an "updated" version of Foo, and Bar has previously been defined as being derived from Foo, would I get a default "updated version" of Bar as well? Or would I have to explicitly update each derived class to conform to the updated base class? -- Jonathan "Dataweaver" Lang
Re: Extending classes in a lexical scope?
- Original Message > From: Moritz Lenz > > That is the preferred way to avoid action-at-a-distance in P6. > > so if I do that, will a 'my @a' use that new Array class? > > Actually I'd prefer it if there were some kind of mechanism to set a > default implementation type, so that I could write something along these > lines: > > class MyArray is Array { ... } > use Container :Array; > > then is this lexical scope all Array declarations and all Prelude > operations that return Arrays return one of the type that I specified. Actually, I'd prefer to go much further than this: use Core 'MyCore'; And have that override core classes lexically. That solves the "but I want it MY way" issue that many Perl and Ruby programmers have, but they don't shoot anyone else in the foot. Cheers, Ovid -- Buy the book - http://www.oreilly.com/catalog/perlhks/ Tech blog- http://use.perl.org/~Ovid/journal/ Twitter - http://twitter.com/OvidPerl Official Perl 6 Wiki - http://www.perlfoundation.org/perl6
Re: Extending classes in a lexical scope?
Larry Wall wrote: > : however, I believe > : that it _is_ possible to derive a new class whose "name" differs from > : an existing class only in terms of version information, such that it > : is substituted for the original class within the lexical scope where > : it was defined, barring explicit inclusion of version information when > : the class is referenced. > > That is the preferred way to avoid action-at-a-distance in P6. so if I do that, will a 'my @a' use that new Array class? Actually I'd prefer it if there were some kind of mechanism to set a default implementation type, so that I could write something along these lines: class MyArray is Array { ... } use Container :Array; then is this lexical scope all Array declarations and all Prelude operations that return Arrays return one of the type that I specified. Cheers, Moritz
Re: Extending classes in a lexical scope?
On Mon, Jan 12, 2009 at 03:38:04AM -0800, Jon Lang wrote: : Ovid wrote: : > Is it possible to modify the core Perl6Array class like that (without extra keywords)? If so, is it possible for each programmer to make such a change so that it's lexically scoped? : : AFAIK, it is not possible to modify a core class; Well, you can always say class Array is also { ... } Classes are open by default and may only be closed by the application-level optimizer, if no one requests the class remain open permanently. However, we do not glorify monkeytyping to the extent that, say, Ruby culture does. As for Perl6Array, that's a rakudo type, not a Perl 6 type, so I can't speak for it. I'd just as soon that the name not show up in Perl 6's namespace, if I had my druthers. : however, I believe : that it _is_ possible to derive a new class whose "name" differs from : an existing class only in terms of version information, such that it : is substituted for the original class within the lexical scope where : it was defined, barring explicit inclusion of version information when : the class is referenced. That is the preferred way to avoid action-at-a-distance in P6. Larry
Re: Extending classes in a lexical scope?
Ovid wrote: > Is it possible to modify the core Perl6Array class like that (without extra > keywords)? If so, is it possible for each programmer to make such a change > so that it's lexically scoped? AFAIK, it is not possible to modify a core class; however, I believe that it _is_ possible to derive a new class whose "name" differs from an existing class only in terms of version information, such that it is substituted for the original class within the lexical scope where it was defined, barring explicit inclusion of version information when the class is referenced. -- Jonathan "Dataweaver" Lang
Extending classes in a lexical scope?
Let's say two people want to add a 'shuffle' method to all arrays. Alice wants to have it look like this: method shuffle (*...@array is rw) { @array .= pick(*); } Bob wants it to look like this: method shuffle (*...@array is rw) { @array = @array[0 .. @array/2] Z @arr...@array/2+1 .. @array]; } Thus, each wants to do the following, being able to modify the array in place: my @array = ^10; @array.shuffle; Is it possible to modify the core Perl6Array class like that (without extra keywords)? If so, is it possible for each programmer to make such a change so that it's lexically scoped? Oh, and the difference between those, for lurkers: perl6 $ perl6 -e 'my @a = ; [...@a[0..@a/2] z...@a[@a/2+...@a]].perl.say' ["a", "e", "b", "f", "c", "g"] perl6 $ perl6 -e 'my @a = ; @a .= pick(*); @a.perl.say' ["g", "a", "f", "c", "e", "d", "b"] Cheers, Ovid -- Buy the book - http://www.oreilly.com/catalog/perlhks/ Tech blog- http://use.perl.org/~Ovid/journal/ Twitter - http://twitter.com/OvidPerl Official Perl 6 Wiki - http://www.perlfoundation.org/perl6