Re: unusual invocants
- Original Message From: TSa (Thomas Sandlaß) tho...@sandlass.de So what the OP wants to do is declare a method that is available on all those invocants - and only those invocatnts - which do all of roles X, Y, and Z. Granted, you can declare a new role XandYandZ that does X, Y, and Z, and define the method there, but that won't work on $foo unless you declare explicitly '$foo does XandYandZ' . The goal is to have the method show up no matter how $foo comes to do all three roles. Right. I have difficulty seeing the need for a method here. The distinguishing feature of a method is the access to the private data of an object that can hardly be granted by doing the three roles X, Y and Z. After all there's no unique implementation of these roles! I believe I started this thread, unless we mean John Lang as the OP after the rename. Private state is actually a separate issue and one which the traits researchers already dig into. I was asking the special case where: 1. A class consumes two (or more) roles 2. Each roles provides a method with an identical signature 3. The methods are not equivalent and neither role can rely on the other's method With that, you have roles which cannot be composed. You must rewrite one (bad if you don't own it), or omit one.. Cheers, Ovid -- Buy the book - http://www.oreilly.com/catalog/perlhks/ Tech blog- http://use.perl.org/~Ovid/journal/ Twitter - http://twitter.com/OvidPerl Official Perl 6 Wiki - http://www.perlfoundation.org/perl6
r28868 - docs/Perl6/Spec
Author: moritz Date: 2009-10-21 09:55:53 +0200 (Wed, 21 Oct 2009) New Revision: 28868 Modified: docs/Perl6/Spec/S06-routines.pod Log: [S06] more consistency on name collisions in signatures, masak++ Modified: docs/Perl6/Spec/S06-routines.pod === --- docs/Perl6/Spec/S06-routines.pod2009-10-21 02:51:54 UTC (rev 28867) +++ docs/Perl6/Spec/S06-routines.pod2009-10-21 07:55:53 UTC (rev 28868) @@ -503,7 +503,7 @@ possible on those arguments that are bound to a final slurpy or arglist variable.) -All parameters must either have a unique name (sigil included) +All parameters must either have a unique name (sigil excluded) or be anonymous. Declaring a routine having two positionals with exactly the same name counts as a compile-time error. Renaming a named parameter can also cause forbidden name collisions:
r28870 - docs/Perl6/Spec
Author: masak Date: 2009-10-21 10:50:10 +0200 (Wed, 21 Oct 2009) New Revision: 28870 Modified: docs/Perl6/Spec/S06-routines.pod Log: [S06] third attempt at describing elusive name collision Modified: docs/Perl6/Spec/S06-routines.pod === --- docs/Perl6/Spec/S06-routines.pod2009-10-21 08:46:25 UTC (rev 28869) +++ docs/Perl6/Spec/S06-routines.pod2009-10-21 08:50:10 UTC (rev 28870) @@ -503,12 +503,16 @@ possible on those arguments that are bound to a final slurpy or arglist variable.) -All parameters must either have a unique name (sigil excluded) -or be anonymous. Declaring a routine having two positionals with exactly -the same name counts as a compile-time error. Renaming a named parameter -can also cause forbidden name collisions: +A signature containing a name collision is considered a compile time +error. A name collision can occur between positional parameters, between +named parameters, or between a positional parameter and a named one. +The sigil is not considered in such a comparison, except in the case of +two positional parameters -- in other words, a signature in which two +or more parameters are identical except for the sigil is still OK (but +you won't be able to pass values by that name). -:($a, $a) # wrong, two a +:($a, $a) # wrong, two $a +:($a, @a) # OK (but don't do that) :($a, :a($b)) # wrong, one a, one a through renaming :($a, :a(@b)) # wrong :(:$a, :@a) # wrong
Re: unusual invocants
On Wed, Oct 21, 2009 at 3:47 AM, Ovid publiustemp-perl6langua...@yahoo.com wrote: I was asking the special case where: 1. A class consumes two (or more) roles 2. Each roles provides a method with an identical signature 3. The methods are not equivalent and neither role can rely on the other's method With that, you have roles which cannot be composed. You must rewrite one (bad if you don't own it), or omit one.. Rather than disallow the composition, I'd say that any class, role, or object that does both roles must override the method in question. Which takes us back to Jon's branch of the thread: it would be nice to be able to declare such an override in a general way that will apply to any such composition that doesn't otherwise override it locally. But what should that declaration look like? -- Mark J. Reed markjr...@gmail.com
Re: unusual invocants
Jonathan Worthington wrote: Ovid wrote: I was asking the special case where: 1. A class consumes two (or more) roles 2. Each roles provides a method with an identical signature 3. The methods are not equivalent and neither role can rely on the other's method With that, you have roles which cannot be composed. You must rewrite one (bad if you don't own it), or omit one.. When a role is composed into a class, it does quite literally become as if it were declared within the class itself (appears directly in the methods list), but equally does not lose its lexical scoping relationship with the role it was declared in either. Would it help to say that when a method declared within a role invokes another method, then we first search the methods within that role's lexical scope? Therefore: role Drinking { method buy_beer() { self.go_to_bar(); ... } method go_to_bar() { ... } } role Gymnastics { method go_to_bar() { } } class DrunkGymnast does Drinking does Gymnastics { method go_to_bar() { # something to resolve the conflict here } } This way, the method buy_beer will always consider methods in its lexical scope first and thus find the role's go_to_bar rather than the one in the class. Of course, if the role's lexical scope had no methods of that name declared within it we'd go elsewhere. This is close to what I've been suggesting in terms of checking which hat the object is wearing (or, alternately, which role it is performing). The main difference is that the final say _must_ be given to the class, because only the class knows enough about the implementation to be sure to do the right thing. For instance, what if you want the DrunkGymnast who goes to the bar in the Drinking sense to automatically be given a citation for doing so? class DrunkGymnast is the place where this issue must be addressed. Or worse: if you have her go_to_bar in the Drinking sense, you set a flag that indicates that she's drunk; and if you have her go_to_bar in the Gymnastics sense while she's drunk, the call should fail. This can only be done if you can define two distinct go_to_bar methods within the class, because Perl no longer has a want mechanism that would allow one method to handle both cases. This is where my proposal for disambiguating the two of them according to the invocant comes in. Ovid need not be right about his statement #2: while the two methods have the same short names (e.g., go_to_bar) and accept the same arguments (e.g., none), they don't necessarily have the same signatures, because they can use the invocant's type to address the in the Drinking sense and in the Gymnastics sense concept that I was using in the previous paragraph. As such, the two methods can have the same names and the same parameter lists, but still have different signatures (and thus different long-names): go_to_bar:(Drinking:) and go_to_bar:(Gymnastics:). The trick would lie in making the compiler smart enough to DWIM in most cases (by figuring out for itself which sense you mean), and in providing an easy-to-use means of explicitly choosing a sense to cover the remaining cases. I have some more thoughts on this; but I'm on a time crunch at the moment, and would really like to get some feedback on the above before proceeding further: have I missed anything in my reasoning? -- Jonathan Dataweaver Lang
Parrot 1.7.0 African Grey Released!
Come, let us hasten to a higher plane Where dyads tread the fairy fields of Venn, Their indices bedecked from one to ''n'' Commingled in an endless Markov chain! I'll grant thee random access to my heart, Thou'lt tell me all the constants of thy love; And so we two shall all love's lemmas prove, And in our bound partition never part. Cancel me not — for what then shall remain? Abscissas some mantissas, modules, modes, A root or two, a torus and a node: The inverse of my verse, a null domain. -- Stanisław Lem, Love and Tensor Algebra On behalf of the entire Parrot team, I'm proud to announce Parrot 1.7.0 African Grey. Parrot is a virtual machine aimed at running all dynamic languages. Parrot 1.7.0 is available on Parrot's FTP site [0], or you can follow the download instructions on our website. For those who would like to develop on Parrot, or help develop Parrot itself, you can check out the latest and best source code with Subversion: svn co https://svn.parrot.org/parrot/trunk parrot For the most recent list of languages that target Parrot and their status, consult the Parrot Trac Wiki [2]. [0] - ftp://ftp.parrot.org/pub/parrot/releases/devel/1.7.0/ [1] - http://parrot.org/download [2] - https://trac.parrot.org/parrot/wiki/Languages New in 1.7.0: - Functionality + Parrot_capture_lex has been added to the PARROT_EXPORT API + PARROT_MAX_ARGS has been increased from 8 to 16 to allow for ops that take more than 8 args - Performance + The profiling runcore now caches metadata for improved performance - Maintenance and cleanup + Expanded the Parrot debugger documentation + Parrot debugger now uses the new Parrot STRING API + Continue to port rest of internals to use the STRING API - Deprecations + The JIT subsystem has been removed and is being written from the ground up. More information can be found at https://trac.parrot.org/parrot/wiki/JITRewrite + Implicit optional named parameters (eligible in 2.1) + Continuation-based ExceptionHandlers (eligible in 2.1) + Use of undocumented variables in class_init (eligible in 2.1) + Parrot_oo_get_namespace (eligible in 2.1) - Bugfix + Improved line number tracking in IMCC - Tests + Converted many more Perl 5 tests to PIR + Expanded test coverage of the CallSignature, Namespace, FixedPMCArray, ResizeableIntegerArray and ExceptionHandler PMCs Happy Hacking! -- Jonathan Leto jonat...@leto.net http://leto.net
Re: unusual invocants
HaloO, Jon Lang wrote: I have some more thoughts on this; but I'm on a time crunch at the moment, and would really like to get some feedback on the above before proceeding further: have I missed anything in my reasoning? I fully understand what you mean, I hope. But note that all instances of the class that does the two roles do both roles. So the object at hand can't select the dispatch target. So it has to come from the *environment* of the call. I consider this as very problematic because essentially you have to import that into the object so that it can be carried for a while---this is what you call wearing a role hat. We should keep the class dispatch as simple as possible and not mix in the environment of the call into the meaning of an object! Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Re: unusual invocants
TSa wrote: Jon Lang wrote: I have some more thoughts on this; but I'm on a time crunch at the moment, and would really like to get some feedback on the above before proceeding further: have I missed anything in my reasoning? I fully understand what you mean, I hope. But note that all instances of the class that does the two roles do both roles. So the object at hand can't select the dispatch target. So it has to come from the *environment* of the call. I consider this as very problematic because essentially you have to import that into the object so that it can be carried for a while---this is what you call wearing a role hat. We should keep the class dispatch as simple as possible and not mix in the environment of the call into the meaning of an object! Usually, I'd agree with you - and even here, I'd say that if you can somehow resolve the dilemma without reference to the environment, that would be preferable. However, the only options that appear to be available without it are the two that Ovid outlined: rewrite one of the roles, or omit one of them. Both of these options become impractical once you account for the likes of CPAN: * Rewriting one of the roles may not be possible if the programmer doesn't own either of the offending roles; and even if it is possible, it likely involves a massive search-and-replace operation that isn't easily automated. * Omitting one of the roles is reasonable as long as you can guarantee that the overall concepts that the roles represent shouldn't be mixed (as is arguably the case for the traditional Dogwood example); but it's less than satisfactory when the only reason they can't be mixed is that each role's author made an unfortunate naming choice for one of the methods. My proposal isn't perfect, either: if an established routine fails to place the appropriate hat on the schizophrenic object, the environment-based disambiguation won't DWIM and the programmer will be forced to explicitly resolve the conflict before passing the object into that routine. Still, I don't get the same sense of it being a potential show-stopper the way that I get from the alternatives. But, as always, the devil's in the details. Perhaps someone _can_ provide a means of rewriting one of the roles in a way that won't break anything (the interface, the compiler's back, or the programmer's mind). And it may turn out that my proposal is unworkable once we start looking into the details of how it would be implemented. You mentioned that my approach involves importing a bit of the environment into the object for a while. How might this be done in a way that won't wreak havoc? One possibility would be to hide it away as a trait of WHAT, and then look for that trait when it comes time to disambiguate the schizo invocants: sub party(Drinking $x) { # $x.WHAT:role = Drinking ... $x.go_to_bar; ... # same as $x.go_to_bar:(Drinking:) } sub compete(Gymnast $x) { # $x.WHAT:role = Gymnast ... $x.go_to_bar; ... # same as $x.go_to_bar:(Gymnast:) } sub joke($x) { $x.WHAT:role is not set ... $x.go_to_bar; ... # can't be resolved without more information given Gymnast $x { # $x.WHAT:role = Gymnast ... joke($x); ... # the joke is about a Gymnast's bar. } Likewise, a method that originated in Drinking (such as .buy_beer) would set self.WHAT:role to Drinking, thus resulting in any call to .go_to_bar getting the right method from the class. (Thanks for the example, Jonathan; I hadn't thought of that rather obvious case.) If DrunkGymnast replaces .buy_beer or adds a new method that calls .go_to_bar, it won't automatically have knowledge of which hat it should be wearing; but that's OK, because it's expected to know about both hats, and can explicitly don the right one before (or when) calling the conflicted method. It's only those environments that can't be expected to know about the dual possibilities that concern me. What other problems might arise, and how might they be solved? -- Jonathan Dataweaver Lang
Re: unusual invocants
HaloO, On Wednesday, 21. October 2009 12:40:06 Mark J. Reed wrote: Rather than disallow the composition, I'd say that any class, role, or object that does both roles must override the method in question. The problem that Ovid posed needs to be resolved in the dispatch tables seen in certain methods of a class. So the solution is not overriding the offending method x but the calls to it in methods foo and bar! The interesting thing is that you have to dig that information out from the source of the roles T1 and T2. I doubt that a programmer making the dependency mistake also documents it ;) I've never seen a call graph of a library in any documentation. Which takes us back to Jon's branch of the thread: it would be nice to be able to declare such an override in a general way that will apply to any such composition that doesn't otherwise override it locally. But what should that declaration look like? Here is a direct syntax for the freeze feature of the paper: class C does T1 does T2 { freeze T1::x for foo; freeze T2::x for bar; method x {...} # for all other methods } The implementation is strait forward: on entry to foo and bar the dispatch table of the invocant is temporarily patched to contain the right x. After the call the original is restored. Heretic question: would it make sense to have a method registry for roles in CPAN? At least for a set of 'standard' modules that then allow arbitrary role combinations without conflict. Regards, TSa. -- The unavoidable price of reliability is simplicity -- C.A.R. Hoare Simplicity does not precede complexity, but follows it. -- A.J. Perlis 1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan