Parrot and PGE will save the day (was Re: "as if" [Was: Selective reuse of storage in &bless.] )
On 1/20/06, Nicholas Clark <[EMAIL PROTECTED]> wrote: > On Fri, Jan 20, 2006 at 04:20:54PM -0500, Rob Kinyon wrote: > > Pros: Larry doesn't have to do anything more on the WMoT. > > Cons: The community, for some reason, really wants this > > auto-translator, even though there wasn't one for P4->P5 and P5->P6 is > > a greater leap than P4->P5 was. > > But (as I understood it) the P4->P5 leap was not intended to be so great > that a translator would be needed. In fact, that confuses cause and effect. > Because the technology wasn't there to write a translator, it constrained the > size of the leap. The important part was that for Perl 5 to still be Perl, > it had to keep running the vast majority of Perl scripts. > > In fact, Perl 5 still strives to maintain Perl 1 compatibility (and the > perl5-porters joke is that even thinking about breaking this is the fastest > way to summon the thought, er backwards compatibility police with a script > he's been running unchanged since 1987). Why else can you still: > > $ perl -le '$h{1} = "Perl"; print values h' > Perl > $ perl -le 'push a, "Perl"; print @a' > Perl Now, that's an unadvertised feature! I think I need to revisit some golfs ... > I believe that the translator is seen as needed (even by @Larry, I think) > to maintain the same level of continuity in the Perl 5->6 transition as > Perl 4->5 - your existing monolithic script runs on the newer Perl > interpreter, and you can edit (within that same file) as and when you need > to. > > Otherwise you're in the situation where you can only inter-operate languages > the whole file level. Which means that it's the same actions to migrate from > Perl 5 to (say) Python as from Perl 5 to Perl 6. And somehow I think that > $Larry has some bias about which language he'd prefer everyone to find it > easiest to migrate to, even if he's too modest to admit it. Please don't take offense at this, but I believe you're using 20th century thinking. The two most important features in Perl6 aren't -in- Perl6 - they're Parrot and the PGE. Both of them make a translator unnecessary. More precisely, they make a file-in-P5 to file-in-P6 translator unnecessary because you can have block-level interoperability. I'm making a few assumptions here: 1) Since PGE isn't part of Perl6 (because it's written in PIR), it can be used as the parser/lexer/etc. for any language, not just Perl6. 2) Since PGE can be lexically-scoped, one can change the entire grammar within a given block, including how variables are referenced, subroutines are called, etc. 3) Since everything is, at the heart, just a PMC, so long as the appropriate PIR is emitted, it doesn't matter how the userside code is written so long as the right parser/lexer/whatever is used to translate it to PIR. So, if all three assumptions hold, then your monolithic Perl5 script can easily inline any Parrot-targeted language you want, simply by doing the following: 1) Use Ponie. 2) Within a block, import the appropriate PGE module(s) to redefine the grammar to P6 and do what you need to do. No translator needed. Rob
perl6-language@perl.org
Larry Wall wrote: > On Fri, Jan 20, 2006 at 09:35:13PM +0800, Audrey Tang wrote: > My original intent was #2, hence the wording in A12. But to speak to > some of Stevan's concernes, there's something going on here which is > not quite "Object does Hash". It's more like "Object can do Hash", > in the linguistic sense that a "Noun can do Verb", but nonetheless > remains a noun. A fallback role is not the same as a normal role. > Maybe there's some way to mixin in a fallback Hash role without > clobbering a real Hash role that is already there, so that if your > Hash container is an object you don't see methods for its keys. > > Something like this might also let us distinguish p5ish scalars that > are simultaneously Num and Str from scalars that, say, intrinsically > do Num but can emulate Str in a pinch without caching the result. > I don't think we have a good way of expressing that distinction right > now. I agree it is a hairy subject, but the more I think about this (and the more i read about and play with CLOS) I think we might be able to accomplish something very close to this by creating more special purpose attribute meta-objects. By moving much of the actual attribute accessing work to the attribute meta-object, we can very easily have arbitrary object "types" since all their access is mediated through the attribute meta-object. In CLOS this would be accomplished by subclassing the standard-class, and telling it to use the different attribute meta-object by default. The of course you slap a juicy LISP macro around it, and you are ready to go. Mm LISP macros :) Basically my point is that the meta-classes and meta-objects govern the behavior of the classes and object. So if we want to change the behavior of our classes and objects, we just subclass the meta-classes and meta-objects and specialize the behavior as we desire. > This seems to imply that a given role like Hash could have two default > implementations--one for an actual Hash container, and one that emulates > a Hash by deferring to the Object. It's sort of like a role that can > delegate back to its own object. This should all be possible with attribute meta-objects. Basically when we encounter this type of need (in p5->p6 translated classes, or otherwise), the compiler (or possibly the translator) needs to discover this need, and change the metaclass appropriately. The self delegation then Just Works. Of course this is all just hand-waving right now since the current metamodel does not support such deep magic. But hey, I have been thinking it might be time for a v3 soon anyway :) > Such issues arise whenever you start making statements of the form > "I want to use an A as if it were a B." The problem is much bigger > than just how do I translate Perl 5 to Perl 6. It's questions like: > > What makes a particular metaphor work? > Will the cultural context support use of an A as if it were a B? > How do we translate the user's thoughts to the computer's thoughts? > How do we translate one user's thoughts to another user's thoughts? > How do we know when such a translation is "good enough"? > How do we know when our mental model of an object is adequate? > How do we know when the computer's mental model of an object is adequate? > What does adequate mean in context? I am actually working with Rob Kinyon on a meta object protocol for Perl 5 for our $work. It does not try to make Perl 5 anything it is not, instead it only attempts to define the workings of the Perl 5 object system and provide clean hooks into it. It is in the very early stages, and needs lots of testing, but it might help to bridge the two models. > Will the culture support partially instantiated objects? :-) Hmm, do you mean lazy objects? As in, only instantiated as much as is absolutly necessary at a particular moment? I recently read a paper on an extended version of CLOS (yay CLOS) which demonstrated how lazy classes could be built, including ones with strict initialization orders ($a must be initialized before $b, but $b depends on $c, etc). But maybe this is not what you mean. Or is this the "class but undef" idea again? Audrey and I have "solved" this by creating a 'p6undef' repr type which allows the class to be instantiated and methods called on it, but if you try to access anything other than basic meta information, it will fail (because it's just undef). Actually, I think this partial object thing needs it own thread really. But I will let you decide when you are ready for that one :) Stevan
perl6-language@perl.org
> On Thursday 19 January 2006 21:53, Stevan Little wrote: > > With p5, you /can/ get to the underlying data structure. This is a > > break which will hamper the backwards compatibility effort I think. > > With Perl 5, you can *appear* to get to the underlying data structure. Yet > tie() is basically free on Ponie and there's a metaclass mediating access to > the underlying storage. I think that makes the problem solvable. Excellent. > (Does using an alternate type of storage mean you need an alternate metaclass? > Perhaps, perhaps not -- but the practical effects of syntax have to come from > somewhere.) Actually I was thinking this might be the best approach. I have been dabbling more and more with CLOS lately and am not seeing where a full-fledge attribute meta-object is probably a really good idea (in the current model the meta-attribute is very very slim). > As long as you can use Perl 5 classes in Perl 6 without rewriting all of the > Perl 5 code, I'm happy. Yes, this is the ultimate goal. I never wanted to get rid of &bless, only to resolve what I saw as an inconsistency with the use of &bless and some of the other aspects of the Perl 6 design. Stevan
perl6-language@perl.org
On 1/21/06, Larry Wall <[EMAIL PROTECTED]> wrote: > But maybe all this is already possible in the current setup, if > > role ObjectFakeHash does Hash {...} > role Object does ObjectFakeHash {...} > class Hash does Hash {...} Yes, I think that's the way to go, as well as :coerce for explicit class-based (instead of role-based) conversions. Audrey
perl6-language@perl.org
On Fri, Jan 20, 2006 at 04:20:54PM -0500, Rob Kinyon wrote: > Pros: Larry doesn't have to do anything more on the WMoT. > Cons: The community, for some reason, really wants this > auto-translator, even though there wasn't one for P4->P5 and P5->P6 is > a greater leap than P4->P5 was. But (as I understood it) the P4->P5 leap was not intended to be so great that a translator would be needed. In fact, that confuses cause and effect. Because the technology wasn't there to write a translator, it constrained the size of the leap. The important part was that for Perl 5 to still be Perl, it had to keep running the vast majority of Perl scripts. In fact, Perl 5 still strives to maintain Perl 1 compatibility (and the perl5-porters joke is that even thinking about breaking this is the fastest way to summon the thought, er backwards compatibility police with a script he's been running unchanged since 1987). Why else can you still: $ perl -le '$h{1} = "Perl"; print values h' Perl $ perl -le 'push a, "Perl"; print @a' Perl I believe that the translator is seen as needed (even by @Larry, I think) to maintain the same level of continuity in the Perl 5->6 transition as Perl 4->5 - your existing monolithic script runs on the newer Perl interpreter, and you can edit (within that same file) as and when you need to. Otherwise you're in the situation where you can only inter-operate languages the whole file level. Which means that it's the same actions to migrate from Perl 5 to (say) Python as from Perl 5 to Perl 6. And somehow I think that $Larry has some bias about which language he'd prefer everyone to find it easiest to migrate to, even if he's too modest to admit it. Nicholas Clark
perl6-language@perl.org
I have to wonder how many other people just edited /usr/share/games/fortune/perl and added: % Humans are not much into strong compile-time typing, and when they are, we call it stereotyping, or racism, or whatever. -- Larry Wall in <[EMAIL PROTECTED]> And now back to your regularly scheduled meaningful discussion already in progress. -- Jeff Stampes [ [EMAIL PROTECTED] ] -- Build and Release Tools The older a man gets, the farther he had to walk to school as a boy.
perl6-language@perl.org
On Thursday 19 January 2006 21:53, Stevan Little wrote: > Okay, so when you say alternate storage then you mean that a class > like this: > > class Foo { > has $.bar; > method new ($class, %params) { > $class.bless('p5Hash', %params); > } > method baz { > $.bar += 1; > } > } > > should use a PMC representation of a p5 hash as it's storage, and > that the method baz does the right thing here? Yes. > Because that makes sense to me. However, what doesn't make sense > would be if I had to write &baz like this: > > method baz { > self->{'bar'} += 1; > } > > In other words, if this is just a detail of the storage, and does not > affect user code at all, then I am okay with it. This though would > mean that you would not have direct access to the underlying data > structure (the p5 hash). I don't think it's impossible, but it's fairly ugly and I'm okay if you can't do it by default from the Perl 6 side. I certainly wouldn't use it. From the Perl 6 side, I would rather use Perl 6 looking code. > Okay, then I assume you mean it to behave the same way as with the > p5hash, that it is completely transparent to the user that you are > using a p5hash or a p6hash or a p6opaque? From Perl 6? Yes. > In which case,.. I say okay. But note again that you have not > provided access to the underlying data structure (the p6hash a.k.a - > an instance of ^Hash). Agreed. > With p5, you /can/ get to the underlying data structure. This is a > break which will hamper the backwards compatibility effort I think. With Perl 5, you can *appear* to get to the underlying data structure. Yet tie() is basically free on Ponie and there's a metaclass mediating access to the underlying storage. I think that makes the problem solvable. (Does using an alternate type of storage mean you need an alternate metaclass? Perhaps, perhaps not -- but the practical effects of syntax have to come from somewhere.) As long as you can use Perl 5 classes in Perl 6 without rewriting all of the Perl 5 code, I'm happy. -- c
perl6-language@perl.org
On Friday 20 January 2006 07:14, Rob Kinyon wrote: > I think this entire issue is rising out of the fact that very very few > people in this discussion are familiar with the design of the MOP. > Stevan and a few others are the primary movers and I'm lucky enough to > have been Stevan's sounding board for a few pieces. Once you grok the > MOP, it's really hard to imagine wanting to use bless(). I don't think that it's a fair assumption that, for example, I haven't followed the metamodel discussions and designs. Nor do I think it's a fair assumption that people who want to interoperate with a lot of Perl 5 code should have to understand the finer points of metamodels and metaobject protocols in the default case. -- c
perl6-language@perl.org
On 1/20/06, Larry Wall <[EMAIL PROTECTED]> wrote: [snip really cool blathering] I don't have much to say on the deeper question, but I have a few ideas on the P5 -> P6 translation question, especially as it relates to OO: 1) Don't translate at all. Ponie, delegating to Parrot, is supposed to handle all of that OO garbage in the same way that Ruby and Python are going to interact with Perl6. Perl5 and Perl6 are as similar as Ruby and Python, so you might as well write a translator between them as one between Perl5 and Perl6. Pros: Larry doesn't have to do anything more on the WMoT. Cons: The community, for some reason, really wants this auto-translator, even though there wasn't one for P4->P5 and P5->P6 is a greater leap than P4->P5 was. 2) Don't attempt to translate $x->{whatever} (or $x->[2] or $x->('whatever') ... ) in isolation. If it occurs within a function defined in a package that has a function that uses bless and it's the first parameter, it's an attribute access. Otherwise, it's a hash access. Pros: It's a nice and easy rule which will work if the programmer didn't violate encapsulation, only puts methods in classes, and is generally an all-around nice guy. Cons: See Pros. 3) Since about half of all classes in P5-land use some module in Class::* to auto-generate stuff (thus providing a nice place to find all the attribute names), ask the community to provide a translator for each of those. Then, use #2 for the others. Pros: The WMoT can punt in about half the cases. Cons: The WMoT cannot punt in about half the cases. Rob
perl6-language@perl.org
On Fri, Jan 20, 2006 at 09:35:13PM +0800, Audrey Tang wrote: : Note that A12 used to say that all Objects does Hash, and %$obj even : returns private attributes when used inside the class scope. : Fortunately, S12 doesn't mention anything like that, so I think the : treatment above is safe. We still need something to bridge that gap, whether that particular mechanism is available or not. The p5-to-p6 translator needs to figure out what to do with things like this: $x->{whatever} In isolation, we can't know whether that should translate to $x or $x.whatever So either p5-to-p6 does type inferencing (from some very dynamic p5 code!) or we fudge it to emit some construct that defers the decision to p6, at either compile time or run time, but p6 compile time still only works if we have a compile-time typed $x, which is likely to be undecidable for a lot of code coming from the p5 universe. On the assumption that p6 has to make the decision then, we have three alternatives: Write $x.whatever, fall back to hash subscript on method call failure Write $x, fall back to method call on non-hash Write $x.punt('whatever'), and take an extra redispatch hit every time My original intent was #2, hence the wording in A12. But to speak to some of Stevan's concernes, there's something going on here which is not quite "Object does Hash". It's more like "Object can do Hash", in the linguistic sense that a "Noun can do Verb", but nonetheless remains a noun. A fallback role is not the same as a normal role. Maybe there's some way to mixin in a fallback Hash role without clobbering a real Hash role that is already there, so that if your Hash container is an object you don't see methods for its keys. Something like this might also let us distinguish p5ish scalars that are simultaneously Num and Str from scalars that, say, intrinsically do Num but can emulate Str in a pinch without caching the result. I don't think we have a good way of expressing that distinction right now. This seems to imply that a given role like Hash could have two default implementations--one for an actual Hash container, and one that emulates a Hash by deferring to the Object. It's sort of like a role that can delegate back to its own object. For simplicity, we might prefer to leave the Hash role alone as a normal hash, and provide some way of registering emulation fallback capabilities, in a tie-ish sort of way, but tied to types instead of to individual containers, so you could know to look for a FakeHash role or some such. But rather than forcing people to register fallbacks, it might be a lot nicer to establish some intrinsic relationship between a role actually does the thing and a role that merely fakes it in terms of something else. But maybe all this is already possible in the current setup, if role ObjectFakeHash does Hash {...} role Object does ObjectFakeHash {...} class Hash does Hash {...} So ObjectFakeHash would just grab the Hash interface but override the default implementation. I think that would give us the fallback semantics I'm looking for without doing great violence to anything else. But maybe someone can come up with a better way. Maybe we can come up with some kind of lexically scoped solution instead, if we decide it's just a language emulation issue. But my hunch is that it's a deep tagmemic/metaphorical problem we're trying to solve here. Such issues arise whenever you start making statements of the form "I want to use an A as if it were a B." The problem is much bigger than just how do I translate Perl 5 to Perl 6. It's questions like: What makes a particular metaphor work? Will the cultural context support use of an A as if it were a B? How do we translate the user's thoughts to the computer's thoughts? How do we translate one user's thoughts to another user's thoughts? How do we know when such a translation is "good enough"? How do we know when our mental model of an object is adequate? How do we know when the computer's mental model of an object is adequate? What does adequate mean in context? Will the culture support partially instantiated objects? :-) That's tagmemics, folks. The main problem with tagmemics is that, while it helps you ask good questions, it doesn't give you easy answers for 'em... Anyway, I'd still kinda like to find some way to use an object "as if" it were a hash, partly to solve my immediate problem, but also because I think a good computer language might address the "as if" problem better than any of them do currently. In general, hypotheticality is still something that humans are much better at than computers. We're still just nipping around the edges with "fail", "let", environmental variables, STM, roles, and junctions. But we'll not get true AI until a computer can understand a sentence like In a hole in the ground there lived a hobbit. as if it were a human. A human has the ability to exec
perl6-language@perl.org
On 1/19/06, chromatic <[EMAIL PROTECTED]> wrote: > On Thursday 19 January 2006 19:50, Rob Kinyon wrote: > > > Nothing. Just like it's not a problem if Perl6 uses one of the > > Ruby-specific PMCs for storage. In fact, the alternate $repr idea is > > specifically to allow for the use of foreign datatypes as storage. > > Luke's excellent example is to use a C-struct as your storage. > > ... but ... > > > Storage of what? What are you trying to do that you need to use an > > object to store your attributes? Why aren't you just using the method > > -that- object is using? > > I can't reconcile these two paragraphs. The second paragraph was referring solely to where you're dealing with Parrot datatypes only. If you have to go outside of Parrot (to a C lib, for instance), then you do need to know about the storage specifics. > > No. My objection to bless() is BUILD() and CREATE(). There's already a > > mechanism in the P6 OO system for specifying the internal > > representation of the instance. > > This is Perl. The "there should be one obvious way to do it" ship, canoe, > raft, and water wings have sailed, paddled, floated, and inflated. And there is. You can create your own meta-object protocol on top of p6opaque or any other representation you want. This is *Perl6* - you can rewrite the whole damn grammar if you want to. You can use another VM if you want to. (PIL^N runs on Javascript!) I think this entire issue is rising out of the fact that very very few people in this discussion are familiar with the design of the MOP. Stevan and a few others are the primary movers and I'm lucky enough to have been Stevan's sounding board for a few pieces. Once you grok the MOP, it's really hard to imagine wanting to use bless(). It's literally like trying to explain to a BASIC programmer why recursion is good or trying to explain to a C programmer why automatic memory management is handy. The frames of reference are so different that the meaning being trasmitted is not the meaning being received. Rob
Re: Perl 6's &bless is (seriously) broken
On 1/20/06, Juerd <[EMAIL PROTECTED]> wrote: > Note, by the way, that JS has "primitive" strings, and Strings, only the > latter being objects. Fortunately for us, though, a string is > automatically promoted to a String when the string is USED AS an object. In other words, according to userland, everything is an object. > > But, if you must use the WMoT, then I suspect the following will happen: > > 1) The WMoT notices your use of &bless and marks that package as a > > class and that method as a constructor. > > 2) It creates a Perl6 class for your use, noting the accesses into > > the Perl5 reference that you used and calling those attributes. > > 3) It then creates your BUILD() method, putting all the non-bless > > components of your new() into it. > > Doesn't solve the problems as mentioned in this thread, like overlapping > methods. Yeah it does because all $repr's are p6opaque with direct access being converted into attribute access. No method overlap. Rob
perl6-language@perl.org
Stevan Little wrote: >> I realize one of Stevan's objections is "But if you use a Hash, does your >> object automatically support the .keys method and .kv and so on?" to >> which I >> reply "No, of course not. That's silly. It just uses the Hash for >> *storage*." >> Is that your objection to bless()? > > Yes, that is my objection, because while the alternate storage approach > discussed above is actually a very interesting feature, it does not fit > with the p5 vision of &bless. > > With p5, you /can/ get to the underlying data structure. This is a break > which will hamper the backwards compatibility effort I think. It is possible to have one's cake and eat it too. Consider: Foo.bless($x) where $x contains an Bar object. We can check if Foo is a subtype to Bar -- for example, Foo.bless({some => 'hash'}) would check whether Foo conforms to the Hash interface. If so, then we safely reuse the underlying representation for storage: class Foo does Hash { has $.a; has $.b } my %args = (a => 1, b => 2); my $obj = Foo.bless(%args); %args.{'a'} = 999; say $obj.a; # 999 say $obj.{'a'}; # 999 If not, we explode $x into named arguments and dispatch to .CREATE to make an p6opaque representation. Hash and Array are thus turned to pairs; a Scalar would have to contain an arglist or a pair, otherwise it'd fail the named-only prototype check. To wit: class Bar { has $.a; has $.b } my %args = (:a<1>, :b<2>); my $obj = Bar.bless(%args); %args.{'a'} = 999; say $obj.a; # 1, not 999 say $obj.{'a'}; # Error -- no such method: postcircumfix:<{ }> Note that A12 used to say that all Objects does Hash, and %$obj even returns private attributes when used inside the class scope. Fortunately, S12 doesn't mention anything like that, so I think the treatment above is safe. Audrey signature.asc Description: OpenPGP digital signature
Re: Class methods vs. Instance methods
[EMAIL PROTECTED] wrote: : class Dog { : method tail { "brown and short" } : }; : : class Chihuahua is Dog { : has $.color; : method tail { $.color _ " and short" } : }; : : You can say Dog.tail, Dog.new.tail, Chihuahua.new.tail, but not : Chihuahua.tail. That's extremely counter-intuitive. I don't think it's counterintuitive. You've defined Dog with an invariant .tail but not Chihuahua. It's doing exactly what you asked for under a prototype view of reality. Except there are no such things as classes in a prototype view of reality. Everything is an instance and there are no such things as class methods. The entire idea that an object (::Dog) can call methods that are for another object ($fido) is ... well ... it's a little off. That's like saying any object can call any method from any other object so long as that method is invariant. In a prototype-instance system, instance(Dog) isa class(Dog) instance(Chihuahua) isa class(Chihuahua) isa class(Dog) instance(Chihuahua) isa instance(Dog) Note that instances inherit doubly, from own class and from parent's instance. But this does not imply that: class(Chihuahua) isa instance(Dog) So I don't see a problem. Miro