Re: Vocabulary
On Dec 16, 2003, at 10:20 PM, Rafael Garcia-Suarez wrote: There's a need (more or less) for special blocks that can be run at the end of the compilation phase of any arbitrary compilation unit. This would be especially useful in an environment such as mod_perl, where CHECK and INIT blocks currently _never_ execute, no matter when they're declared. Regards, David -- David Wheeler AIM: dwTheory [EMAIL PROTECTED] ICQ: 15726394 http://www.kineticode.com/ Yahoo!: dew7e Jabber: [EMAIL PROTECTED] Kineticode. Setting knowledge in motion.[sm]
Re: Vocabulary
On Dec 17, 2003, at 1:39 AM, Simon Cozens wrote: The desire to optimize the hell out of Perl 6 is a good one, but surely you optimize when there is a problem, not when before. Is there a problem with the speed you're getting from Perl 6 at the moment? Yes, it's taking too long to be released! ;-) Regards, David (Who wants to start writing Perl 6 applications yesterday.) -- David Wheeler AIM: dwTheory [EMAIL PROTECTED] ICQ: 15726394 http://www.kineticode.com/ Yahoo!: dew7e Jabber: [EMAIL PROTECTED] Kineticode. Setting knowledge in motion.[sm]
Re: Vocabulary
On Wed, Dec 17, 2003 at 06:20:22AM -, Rafael Garcia-Suarez wrote: : Larry Wall wrote in perl.perl6.language : : On Wed, Dec 17, 2003 at 12:11:59AM +, Piers Cawley wrote: : : When you say CHECK time, do you mean there'll be a CHECK phase for : : code that gets required at run time? : : Dunno about that. When I say CHECK time I'm primarily referring : to the end of the main compilation. Perl 5 appears to ignore CHECK : blocks declared at run time, so in the absence of other considerations : I suspect Perl 6 might do the same. : : This has proven to be inconvenient except for a few specialized usages, : such as the B::/O compiler framework. : : There's a need (more or less) for special blocks that can be run at the : end of the compilation phase of any arbitrary compilation unit. Well, if you want to run at the end of the current compilation unit, a BEGIN block at the end is close to what you want. Admittedly, the BEGIN block can't easily *know* that it's the last thing... That's not to say we can't improve the semantics of CHECK and INIT. Larry
Re: Vocabulary
Larry Wall [EMAIL PROTECTED] writes: On Wed, Dec 17, 2003 at 12:11:59AM +, Piers Cawley wrote: : When you say CHECK time, do you mean there'll be a CHECK phase for : code that gets required at run time? Dunno about that. When I say CHECK time I'm primarily referring to the end of the main compilation. Perl 5 appears to ignore CHECK blocks declared at run time, so in the absence of other considerations I suspect Perl 6 might do the same. I feared that might be the case. -- Beware the Perl 6 early morning joggers -- Allison Randal
Re: Vocabulary
[EMAIL PROTECTED] (Michael Lazzaro) writes: Well, just for clarification; in my anecdotal case (server-side web applications), the speed I actually need is as much as I can get, and all the time. Every N cycles I save represents an increase in peak traffic capabilities per server, which is, from a marketing perspective, essential. The desire to optimize the hell out of Perl 6 is a good one, but surely you optimize when there is a problem, not when before. Is there a problem with the speed you're getting from Perl 6 at the moment? -- evilPetey I often think I'd get better throughput yelling at the modem.
RE: Vocabulary
Michael Lazzaro wrote: I don't think so; we're just talking about whether you can extend a class at _runtime_, not _compiletime_. Whether or not Perl can have some degree of confidence that, once a program is compiled, it won't have to assume the worst-case possibility of runtime alteration of every class, upon every single method call, just in case you've screwed with something. That's a cute way of glossing over the problem. How do you truly know when runtime is in the first place? Imagine an application server which parses and loads code from files on-demand. This shouldn't be difficult. Imagine that that code references a system of modules. Imagine if Perl finalizes classes after primary compilation (after parsing, say, an ApacheHandler file), and proceeds to behave quite differently indeed afterwards. Imagine that a perfectly innocent coder finds that his class library doesn't run the same (doesn't run at all) under the application server as it does when driven from command line scripts: His method overrides don't take effect (or, worse, Perl tells him he can't even compile them because the class is already finalized! And he thought Perl was a dynamic language!). What's his recourse? Nothing friendly. Tell Perl that he's going to subclass the classes he subclasses? Why? He already subclasses them! Isn't that tell enough? And how? Some obscure configuration file of the application server, no doubt. And now the app server needs to be restarted if that list changes. His uptime just went down. And now he can't have confidence that his system will continue to behave consistently over time; apachectl restart becomes a part of his development troubleshooting lexicon. Java doesn't make him do that; HotSpot can make this optimization at runtime and back it out if necessary. Maybe he'll just write a JSP instead. C# and VB.NET do likewise. ASP.NET isn't looking so bad, either. The .NET Frameworks are sure a lot less annoying than the Java class library, after all. Point of fact, for a large set of important usage cases, Perl simply can't presume that classes will EVER cease being introduced into the program. That means it can NEVER make these sorts of optimizations unless it is prepared to back them out. Even in conventional programs, dynamic class loading is increasingly unavoidable. Forcing virtuous programmers to declare virtual (lest their program misbehave or their perfectly valid bytecode fail to load, or their perfectly valid source code fail to compile) is far worse than allowing foolish programmers to declare final. Making semantic distinctions of this scale between compile time and runtime will be a significant blow to Perl, which has always been strengthened by its dynamism. Its competitors do not include such artifacts; they perform class finalization optimizations on the fly, and, despite the complexity of the task, are prepared to back out these optimizations at runtime--while the optimized routines are executing, if necessary. Yes, this requires synchronization points, notifications (or inline checks), and limits code motion. Better than the alternative, I say. It is very simply a huge step backwards to create a semantic wall between primary compilation and program execution. So write the complicated code to make it work right. - or - Take the performance hit and go home. Dynamism has a price. Perl has always paid it in the past. What's changed? -- Gordon Henriksen IT Manager ICLUBcentral Inc. [EMAIL PROTECTED]
Re: Vocabulary
On Wed, Dec 17, 2003 at 06:20:22AM -, Rafael Garcia-Suarez wrote: : Larry Wall wrote in perl.perl6.language : : On Wed, Dec 17, 2003 at 12:11:59AM +, Piers Cawley wrote: : : When you say CHECK time, do you mean there'll be a CHECK phase for : : code that gets required at run time? : : Dunno about that. When I say CHECK time I'm primarily referring : to the end of the main compilation. Perl 5 appears to ignore CHECK : blocks declared at run time, so in the absence of other considerations : I suspect Perl 6 might do the same. : : This has proven to be inconvenient except for a few specialized usages, : such as the B::/O compiler framework. : : There's a need (more or less) for special blocks that can be run at the : end of the compilation phase of any arbitrary compilation unit. Well, that's what I'd call an other consideration. :-) Larry
Re: Vocabulary
On Tue, Dec 16, 2003 at 06:55:56PM -0500, Gordon Henriksen wrote: : Michael Lazzaro wrote: : : I don't think so; we're just talking about whether you can extend a : class at _runtime_, not _compiletime_. Whether or not Perl can have : some degree of confidence that, once a program is compiled, it won't : have to assume the worst-case possibility of runtime alteration of : every class, upon every single method call, just in case : you've screwed with something. : : That's a cute way of glossing over the problem. : : How do you truly know when runtime is in the first place? Imagine an : application server which parses and loads code from files on-demand. : This shouldn't be difficult. Imagine that that code references a : system of modules. : : Imagine if Perl finalizes classes after primary compilation : (after parsing, say, an ApacheHandler file), and proceeds to behave : quite differently indeed afterwards. : : Imagine that a perfectly innocent coder finds that his class : library doesn't run the same (doesn't run at all) under the : application server as it does when driven from command line scripts: : His method overrides don't take effect (or, worse, Perl tells him he : can't even compile them because the class is already finalized! And : he thought Perl was a dynamic language!). : : What's his recourse? Nothing friendly. Tell Perl that he's going : to subclass the classes he subclasses? Why? He already subclasses : them! Isn't that tell enough? And how? Some obscure configuration : file of the application server, no doubt. And now the app server needs : to be restarted if that list changes. His uptime just went down. And : now he can't have confidence that his system will continue to behave : consistently over time; apachectl restart becomes a part of his : development troubleshooting lexicon. Any such application server would probably just use DYNAMIC_EVERYTHING; (or whatever we call it) and have done with it. : Java doesn't make him do that; HotSpot can make this optimization at : runtime and back it out if necessary. Maybe he'll just write a JSP : instead. If Parrot turns out to be able to make this optimization, then the individual declarations of dynamism merely become hints that it's not worth trying to optimize a particular class because it'll get overridden anyway. It's still useful information on an individual class basis. The only thing that is bogus in that case is the global DYNAMIC_EVERYTHING declaration in the application server. So I could be argued into making that the default. A program that wants a static analysis at CHECK time for speed would then need to declare that. The downside of making that the default is that then people won't declare which classes need to remain extensible under such a regime. That's another reason such a declaration does not belong with the class itself, but with the users of the class. If necessary, the main program can pick out all the classes it things need to remain dymanic: module Main; use STATIC_CLASS_CHECK; use class Foo is dynamic; use class Bar is dynamic; or whatever the new Cuse syntax will be in A11... : C# and VB.NET do likewise. ASP.NET isn't looking so bad, either. The : .NET Frameworks are sure a lot less annoying than the Java class : library, after all. On the other hand, those guys are also doing a lot more mandatory static typing to get their speed, and that's also annoying. (Admittedly, they're working on supporting dynamic languages better.) : Point of fact, for a large set of important usage cases, Perl simply : can't presume that classes will EVER cease being introduced into the : program. That means it can NEVER make these sorts of optimizations : unless it is prepared to back them out. Even in conventional programs, : dynamic class loading is increasingly unavoidable. Forcing virtuous : programmers to declare virtual (lest their program misbehave or : their perfectly valid bytecode fail to load, or their perfectly valid : source code fail to compile) is far worse than allowing foolish : programmers to declare final. The relative merit depends on who declares the final, methinks. But if we can avoid both problems, I think we should. : Making semantic distinctions of this scale between compile time : and runtime will be a significant blow to Perl, which has always been : strengthened by its dynamism. Its competitors do not include such : artifacts; they perform class finalization optimizations on the fly, : and, despite the complexity of the task, are prepared to back out these : optimizations at runtime--while the optimized routines are executing, : if necessary. Yes, this requires synchronization points, notifications : (or inline checks), and limits code motion. Better than the : alternative, I say. It is very simply a huge step backwards to : create a semantic wall between primary compilation and program : execution. : : So write the complicated code to make it work
Re: Vocabulary
Michael Lazzaro writes: On Sunday, December 14, 2003, at 06:14 PM, Larry Wall wrote: But the agreement could be implied by silence. If, by the time the entire program is parsed, nobody has said they want to extend an interface, then the interface can be considered closed. In other words, if you think you *might* want to extend an interface at run time, you'd better say so at compile time somehow. I think that's about as far as we can push it in the final direction. That seems a very fair rule, especially if it adds a smidge more speed. Runtime extension will likely be very unusual Unless you're me. Or Damian. Or a fair number of other programmers who like to dive into the Perl Dark Side on a regular basis. -- requiring it to be explicit seems reasonable. It seems so. Knowing Larry, I'm sure this is an ungrounded fear, but I definitely want to be able to declare in a module I'm going to be screwing with stuff; keep out of my way, so that I don't impose any awkward declarations on my module users. If that request can be made more explicit in the cases where that's possible, great, but the general declaration should be available. Luke I'm probably spouting nonsense. I just hope it's good-sounding nonsense... It's beyond good-sounding, it's frickin' awesome. MikeL
Re: Vocabulary
On Tue, Dec 16, 2003 at 07:05:19AM -0700, Luke Palmer wrote: : Michael Lazzaro writes: : : On Sunday, December 14, 2003, at 06:14 PM, Larry Wall wrote: : But the agreement could be implied by silence. If, by the time the : entire program is parsed, nobody has said they want to extend an : interface, then the interface can be considered closed. In other : words, if you think you *might* want to extend an interface at run : time, you'd better say so at compile time somehow. I think that's : about as far as we can push it in the final direction. : : That seems a very fair rule, especially if it adds a smidge more speed. : Runtime extension will likely be very unusual : : Unless you're me. Or Damian. Or a fair number of other programmers who : like to dive into the Perl Dark Side on a regular basis. : : -- requiring it to be explicit seems reasonable. : : It seems so. Knowing Larry, I'm sure this is an ungrounded fear, but I : definitely want to be able to declare in a module I'm going to be : screwing with stuff; keep out of my way, so that I don't impose any : awkward declarations on my module users. If that request can be made : more explicit in the cases where that's possible, great, but the general : declaration should be available. Okay, we'll call the general declaration: use $ or some such. :-) Seriously, I hope we can provide a framework in which you can screw around to your heart's content while modules are being compiled, and to a lesser extent after compilation. But we'll never get to a programming-in-the-large model if we can't limit most of the screwing around to the lexical scope currently being compiled, or at least to a known subset of the code. Modules that turn off optimization for all other modules are going to be about as popular as $. So the general declaration should probably be something easy to see like: use STRANGE_SEMANTICS_THAT_SLOW_EVERYONE_DOWN; That will encourage people to be more specific about what they want to pessimize. Certainly, your fancy module should be encouraged to declare these things on behalf of its users if it can. I'm not suggesting that Lukian or Damianly modules force such declarations onto the users unless it's impossible for the module to know. And it seems to me that with sufficient control over the user's grammar, you can often get that information into your own fancy module somehow. Might take a few macros though, or analysis of the user's code at CHECK time (or maybe just before). And in general, it's probably not necessary to declare all the new interfaces, but only those interfaces known at compile time that want to stay open. Any interfaces added at run time are probably assumed to be open. So in some cases you might find yourself deriving a single open class at compile time from which you can derive other open classes later. But still, the principle remains that original declarer of an interface doesn't know in general whether its users are going to want to extend it. At some point the users have to take responsibility if they want their code to run fast. Or run at all... So we need to make it very easy for users to provide this kind of information when it's needed. Larry
Re: Vocabulary
On Tuesday, December 16, 2003, at 09:07 AM, Larry Wall wrote: Seriously, I hope we can provide a framework in which you can screw around to your heart's content while modules are being compiled, and to a lesser extent after compilation. But we'll never get to a programming-in-the-large model if we can't limit most of the screwing around to the lexical scope currently being compiled, or at least to a known subset of the code. Modules that turn off optimization for all other modules are going to be about as popular as $. So the general declaration should probably be something easy to see like: use STRANGE_SEMANTICS_THAT_SLOW_EVERYONE_DOWN; That will encourage people to be more specific about what they want to pessimize. Certainly, your fancy module should be encouraged to declare these things on behalf of its users if it can. I'm not suggesting that Lukian or Damianly modules force such declarations onto the users unless it's impossible for the module to know. And it seems to me that with sufficient control over the user's grammar, you can often get that information into your own fancy module somehow. Might take a few macros though, or analysis of the user's code at CHECK time (or maybe just before). And in general, it's probably not necessary to declare all the new interfaces, but only those interfaces known at compile time that want to stay open. Any interfaces added at run time are probably assumed to be open. So in some cases you might find yourself deriving a single open class at compile time from which you can derive other open classes later. Exactly, assuming I correctly understand. :-) My own first instinct would be that the run-time extensibility of a particular interface/class would simply be a trait attached to that class... by default, classes don't get it. By limiting or not limiting the amount of runtime screwin' around you can do with the class, it is therefore able to control the level of optimization that calls to methods, etc., are given -- but specific to that particular interface/class, not to the module and certainly not to the program in general. class Wombat is runtime_extensible { ... }; So everything is closed, except the specific classes which are not. Even when you are (to use an example from my own code) making runtime subclasses on-the-fly, you're almost always starting from some common base class. (And 'almost' is probably an unneeded qualifier, there. As is 'probably'.) As far as users of your class being able to specify that they want something runtime-extensible, when your original module didn't call for it, I don't see that as a problem, if they can just add the trait to your class shortly after they Cuse the package containing it, if such things are possible -- or, for that matter, simply subclass your original into a runtime_extensible class: class Wombat { ... }; # Not runtime extensible class MyWombat is Wombat is runtime_extensible { ... }; # Runtime extensible Now, it might be that declaring MyWombat to be runtime_extensible actually silently disables some compile-time optimizations not only for it, but for all its superclasses/roles/etc., depending on how intelligent and far reaching those optimizations may be. Not sure. Still, the fact that you are _requesting_ that happen is specific to the particular class that needs it -- and should be associated with that class, such that if that class later falls into disuse, the optimizations silently reappear. (At first glance, I am less sure of the need to have similar functionality for entire modules, as opposed to classes, but perhaps someone out there can come up with an example.) MikeL
Re: Vocabulary
On Tue, 2003-12-16 at 12:06, Michael Lazzaro wrote: My own first instinct would be that the run-time extensibility of a particular interface/class would simply be a trait attached to that class... by default, classes don't get it. That doesn't sound very dynamic. At the post-OSCON design meetings, Larry suggested that the user of a class or library could say I'm not going to muck about with this at runtime and any extra optimization would be nice, so go ahead and do whatever you can do it. Putting that opportunity on the user has several advantages: - the library writer isn't responsible for getting the library completely perfect, because library users can make changes if necessary - the common case (run-time extension and manipulation) needs less code (that is, you don't have to say Mother, may I take advantage of the features of the dynamic language I'm supposed to be? to take advantage of those features) - the user of the library can choose specific optimizations when and where he needs them -- c
RE: Vocabulary
finally by default? None for me; thanks, though. -- Gordon Henriksen IT Manager ICLUBcentral Inc. [EMAIL PROTECTED]
Re: Vocabulary
Chip Salzenberg writes: According to Jonathan Scott Duff: Those classes that are closed can be opened at run-time and the user pays the penalty then when they try to modify the class [...] The optimization that can be reversed is not the true optimization. While poetic and concise, I think that statement needs to be driven into the ground a bit more. Over on p6i, I think we're basically in agreement that the ability to undo optimizations is nothing we can count on. Unless there is a breakthrough in computer science any time soon, this while loop: sub one() { 1 }; sub go() { my $x = 0; while $x++ one { # loop optimized away %main::{'one'} = sub { 10 }; print Boing!\n; } } Is not something that can can be re-inserted when we find out one() has changed. While it's possible to make it so go() is unoptimized on the next call, that's not good enough. We expect changes to act instantly. But if you separate parsing and code-generation time, you can make optimizations earlier based on declarations later, which is just fine. It allows you to say: use PresumptuousModule SomeClass ; class SomeClass is extensible { }; Then even if the writer of PresumptuousModule thinks you'll be better off with the optimization, you can tell him otherwise. But you have to do it before the code is generated. Luke
Re: Vocabulary
On Tuesday, December 16, 2003, at 12:20 PM, Gordon Henriksen wrote: finally by default? None for me; thanks, though. I don't think so; we're just talking about whether you can extend a class at _runtime_, not _compiletime_. Whether or not Perl can have some degree of confidence that, once a program is compiled, it won't have to assume the worst-case possibility of runtime alteration of every class, upon every single method call, just in case you've screwed with something. They still aren't final classes, in that you can subclass them at will. You just can't subclass them _runtime_, via Ceval, unless you've specifically marked that you want to allow that for that _specific_ class. As Larry hypothesized: The other reason for final is to make it easy for the compiler to optimize. That's also problematical. As implemented by Java, it's a premature optimization. The point at which you'd like to know this sort of thing is just after parsing the entire program and just before code generation. And the promises have to come from the users of interfaces, not the providers, because the providers don't know how their services are going to be used. Methods, roles, and classes may never declare themselves final. They may be declared final only by the agreement of all their users. But the agreement could be implied by silence. If, by the time the entire program is parsed, nobody has said they want to extend an interface, then the interface can be considered closed. In other words, if you think you *might* want to extend an interface at run time, you'd better say so at compile time somehow. I think that's about as far as we can push it in the final direction. -and- Actually, I think making people declare what they want to extend might actually provide a nice little safety mechanism for what can be modified by the eval and what can't. It's not exactly Safe, but it's a little safer. -and- Seriously, I hope we can provide a framework in which you can screw around to your heart's content while modules are being compiled, and to a lesser extent after compilation. But we'll never get to a programming-in-the-large model if we can't limit most of the screwing around to the lexical scope currently being compiled, or at least to a known subset of the code. So, if I may interpret that; it might not be so bad to have to declare whether or not you were going to extend/alter a class at runtime, in order that Perl could optimize what it knows at compile-time for the 99.5% of the classes that you wouldn't be doing that for. MikeL
Re: Vocabulary
On Tuesday, December 16, 2003, at 03:00 PM, Luke Palmer wrote: But Perl hinges on laziness, doesn't it? Eh, I trust that Perl 6 will make it easy to figure that out in most cases. I was coming from the perspective that 90% of my projects don't need speed; but I can say no such thing on account of my users. And what about that un-accounted-for 10%? As someone who has 90% of their projects relying very critically on speed, and who has had to battle a number of clients' IT departments over the years in defense of said speed compared to other popular languages which, out of spite, I will not name, I beg you to never speak or think that sentence again. ;-) MikeL
Re: Vocabulary
According to Michael Lazzaro: As someone who has 90% of their projects relying very critically on speed ... an anecdote ... and who has had to battle a number of clients' IT departments over the years in defense of said speed compared to other popular languages which, out of spite, I will not name, ... and a public relations issue. Let us not confuse them. -- Chip Salzenberg - a.k.a. - [EMAIL PROTECTED] I wanted to play hopscotch with the impenetrable mystery of existence, but he stepped in a wormhole and had to go in early. // MST3K
Re: Vocabulary
Larry Wall [EMAIL PROTECTED] writes: On Tue, Dec 16, 2003 at 07:05:19AM -0700, Luke Palmer wrote: : Michael Lazzaro writes: : : On Sunday, December 14, 2003, at 06:14 PM, Larry Wall wrote: : But the agreement could be implied by silence. If, by the time the : entire program is parsed, nobody has said they want to extend an : interface, then the interface can be considered closed. In other : words, if you think you *might* want to extend an interface at run : time, you'd better say so at compile time somehow. I think that's : about as far as we can push it in the final direction. : : That seems a very fair rule, especially if it adds a smidge more speed. : Runtime extension will likely be very unusual : : Unless you're me. Or Damian. Or a fair number of other programmers who : like to dive into the Perl Dark Side on a regular basis. : : -- requiring it to be explicit seems reasonable. : : It seems so. Knowing Larry, I'm sure this is an ungrounded fear, but I : definitely want to be able to declare in a module I'm going to be : screwing with stuff; keep out of my way, so that I don't impose any : awkward declarations on my module users. If that request can be made : more explicit in the cases where that's possible, great, but the general : declaration should be available. Okay, we'll call the general declaration: use $ or some such. :-) Seriously, I hope we can provide a framework in which you can screw around to your heart's content while modules are being compiled, and to a lesser extent after compilation. But we'll never get to a programming-in-the-large model if we can't limit most of the screwing around to the lexical scope currently being compiled, or at least to a known subset of the code. Modules that turn off optimization for all other modules are going to be about as popular as $. Or the debugger. Or a refactoring tool. Or a Class browser... So the general declaration should probably be something easy to see like: use STRANGE_SEMANTICS_THAT_SLOW_EVERYONE_DOWN; No question about that. That will encourage people to be more specific about what they want to pessimize. Certainly, your fancy module should be encouraged to declare these things on behalf of its users if it can. I'm not suggesting that Lukian or Damianly modules force such declarations onto the users unless it's impossible for the module to know. And it seems to me that with sufficient control over the user's grammar, you can often get that information into your own fancy module somehow. Might take a few macros though, or analysis of the user's code at CHECK time (or maybe just before). When you say CHECK time, do you mean there'll be a CHECK phase for code that gets required at run time? -- Beware the Perl 6 early morning joggers -- Allison Randal
Re: Vocabulary
Michael Lazzaro [EMAIL PROTECTED] writes: On Tuesday, December 16, 2003, at 12:20 PM, Gordon Henriksen wrote: finally by default? None for me; thanks, though. I don't think so; we're just talking about whether you can extend a class at _runtime_, not _compiletime_. Whether or not Perl can have some degree of confidence that, once a program is compiled, it won't have to assume the worst-case possibility of runtime alteration of every class, upon every single method call, just in case you've screwed with something. There's still a hell of a lot of stuff you can do with 'cached' optimization that can be thrown away if anything changes. What the 'final' type declarations would do is allow the compiler to throw away the unoptimized paths and the checks for dynamic changes that mean the optimization has to be thrown out and started again. -- Beware the Perl 6 early morning joggers -- Allison Randal
Re: Vocabulary
On Tuesday, December 16, 2003, at 04:01 PM, Chip Salzenberg wrote: According to Michael Lazzaro: As someone who has 90% of their projects relying very critically on speed ... an anecdote ... Yes. and who has had to battle a number of clients' IT departments over the years in defense of said speed compared to other popular languages which, out of spite, I will not name, ... and a public relations issue. Yes, again. Let us not confuse them. I'm not sure I understand which part of that is in conflict. Is it the premise that some people use Perl in environments in which speed is an issue, the premise that Perl5 has a public relations issue about being inappropriate for speed-critical environments, or the conflation that someone that works in speed-critical environments, and wishes to use Perl, is going to run up against the public-relations issue? MikeL
Re: Vocabulary
On Wed, Dec 17, 2003 at 12:15:04AM +, Piers Cawley wrote: There's still a hell of a lot of stuff you can do with 'cached' optimization that can be thrown away if anything changes. What the 'final' type declarations would do is allow the compiler to throw away the unoptimized paths and the checks for dynamic changes that mean the optimization has to be thrown out and started again. As Luke pointed out in an earlier message, you can encounter grave difficulty (i.e. halting problem unsolvable sort of difficulty) in trying to unoptimize a piece of code that is in the middle of being executed. Just about any subroutine call might (but almost always won't :-) happen to execute code that makes the current subroutine have to revert to unoptimized (or differently optimized) form. When that subroutine call returns after such a rare occurrence, it can't return to the unoptimized code (because there could be missing context because the calling routine got this far using the optimized code and may have skipped stuff that is (now) necessary) and it can't return to the old code (because its optimization might now be wrong).
Re: Vocabulary
According to Michael Lazzaro: On Tuesday, December 16, 2003, at 04:01 PM, Chip Salzenberg wrote: ... an anecdote ... ... and a public relations issue. Let us not confuse them. I'm not sure I understand which part of that is in conflict. Speed is for users. PR is for non-users. You want speed? OK, we can talk about the actual speed you actually need based on your actual usage patterns. But from a design perspective you're a collection of anecote, not a user base; so your usage patterns may be irrelevant to Perl in the big picture. In a separate matter, non-users may perceive Perl {5,6} to be too slow for their needs; more to the point, they may *assume* that it is too slow without research and testing. That assumption is a public relations issue -- ironically, one which is fundamentally disconnected from the question of Perl's _actual_ efficiency. -- Chip Salzenberg - a.k.a. - [EMAIL PROTECTED] I wanted to play hopscotch with the impenetrable mystery of existence, but he stepped in a wormhole and had to go in early. // MST3K
Re: Vocabulary
On Wed, Dec 17, 2003 at 12:11:59AM +, Piers Cawley wrote: : When you say CHECK time, do you mean there'll be a CHECK phase for : code that gets required at run time? Dunno about that. When I say CHECK time I'm primarily referring to the end of the main compilation. Perl 5 appears to ignore CHECK blocks declared at run time, so in the absence of other considerations I suspect Perl 6 might do the same. Larry
Re: Vocabulary
On Tuesday, December 16, 2003, at 05:36 PM, Chip Salzenberg wrote: Speed is for users. PR is for non-users. You want speed? OK, we can talk about the actual speed you actually need based on your actual usage patterns. But from a design perspective you're a collection of anecote, not a user base; so your usage patterns may be irrelevant to Perl in the big picture. In a separate matter, non-users may perceive Perl {5,6} to be too slow for their needs; more to the point, they may *assume* that it is too slow without research and testing. That assumption is a public relations issue -- ironically, one which is fundamentally disconnected from the question of Perl's _actual_ efficiency. Well, just for clarification; in my anecdotal case (server-side web applications), the speed I actually need is as much as I can get, and all the time. Every N cycles I save represents an increase in peak traffic capabilities per server, which is, from a marketing perspective, essential. If a potential client company needs to decide between two server-based products -- my Perl based product, and a competing Java-based one -- one of the first questions they ask is how much traffic can it handle for X dollars of hardware and software. I don't have to win that benchmark, but I have to be close. Otherwise I don't get to play. I agree, it is frequently the case that the question of speed is made critical by people who most assuredly do not need it. But they still decide that way, and I have found that asserting to them that speed is not important has been... well, less than effective. I do not doubt that P6 will be much more competitive, speed-wise, than P5 -- but if it could actually _win_ a few benchmarks, it would turn my company's use of Perl from a PR problem to a PR advantage. your usage patterns may be irrelevant to Perl in the big picture. The thought has crossed my mind repeatedly, believe me. MikeL
Re: Vocabulary
Michael Lazzaro writes: I agree, it is frequently the case that the question of speed is made critical by people who most assuredly do not need it. But they still decide that way, and I have found that asserting to them that speed is not important has been... well, less than effective. I do not doubt that P6 will be much more competitive, speed-wise, than P5 -- but if it could actually _win_ a few benchmarks, it would turn my company's use of Perl from a PR problem to a PR advantage. In the presence of parrot's JIT, competing should be no problem. I'm not entirely sure Perl 6 will be faster than Perl 5 on the average. But the difference is that Perl 6 will allow you to make fast code where you need it. For instance (and the main one, probably), using native (lowercase) types allows you to JIT, and using JIT is just... well, you have to see it for yourself. Amazing. But since, as I've said, I don't do speed-critical work, I won't be usually using lowercase types. And that trades me flexibility for speed. And from what I've seen of Java, if you need speed, hand-optimizing your inner loop to parrot assembly should blow Java out of the water. Without needing a C compiler (I despise XS). Luke your usage patterns may be irrelevant to Perl in the big picture. The thought has crossed my mind repeatedly, believe me. MikeL
Re: Vocabulary
Larry Wall wrote in perl.perl6.language : On Wed, Dec 17, 2003 at 12:11:59AM +, Piers Cawley wrote: : When you say CHECK time, do you mean there'll be a CHECK phase for : code that gets required at run time? Dunno about that. When I say CHECK time I'm primarily referring to the end of the main compilation. Perl 5 appears to ignore CHECK blocks declared at run time, so in the absence of other considerations I suspect Perl 6 might do the same. This has proven to be inconvenient except for a few specialized usages, such as the B::/O compiler framework. There's a need (more or less) for special blocks that can be run at the end of the compilation phase of any arbitrary compilation unit.
Re: Vocabulary
On Sun, Dec 14, 2003 at 06:14:42PM -0800, Larry Wall wrote: On Sun, Dec 14, 2003 at 03:16:16AM -0600, Jonathan Scott Duff wrote: [ my ramblings about a mechanism for role methods to supercede class methods elided ] I think there's a simple way to solve this: If you're changing the policy of the class, then you're changing the class! Derive from the defective class and pull in the roles the way you prefer. D'oh! You are absolutely correct. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: Vocabulary
On Sunday, December 14, 2003, at 06:14 PM, Larry Wall wrote: But the agreement could be implied by silence. If, by the time the entire program is parsed, nobody has said they want to extend an interface, then the interface can be considered closed. In other words, if you think you *might* want to extend an interface at run time, you'd better say so at compile time somehow. I think that's about as far as we can push it in the final direction. That seems a very fair rule, especially if it adds a smidge more speed. Runtime extension will likely be very unusual -- requiring it to be explicit seems reasonable. I'm probably spouting nonsense. I just hope it's good-sounding nonsense... It's beyond good-sounding, it's frickin' awesome. MikeL
Re: Vocabulary
On Sat, Dec 13, 2003 at 01:44:34PM -0800, Larry Wall wrote: On Sat, Dec 13, 2003 at 12:50:50PM -0500, Austin Hastings wrote: : It seems to me there's an argument both ways -- : : 1. Code written in the absence of a role won't anticipate the role and : therefore won't take (unknowable) steps to disambiguate method calls. Ergo : method overloads are bad. : : 2. Roles may be written to deliberately supercede the methods of their : victims. Method overloads are vital. I think the default has to be 1, with an explicit way to get 2, preferably with the agreement of the class in question, though that's not absolutely necessary if you believe in AOP. So, if we follow the rules in the Traits paper, a role may have no semantic effect if the object's class already provides the necessary methods. To *guarantee* that a role will modify an object's behavior, we need some sytactic clue. Perhaps shall? my Person $pete shall Work; Whatever methods Work defines will override corresponding methods of the same name (signature?) in the Person class. (With will or does just the opposite is true) And that same idea could extend to roles overriding roles easy enough: my Person $pete will Work shall Lead; $pete.order(); # calls Lead.order i.e. if the class Person, and the roles Work and Lead all define a method called order(), then the Lead role's order() will be the one called. I'm not sure that will works that way, but you get the idea. WRT to the classes cooperation, should a class be able to say You can't override this method? method foo is forever { ... } Seems like it would make it harder for the programmers to debug in the event of problems. I guess that could be mitigated by clear error reporting and rampant object introspection. : This doesn't take into account role vs. role conflicts (which seem more : likely to be serendipitous). : : Perhaps an exact signature rule would work? Such that if the method was an : exact replacement, then no error occurs, otherwise it becomes either an : error or a multi? Er, which method? : Alternatively, perhaps a role must declare its method to be multi or not, : and if not then the role's method overloads the original class's. No, I think the default needs to be such that the class's method is expected to dispatch to the role's method. If no such method exists then it falls back on the normal role method dispatch. In either case, it would almost always be the case that you'd want multimethod dispatch to the set of role methods of the same name. I'm starting to think that any methods declared in roles are automatically considered multi when composed, whether so declared or not. Hmm. So that would mean that we'd need a syntax for method replacement when we wanted it (which we'd need anyway if the method was our smallest unit of reuse rather than the role) and the only time we would get an error is when 2 (or more) roles included in a composition have exactly the same signature. [slight digression, but methods are really singleton roles aren't they?] I'm not sure now whether I like idea of shall at all now. It seems better to just have every method of a role declare that it replaces the same-name method of the class. If the class doesn't want future roles replacing a given method, then we get an error. Oh, but without shall, composition order would matter and there'd be no visual cue at composition time that a particular role is special. Drat. Surely we would need a way to do same-signature replacement on methods too? This would mildly argue against an implicit multi. So whenever you bind a run-time role, the class looks to see if it already knows how to do the combination of roles this object wants, and if so, the role binding is very fast. Otherwise it creates the new composition, checks for conflicts, resolves them (or doesn't), and then binds the new composition as the object's current view of its class. Neat. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: Vocabulary
Jonathan Scott Duff [EMAIL PROTECTED] writes: On Sat, Dec 13, 2003 at 01:44:34PM -0800, Larry Wall wrote: On Sat, Dec 13, 2003 at 12:50:50PM -0500, Austin Hastings wrote: : It seems to me there's an argument both ways -- : : 1. Code written in the absence of a role won't anticipate the role and : therefore won't take (unknowable) steps to disambiguate method calls. Ergo : method overloads are bad. : : 2. Roles may be written to deliberately supercede the methods of their : victims. Method overloads are vital. I think the default has to be 1, with an explicit way to get 2, preferably with the agreement of the class in question, though that's not absolutely necessary if you believe in AOP. So, if we follow the rules in the Traits paper, a role may have no semantic effect if the object's class already provides the necessary methods. To *guarantee* that a role will modify an object's behavior, we need some sytactic clue. Perhaps shall? my Person $pete shall Work; But presumably my Person $self will Work; Using a pair of words that change their meaning depending on the subject of the verb seems to be a courageous choice of language and rather too contextual even for Perl. -- Beware the Perl 6 early morning joggers -- Allison Randal
Re: Vocabulary
On Sun, Dec 14, 2003 at 03:16:16AM -0600, Jonathan Scott Duff wrote: : So, if we follow the rules in the Traits paper, a role may have no : semantic effect if the object's class already provides the necessary : methods. To *guarantee* that a role will modify an object's behavior, : we need some sytactic clue. Perhaps shall? : : my Person $pete shall Work; : : Whatever methods Work defines will override corresponding methods of the : same name (signature?) in the Person class. (With will or does just : the opposite is true) And that same idea could extend to roles : overriding roles easy enough: : : my Person $pete will Work shall Lead; : $pete.order(); # calls Lead.order : : i.e. if the class Person, and the roles Work and Lead all define a : method called order(), then the Lead role's order() will be the one : called. : : I'm not sure that will works that way, but you get the idea. I think there's a simple way to solve this: If you're changing the policy of the class, then you're changing the class! Derive from the defective class and pull in the roles the way you prefer. If we're taking away the job of code reuse away from classes and giving it to roles, then the only job left to classes is object policy. Let's not take that away too. : WRT to the classes cooperation, should a class be able to say You : can't override this method? : : method foo is forever { ... } : : Seems like it would make it harder for the programmers to debug in the : event of problems. I guess that could be mitigated by clear error : reporting and rampant object introspection. I'm deeply suspicious of any trait resembling final. The way to prevent people from overriding your interface is to write the interface good enough that no one will want to override it. Good luck. :-) [begin digression] The other reason for final is to make it easy for the compiler to optimize. That's also problematical. As implemented by Java, it's a premature optimization. The point at which you'd like to know this sort of thing is just after parsing the entire program and just before code generation. And the promises have to come from the users of interfaces, not the providers, because the providers don't know how their services are going to be used. Methods, roles, and classes may never declare themselves final. They may be declared final only by the agreement of all their users. But the agreement could be implied by silence. If, by the time the entire program is parsed, nobody has said they want to extend an interface, then the interface can be considered closed. In other words, if you think you *might* want to extend an interface at run time, you'd better say so at compile time somehow. I think that's about as far as we can push it in the final direction. [end digression] : I'm starting to think that any methods declared in roles are automatically : considered multi when composed, whether so declared or not. : : Hmm. So that would mean that we'd need a syntax for method replacement : when we wanted it (which we'd need anyway if the method was our smallest : unit of reuse rather than the role) and the only time we would get an : error is when 2 (or more) roles included in a composition have exactly : the same signature. Right, I think. : [slight digression, but methods are really singleton roles aren't they?] In a sense, yes. Though just as with singleton classes, the type and the thing it represents should not be confused. : I'm not sure now whether I like idea of shall at all now. It seems : better to just have every method of a role declare that it replaces the : same-name method of the class. If the class doesn't want future roles : replacing a given method, then we get an error. Oh, but without shall, : composition order would matter and there'd be no visual cue at : composition time that a particular role is special. Drat. : : Surely we would need a way to do same-signature replacement on methods : too? This would mildly argue against an implicit multi. I still think the right way to change policy is to write your own class that *doesn't* define the methods you want the roles to override. The name of a class has to represent *something*, if it doesn't represent a fixed set of methods. I submit that it represents a consistent policy. A different policy should have a different class name. So I think that classes have to be in charge of role composition. The actor chooses how to play the part, not vice versa. To the extent that the actor can't choose, we're looking at the actor's traits, not the actor's roles. I try not to confuse roles and traits in my own life. Being the Perl god is a role. Being a stubborn cuss is a trait. :-) Larry
Re: Vocabulary
According to Larry Wall: If, by the time the entire program is parsed, nobody has said they want to extend an interface, then the interface can be considered closed. What with Ceval STRING and its various wrappers, when can the program be said to be fully parsed? - anticipating Mu -- Chip Salzenberg - a.k.a. - [EMAIL PROTECTED] I wanted to play hopscotch with the impenetrable mystery of existence, but he stepped in a wormhole and had to go in early. // MST3K
Re: Vocabulary
Larry Wall wrote: I think the class is still the final arbiter of what its objects are--there is no other entity that holds all the reins. If a class chooses to include a role, and that role violates the normal rules of roles, the class is still responsible for that (or else you need some babysitting code somewhere, hopefully in the metaclass). Maybe that's what a trait is--a renegade role. Let's see if I've got this straight: role methods supercede inherited methods; class methods supercede role methods; trait methods supercede class methods; conflicting methods from multiple roles get discarded... ...but the class may alias or exclude any of the conflicting methods to explicitly resolve the dispute. Am I right so far? Maybe not; I noticed earlier that you've mentioned that roles can be applied at compile-time using does or at run-time using but; might _that_ be the defining feature as to whether the role supercedes the class or vice versa? does supercedes inheritence, has and method supercedes does, is and but supercedes has and method... So how do you resolve conflicts between things that supercede the class? First come first serve (as per slatherons)? = Jonathan Dataweaver Lang __ Do you Yahoo!? New Yahoo! Photos - easier uploading and sharing. http://photos.yahoo.com/
RE: Vocabulary
-Original Message- From: Larry Wall [mailto:[EMAIL PROTECTED] Sent: Friday, December 12, 2003 8:30 PM On Fri, Dec 12, 2003 at 05:17:37PM -0500, Austin Hastings wrote: : Good. I like the mixin being available at either time. This makes properties : a lot more useful since I can provided default or normal values: : : role Celebrated : does Date : does { : method celebrated($d) { return $d.date; } : } : : class Birthday does Celebrated { : has $.date; : } : : my Birthday $d = Birthday.new('February', 29, 2004) but : Celebrated('March', 01, 2004); : : print My birthday is celebrated $d.celebrated; More generally, you can write the rest of the class knowing that the role is there if it's compiled in. : I presume that the linear order (compile time) or chronological order of : applying roles decides the order in which overlaid methods are : Cwraped/overlaid. The original Traits paper specifies that it's illegal to compose two methods of the same name into the class, and you have to rename one of them to get them both visible. This is why the authors specifically rejected mixins, because they hide errors like this. I'm not convinced these are errors. Having a role override methods makes sense in a lot of ways. Consider, for example, a caching or persistence implementation that overrides the .STORE method of its victims. It seems to me there's an argument both ways -- 1. Code written in the absence of a role won't anticipate the role and therefore won't take (unknowable) steps to disambiguate method calls. Ergo method overloads are bad. 2. Roles may be written to deliberately supercede the methods of their victims. Method overloads are vital. This doesn't take into account role vs. role conflicts (which seem more likely to be serendipitous). Perhaps an exact signature rule would work? Such that if the method was an exact replacement, then no error occurs, otherwise it becomes either an error or a multi? Alternatively, perhaps a role must declare its method to be multi or not, and if not then the role's method overloads the original class's. (Which takes us to retroactive multi-fication. Ugh.) Or perhaps you just have to say this method overloads. As for the relationship of Trait methods to other methods declarations, an explicit method declaration in the class proper overrides the composed methods, while composed methods override anything else in the inheritance hierarchy. At compile time, right? Whereas composition (but=) overrides declaration at run-time? : Which is it, by the way? Or is there MTOWTDI, such as a method modifier for : specifying polymorph behavior? The default way might well be the way specified in the Traits paper. However, their underlying language didn't support any kind of multi dispatch. Perl 6 will be able to multi any set of names in the same namespace as long as the arguments are differentiable by type. So it might be possible to insert a stub method declaration in the class proper that says treat all composed methods of this name as multis. That presumes the methods take differing arguments, of course. : method CONFORM is wrapped { ... call ... } That would be another way to do it, except that you might still have to switch on something to tell it which role method to call. : A property is a simple kind of role that supplies a single attribute. : The type of a property is identical to its role name. Roles can have : subtypes that function as enums when the subtypes are constrained to a : single value. : : This seems really clunky for enums. It works okay for boolean, but even : doing month-names is going to suck pretty hard: : : role Month; : : role January does Month[0]; : role February does Month[1]; : role March does Month[2]; : role April does Month[3]; : role May does Month[4]; : role June does Month[5]; : role July does Month[6]; : role Augustdoes Month[7]; : role September does Month[8]; : role October does Month[9]; : role November does Month[10]; : role December does Month[11]; : : role Month does Int[January..December]; That's why I suggested some syntactic sugar for it. But I admit that treating each enum as a subtype is a stretch. They could be constant methods, for instance. In any event, the various enum names should probably be hidden in the Month role and not be exported by default. Yeah, the concept is useful enough that it's probably worth a spoonful of sugar. Perhaps it were better to think of a clever way of defining a batch of named constants in a class declaration, so that enums could be full classes if they want to be: class Month is Int { method name {...}; has values [ January = 0, February, ..., December ]; } : You can use one of these subtypes without specifically implying the role : name. So saying : : $bar but Red :
Re: Vocabulary
On Sat, Dec 13, 2003 at 12:07:40PM -0500, Austin Hastings wrote: : From: Larry Wall [mailto:[EMAIL PROTECTED] : The behavior probably doesn't expire unless you've cloned the object : and the clone expires. However, if a role goes out of its lexical : scope, it can't be named, so it's effectively not usable unless you : dig out a name for it via reflection. But the information is still : cached there, so the object could be smarter the next time it takes : on the same role. : : It's a role closure, in other words? Erm. That's a fancy word, and I don't claim to know what it means all the time. I suspect the name of the role is closed but the role itself isn't. Alice: If the name of the role is called Teach... : That being the case, how to you unapply a role? : : $frank does no Teach; : : $frank doesnt Teach; $frank.role_manager( action = delete, mode = override_all_safety_mechanisms, name_the_role_is_called = Teach ); Or something like that. :-) : That being said, a role applied with Ctemp probably *should* be : stripped out when it goes out of scope. Could get messy though... : : I can't think of a way to apply a role with temp (to a non-temp object). How : do you do it? Well, we did set up a way for a method to be temporizable, so it probably comes down to whether Cbut is just syntactic sugar for a method call that knows how to undo itself. Larry
Re: Vocabulary
On Sat, Dec 13, 2003 at 12:50:50PM -0500, Austin Hastings wrote: : -Original Message- : From: Larry Wall [mailto:[EMAIL PROTECTED] : Sent: Friday, December 12, 2003 8:30 PM : : On Fri, Dec 12, 2003 at 05:17:37PM -0500, Austin Hastings wrote: : : I presume that the linear order (compile time) or chronological order of : : applying roles decides the order in which overlaid methods are : : Cwraped/overlaid. : : The original Traits paper specifies that it's illegal to compose two : methods of the same name into the class, and you have to rename one of : them to get them both visible. This is why the authors specifically : rejected mixins, because they hide errors like this. : : I'm not convinced these are errors. Having a role override methods makes : sense in a lot of ways. A role method certainly overrides inherited methods, so it's only methods defined in the class itself we're talking about here. : Consider, for example, a caching or persistence implementation that : overrides the .STORE method of its victims. I think the class is still the final arbiter of what its objects are--there is no other entity that holds all the reins. If a class chooses to include a role, and that role violates the normal rules of roles, the class is still responsible for that (or else you need some babysitting code somewhere, hopefully in the metaclass). Maybe that's what a trait is--a renegade role. Instead of does Storable maybe it's is storable : It seems to me there's an argument both ways -- : : 1. Code written in the absence of a role won't anticipate the role and : therefore won't take (unknowable) steps to disambiguate method calls. Ergo : method overloads are bad. : : 2. Roles may be written to deliberately supercede the methods of their : victims. Method overloads are vital. I think the default has to be 1, with an explicit way to get 2, preferably with the agreement of the class in question, though that's not absolutely necessary if you believe in AOP. : This doesn't take into account role vs. role conflicts (which seem more : likely to be serendipitous). : : Perhaps an exact signature rule would work? Such that if the method was an : exact replacement, then no error occurs, otherwise it becomes either an : error or a multi? Er, which method? : Alternatively, perhaps a role must declare its method to be multi or not, : and if not then the role's method overloads the original class's. No, I think the default needs to be such that the class's method is expected to dispatch to the role's method. If no such method exists then it falls back on the normal role method dispatch. In either case, it would almost always be the case that you'd want multimethod dispatch to the set of role methods of the same name. I'm starting to think that any methods declared in roles are automatically considered multi when composed, whether so declared or not. : (Which takes us to retroactive multi-fication. Ugh.) More like proactive multi-fication, I think. : Or perhaps you just have to say this method overloads. If it's part of the role contract, it's part of the contract. But maybe that makes it a trait. : As for the relationship of Trait methods to other methods : declarations, an explicit method declaration in the class proper : overrides the composed methods, while composed methods override : anything else in the inheritance hierarchy. : : At compile time, right? Whereas composition (but=) overrides declaration at : run-time? I don't think the rules for run-time roles should be different than the rules for compile-time roles (because Perl doesn't make a hard-and-fast distinction between compile time and run time). And the arbitration logic has to be somehow associated with the class, either explicitly by the class's declarations, or by some babysitting code telling the class how to behave given the new composition. I've been talking about singleton classes to implement run-time roles, but that's not quite right. I think a class caches its various compositions and either reuses an existing one or creates a new composition depending on which set of roles has been bound to the current object. It might seem like you could have a combinatorial explosion of the possible number of compositions if multiple properties are applied at run time, but when you think about, the number of those cached compositions has to be equal or less than the number of singleton classes you'd get if you created a new one for every object with one or more properties. In general there will be many fewer compositions than singletons. So whenever you bind a run-time role, the class looks to see if it already knows how to do the combination of roles this object wants, and if so, the role binding is very fast. Otherwise it creates the new composition, checks for conflicts, resolves them (or doesn't), and then binds the new composition as the object's current view of its class. In a sense, these are
Re: Vocabulary
On Fri, Dec 12, 2003 at 04:23:02AM -0700, Luke Palmer wrote: So I'm seeing a lot of inconsistent OO-vocabulary around here, and it makes things pretty hard to understand. So here's how Perl 6 is using said inconsistent terms, AFAIK: - attribute A concrete data member of a class. Used with Chas. - property An out-of-band sticky note to be placed on a single object. Used with Cbut. I think an important aspect of properties that you left out here is that they are run-time. - trait A compile time sticky note to be placed on a wide variety of things. Used with Cis. - role A collection of methods to be incorporated into a class sans inheritance (and maybe some other stuff, too). Used with Cdoes. s/class/object/ Roles are like sticky behavior (as I understand them) just as properties are sticky state. And I assume that roles are run-time so that you can have your objects obtain new behavior (fullfill new roles) as needed without having to use eval all the time. I think I'm getting it but I'm not sure. Does something like this work? my role Teach { ... } my role Operate { ... } my role Learn { ... } my Person $frank; { temp $frank_the_teacher = $frank does Teach; ... } { temp $frank_the_doctor = $frank does Operate; ... } { temp $frank_the_student = $frank does Learn; ... } I.e., we can use dynamic scoping to control how long an object fulfills a particular role? Maybe it could also be written like so: my Person $frank; { my role Teach { ... }; $frank does Teach; ... } { my role Operate { ... }; $frank does Operate; ... } { my role Learn { ... } $frank does Learn; ... } so that when the role goes out of scope, the object no longer possesses the abilities of that role. I confuse myself everytime I think about this stuff. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: Vocabulary
On Fri, Dec 12, 2003 at 04:23:02AM -0700, Luke Palmer wrote: : So I'm seeing a lot of inconsistent OO-vocabulary around here, and it : makes things pretty hard to understand. Agreed. : So here's how Perl 6 is using said inconsistent terms, AFAIK: : : - attribute : A concrete data member of a class. Used with Chas. Declared with Chas is a little more precise. : - property : An out-of-band sticky note to be placed on a single object. : Used with Cbut. Maybe applied with? : - trait : A compile time sticky note to be placed on a wide variety of things. : Used with Cis. Fine. (Though I like to hyphenate compile-time when it's an adjective, and not when it's a noun. Same for run-time, just to be consistent.) : - role : A collection of methods to be incorporated into a class sans A role can also supply one or more attributes. : inheritance (and maybe some other stuff, too). Used with Cdoes. Here it gets a little fuzzier. A role can be applied to a class at compile time via does, or to an object at run time via but. A property is a simple kind of role that supplies a single attribute. The type of a property is identical to its role name. Roles can have subtypes that function as enums when the subtypes are constrained to a single value. You can use one of these subtypes without specifically implying the role name. So saying $bar but Red might give you a value with the property Color. You can write the corresponding boolean test using the smart match operator: $bar ~~ Red and it (smartly) picks out the Color property to compare with, provided it's unambiguous. You can use that syntax to compare against any subtype or junction of subtypes: $bar ~~ RedishWhiteish # pinkish : So for example: : : class Dog : does Boolean# role : is extended # trait : is Mammal # [1] : { : has $.tail; # attribute : has @.legs; # attribute : } : : my $fido = Dog.new : but false; # property : : Hope that clears things up. Yes, it does. : Luke : : [1] This is a base class, which is an overloaded use of Cis. Though, : upon A12 release, we'll probably find out that it's not overloaded but : instead, elegantly unified, somehow. If not, it'll be easy to turn it into an isa. Larry
RE: Vocabulary
-Original Message- From: Jonathan Scott Duff [mailto:[EMAIL PROTECTED] Sent: Friday, December 12, 2003 11:13 AM To: Luke Palmer Cc: Language List Subject: Re: Vocabulary On Fri, Dec 12, 2003 at 04:23:02AM -0700, Luke Palmer wrote: So I'm seeing a lot of inconsistent OO-vocabulary around here, and it makes things pretty hard to understand. So here's how Perl 6 is using said inconsistent terms, AFAIK: - attribute A concrete data member of a class. Used with Chas. - property An out-of-band sticky note to be placed on a single object. Used with Cbut. I think an important aspect of properties that you left out here is that they are run-time. - trait A compile time sticky note to be placed on a wide variety of things. Used with Cis. - role A collection of methods to be incorporated into a class sans inheritance (and maybe some other stuff, too). Used with Cdoes. s/class/object/ Roles are like sticky behavior (as I understand them) just as properties are sticky state. And I assume that roles are run-time so that you can have your objects obtain new behavior (fullfill new roles) as needed without having to use eval all the time. This seems needlessly restrictive. If we're defining roles as having mixin capabilities, we should be able to use them in classes. Laziness. role Work {...}; role Management {...}; class Employee {...}; class Worker is Employee does Work; class Manager is Employee does Management; role PHB does Manager[does no Work]; I think I'm getting it but I'm not sure. Does something like this work? my role Teach { ... } my role Operate { ... } my role Learn { ... } my Person $frank; { temp $frank_the_teacher = $frank does Teach; ... } { temp $frank_the_doctor = $frank does Operate; ... } { temp $frank_the_student = $frank does Learn; ... } I.e., we can use dynamic scoping to control how long an object fulfills a particular role? Maybe it could also be written like so: my Person $frank; { my role Teach { ... }; $frank does Teach; ... } { my role Operate { ... }; $frank does Operate; ... } { my role Learn { ... } $frank does Learn; ... } so that when the role goes out of scope, the object no longer possesses the abilities of that role. I confuse myself everytime I think about this stuff. That's brilliant, if twisted. The object persists, but the behaviors expire. There's a paradigm there, man. Write a book. (It's double-e Eevil, too, but that's Damian's problem. :-) =Austin
RE: Vocabulary
-Original Message- From: Larry Wall [mailto:[EMAIL PROTECTED] Sent: Friday, December 12, 2003 12:17 PM : - role : A collection of methods to be incorporated into a class sans A role can also supply one or more attributes. So a role can constrain values and add behavior and attributes. Presumably it can do both at the same time? enum ParityMode values P_ODD P_EVEN P_NONE; role Byte does Int[0..255] # Value constraint does { # extending by adding attributes methods, and by overriding the STORE method has ParityMode $.parity_mode = NONE; has bit $.parity; # .CONFORM is redundant with Value constraint above, which autogenerates this. method CONFORM(Int $i) { SUPER 0 = $i = 255; } method STORE(Int $i: $v) { $i = .CONFORM($v) || fail; set_parity; } method set_parity {...} }; : inheritance (and maybe some other stuff, too). Used with Cdoes. Here it gets a little fuzzier. A role can be applied to a class at compile time via does, or to an object at run time via but. Good. I like the mixin being available at either time. This makes properties a lot more useful since I can provided default or normal values: role Celebrated does Date does { method celebrated($d) { return $d.date; } } class Birthday does Celebrated { has $.date; } my Birthday $d = Birthday.new('February', 29, 2004) but Celebrated('March', 01, 2004); print My birthday is celebrated $d.celebrated; I presume that the linear order (compile time) or chronological order of applying roles decides the order in which overlaid methods are Cwraped/overlaid. Which is it, by the way? Or is there MTOWTDI, such as a method modifier for specifying polymorph behavior? method CONFORM is wrapped { ... call ... } A property is a simple kind of role that supplies a single attribute. The type of a property is identical to its role name. Roles can have subtypes that function as enums when the subtypes are constrained to a single value. This seems really clunky for enums. It works okay for boolean, but even doing month-names is going to suck pretty hard: role Month; role January does Month[0]; role February does Month[1]; role March does Month[2]; role April does Month[3]; role May does Month[4]; role June does Month[5]; role July does Month[6]; role Augustdoes Month[7]; role September does Month[8]; role October does Month[9]; role November does Month[10]; role December does Month[11]; role Month does Int[January..December]; You can use one of these subtypes without specifically implying the role name. So saying $bar but Red might give you a value with the property Color. This is smart and helpful. I like it. However, there needs to be a way to specify what to do when multiple roles share the same values. For example, if I have NeededBy and Estimated roles: my $birthday = 02/29/2004 but March; my $ship_date = 01/01/01 but NeededBy(February); You can write the corresponding boolean test using the smart match operator: $bar ~~ Red and it (smartly) picks out the Color property to compare with, provided it's unambiguous. You can use that syntax to compare against any subtype or junction of subtypes: $bar ~~ RedishWhiteish # pinkish Disambiguation? $bar ~~ NeededBy(February) or $bar.NeededBy ~~ February =Austin
Re: Vocabulary
A role can also supply one or more attributes. : inheritance (and maybe some other stuff, too). Used with Cdoes. The smalltalk paper you mentionned which talked about roles (under the name of traits) said that roles were stateless. What are the consequences of using stateful roles? A related question. Will getter and setter methods will have the same name as the underlying accessed attributes? -- stef
Re: Vocabulary
At 9:16 AM -0800 12/12/03, Larry Wall wrote: On Fri, Dec 12, 2003 at 04:23:02AM -0700, Luke Palmer wrote: : - property : An out-of-band sticky note to be placed on a single object. : Used with Cbut. Maybe applied with? : - trait : A compile time sticky note to be placed on a wide variety of things. : Used with Cis. Fine. (Though I like to hyphenate compile-time when it's an adjective, and not when it's a noun. Same for run-time, just to be consistent.) I would really, *really* like to kill the whole It's a sticky note! metaphor dead. If I understand the changes proposed in properties as part of the whole shift to roles thing they aren't anything like sticky notes at all, as they dynamically subclass the object. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: Vocabulary
On Fri, Dec 12, 2003 at 07:12:40PM +0100, Stéphane Payrard wrote: : : A role can also supply one or more attributes. : : : inheritance (and maybe some other stuff, too). Used with Cdoes. : : The smalltalk paper you mentionned which talked about roles (under : the name of traits) said that roles were stateless. Though they did point out that state was one of the thing they wanted to look into. : What are the consequences of using stateful roles? That's what we're trying to figure out. :-) It seems to me that as long as the attributes declared in the role are elaborated into the real object at class composition time, there's really very little problem with doing that part of it. You have to watch for collisions just as you do with method names, of course. The tricky part comes later when you start to use it. The trickiest thing will be to know if some change in the rest of the object has invalidated your role's state such that you have to recompute it. : A related question. Will getter and setter methods will have the : same name as the underlying accessed attributes? Yes, the getter/setter method is the same name as the attribute. (There's only one method, but it can be an lvalue method for rw attributes). Larry
Re: Vocabulary
It was Friday, December 12, 2003 when Luke Palmer took the soap box, saying: : So I'm seeing a lot of inconsistent OO-vocabulary around here, and it : makes things pretty hard to understand. Awesome. I've taken your original, plus comments so far and created perlvocab.pod. Lets give it a couple go-rounds and it can be stored in CVS for safe keeping (and maintaining). Send me diffs if you like. Document below sig. Casey West -- Usenet is like Tetris for people who still remember how to read. -- Button from the Computer Museum, Boston, MA =pod =head1 NAME perlvocab - Perl Vocabulary and Glossary =head1 SYNOPSIS This document authoritatively defines many potentially ambiguous terms in Perl. =head1 DESCRIPTION =head2 Object Oriented Terminology =over 4 =item attribute A concrete data member of a class. Declared with Chas. =item property A run-time, out-of-band sticky note to be placed on a single object, applied with with Cbut. A property is a simple kind of role that supplies a single attribute. The type of a property is identical to its role name. Roles can have subtypes that function as enums when the subtypes are constrained to a single value. You can use one of these subtypes without specifically implying the role name. So saying $bar but Red might give you a value with the property Color. You can write the corresponding boolean test using the smart match operator: $bar ~~ Red and it (smartly) picks out the Color property to compare with, provided it's unambiguous. You can use that syntax to compare against any subtype or junction of subtypes: $bar ~~ RedishWhiteish # pinkish =item trait A compile-time sticky note to be placed on a wide variety of things. Used with Cis. =item role A collection of methods and/or attributes to be incorporated into a class sans inheritance (and maybe some other stuff, too). A role can be applied to a class at compile time via Cdoes, or to an object at run time via Cbut. So for example: class Dog does Boolean# role is extended # trait is Mammal # base class { has $.tail; # attribute has @.legs; # attribute } my $fido = Dog.new but false; # property In this example, CMammal is a base class, which is an overloaded use of Cis. Though, upon A12 release, we'll probably find out that it's not overloaded but instead, elegantly unified, somehow. =head1 AUTHOR Luke Palmer, Original Document Contributions by Larry Wall, and Jonathan Scott Duff Compilation by Casey West =cut
Re: Vocabulary
On Fri, Dec 12, 2003 at 05:17:37PM -0500, Austin Hastings wrote: : -Original Message- : From: Larry Wall [mailto:[EMAIL PROTECTED] : Sent: Friday, December 12, 2003 12:17 PM : : : - role : : A collection of methods to be incorporated into a class sans : : A role can also supply one or more attributes. : : So a role can constrain values and add behavior and attributes. Presumably : it can do both at the same time? I suspect so. Some added behaviors may only make sense on a constrained set of values. : enum ParityMode values P_ODD P_EVEN P_NONE; : : role Byte : does Int[0..255] # Value constraint : does { # extending by adding attributes methods, and by : overriding the STORE method : has ParityMode $.parity_mode = NONE; : has bit $.parity; : :# .CONFORM is redundant with Value constraint above, : which autogenerates this. : method CONFORM(Int $i) { SUPER 0 = $i = 255; } : method STORE(Int $i: $v) { $i = .CONFORM($v) || fail; set_parity; } : method set_parity {...} : }; Yes, though CONFORM is likely to be spelled PRE. And I'm not sure your STORE is gonna work by clobbering the invocant reference like that. More likely you have to assign to .value or some such accessor provided by Int. Or since roles compose into the class, it may be okay for roles to access attribute variables directly, and set $.value (presuming that's the attribute provided by Int). Depends on how fancy we want to get with the cross checking at composition time. : : inheritance (and maybe some other stuff, too). Used : with Cdoes. : : Here it gets a little fuzzier. A role can be applied to a class : at compile time via does, or to an object at run time via but. : : Good. I like the mixin being available at either time. This makes properties : a lot more useful since I can provided default or normal values: : : role Celebrated : does Date : does { : method celebrated($d) { return $d.date; } : } : : class Birthday does Celebrated { : has $.date; : } : : my Birthday $d = Birthday.new('February', 29, 2004) but : Celebrated('March', 01, 2004); : : print My birthday is celebrated $d.celebrated; More generally, you can write the rest of the class knowing that the role is there if it's compiled in. : I presume that the linear order (compile time) or chronological order of : applying roles decides the order in which overlaid methods are : Cwraped/overlaid. The original Traits paper specifies that it's illegal to compose two methods of the same name into the class, and you have to rename one of them to get them both visible. This is why the authors specifically rejected mixins, because they hide errors like this. As for the relationship of Trait methods to other methods declarations, an explicit method declaration in the class proper overrides the composed methods, while composed methods override anything else in the inheritance hierarchy. : Which is it, by the way? Or is there MTOWTDI, such as a method modifier for : specifying polymorph behavior? The default way might well be the way specified in the Traits paper. However, their underlying language didn't support any kind of multi dispatch. Perl 6 will be able to multi any set of names in the same namespace as long as the arguments are differentiable by type. So it might be possible to insert a stub method declaration in the class proper that says treat all composed methods of this name as multis. That presumes the methods take differing arguments, of course. : method CONFORM is wrapped { ... call ... } That would be another way to do it, except that you might still have to switch on something to tell it which role method to call. : A property is a simple kind of role that supplies a single attribute. : The type of a property is identical to its role name. Roles can have : subtypes that function as enums when the subtypes are constrained to a : single value. : : This seems really clunky for enums. It works okay for boolean, but even : doing month-names is going to suck pretty hard: : : role Month; : : role January does Month[0]; : role February does Month[1]; : role March does Month[2]; : role April does Month[3]; : role May does Month[4]; : role June does Month[5]; : role July does Month[6]; : role Augustdoes Month[7]; : role September does Month[8]; : role October does Month[9]; : role November does Month[10]; : role December does Month[11]; : : role Month does Int[January..December]; That's why I suggested some syntactic sugar for it. But I admit that treating each enum as a subtype is a stretch. They could be constant methods, for instance. In any event, the various enum names should probably be hidden in the Month role and not be exported by default. : You can use one of these subtypes without specifically implying the role : name.