Re: MMD as an object.
Bob Rogers [EMAIL PROTECTED] wrote: From: Leopold Toetsch [EMAIL PROTECTED] 1) is there a MultiSub object with one short name that holds all possible long names (and function references)? If yes, who is creating it: the Perl6 compiler emits code to do so or it's up to Parrot to do the right thing? FWIW, Common Lisp specifies a generic function [1] that collects all methods defined for a given operation name. (In Perl/Parrot, the generic function name for your examples would be the string foo; in Lisp, it would be the symbol FOO in some package, but the practical difference should be slight.) The important thing is that the GF has all the information required to make method dispatch decisions. That sounds exactly like the MultiSub object that gathers a candidate list of all subroutines with the same short name. ... But on the other hand, the CL community has more than 15 years of experience with MMD, so I wanted to be sure everyone was aware of it. Yeah, that's really helpful. 2) namespaces of (multi) subs. A non-multi method is in the classes' namespace. In Parrot terms that's currently: %globals{\0class_name}{method_name} I'm not quite sure, if the method hash shouldn't live inside the class. Is naming at this level really important here? Well, the short name of the multi sub has to be stored somewhere. ... The operation itself needs a name (so that people can call it), and classes need class names (maybe), but all methods are implicitly named by the combination of operation plus argument signature. Yes. That's the long name in Perl6 design documents. ... Which would seem to mean that, unlike perl5, the package in which a multimethod is defined doesn't matter; all that is captured by the argument signature. Yep. You can define a multi sub anywhere. ... Or is it possible to have more than one method with the identical signature? And if so, what does that mean? There can be identical signatures in different scopes. Within one scope, I don't know. The long name is therefore a list of class names, which suggests that the single-dispatch naming above is backwards. Of course, I'm probably out of my depth here . . . The long name contains the signature. The short name is the bare foo. A multi method is similar, except that their can be more then one with the same short name (which probably means that there has to be a MultiSub object holding the long names) I'm not sure it is meaningful to give a sub a short name, You call it by the short name. %globals{foo} -- MultiSub{foo_A_B = Sub, ...} This sounds right to me. Or perhaps %globals{foo} -- MultiSub{[foo, 'A', 'B'] = Sub, ...} Yep, something like that. just to belabor the point a bit. What about a not so global multi: multi sub foo(A $a, B $b) {...} Thanks for clarifying, leo Is this really different? After all, the operation foo should be just a string in either case. Sure. But the string foo has to live in some namespace. But, it it's not marked as global it's probably in either a package or a module, so again it has it's namespace. -- Bob Rogers leo
Re: MMD as an object.
Rod Adams [EMAIL PROTECTED] wrote: Leopold Toetsch wrote: Discussion seems to have went off into esoteric cases of locally overriden dispatcher policies and what not. I don't think it's as esoteric as you might think. Consider: package Foo; use MMD::Random; our bar is MMD::Random is export(DEFAULT); multi sub bar ($x) {...}; multi sub bar ($x) {...}; Note that they all have the same signature. The Manhattan policy would complain about this, since it's looking for the closest parameter match. The Random policy does not care. It's going to randomly pick any member method for each call. Ok. If you'd really need such random dispatch, it could be done like this, when I interpret A12 correctly: sub run_random_bar($x) { my @meths = WALKMETH($x, :method('bar')); my $meth = @meths[rand(@meths.elems)]; $meth($x); } or even with my sub bar($x) {...} # same body as above bar($x); If you need an esoteric dispatcher roll your own :) Since the main goal of treating multis as an object was to be able to override the dispatch policy, I think how a user defined policy interacts with different localities is very much on topic. I don't think that the policy should be in the MultiSub object. You have all methods and information to be able to do your own dispatch, if needed. Your approach would very likely disable all possible optimizations. Anyway, that's far future. What I'd like to know is more basic things: Yes, still :-) 1) is there a MultiSub object with one short name that holds all possible long names (and function references)? As for whether such a thing is visible at the Perl level, I think that depends on if we allow user defined dispatch policies or not. If not, it's just an introspection tool that could be addressed in other ways. Don't think so. It's a problem of namespaces and how these multi subs are managed. It touches Perl6 as well as Parrot. Even without custom policies, p6c may decide to go the MultiSub object route at the compiler level. But I can't speak to that, nor on the Compiler - Parrot interaction. It depends on what Parrot will get from the Perl6 compiler. What about multi subs? They can be defined everywhere. Given: multi sub *foo(A $a, B $b) {...} Is this something like: %globals{foo} -- MultiSub{foo_A_B = Sub, ...} What about a not so global multi: multi sub foo(A $a, B $b) {...} This can be seen as questioning how to keep track of what multi's are in scope at any given point in time, because you must dispatch amongst all the multi's visible, regardless of the differing scope. Sure. But the dispatch scheme is described in A12. That is per se not the problem. However if you have multi's from a mix of different sources and scopes, all with the same short name, which policy decides how to dispatch amongst them at a given calling locality is very much at issue, and is roughly where we are in the discussion. Yes. The policy will be handled by a dispatcher object's dispatch vtable, as far as I can currently see. leo
Re: MMD as an object.
[EMAIL PROTECTED] wrote: Ok. If you'd really need such random dispatch, it could be done like this, when I interpret A12 correctly: sub run_random_bar($x) { my @meths = WALKMETH($x, :method('bar')); my $meth = @meths[rand(@meths.elems)]; $meth($x); } or even with my sub bar($x) {...} # same body as above bar($x); This is enough to make me completely happy. :) Miro
Re: MMD as an object.
Leopold Toetsch wrote: Ok. If you'd really need such random dispatch, it could be done like this, when I interpret A12 correctly: sub run_random_bar($x) { my @meths = WALKMETH($x, :method('bar')); my $meth = @meths[rand(@meths.elems)]; $meth($x); } or even with my sub bar($x) {...} # same body as above bar($x); If you need an esoteric dispatcher roll your own :) That's certainly the doable with any language that provides sufficient introspection, within limits. It's a matter of where you store your hand rolled dispatcher. If I were to need a different policy for a given method .bar, I would likely create something called .bar much like your run_random_bar, which then dispatches amongst methods I name something like ._bar . I see some detractions to this approach: 1) Users wishing to add another multi to the mix must know that they have to make it a ._bar instead of a .bar. This is a relatively minor concern. It feels rather clumsy having two different names for what is essentially a single set of multis. 2) What parameter signature do you give the wrapper method, so it does not clobber the arguments, yet still has them to pass on to the appropriate method? And at the same time, determine what signature the wrapper was called with, to determine who to dispatch to... I hadn't said it before, but I had assumed the dispatch method of the MultiSub would have a signature of something like Str @types passed to it. 3) It does not allow more than one sub with the same signature and short name to be in scope at the same time. There are cases more legitimate than MMD::Random for this. For instance, dispatching based on return type. Or off of some user defined trait the different methods have. Or the most common case: on named arguments. My understanding of the P6 Long Names is that if one creates a multi with the same parameter signature as a previously defined multi of same short name, it masks the previous one if in a tighter scope, or erases the previous if the same scope. The original thought was to have the policy take over the acceptance of new multi's into the MultiSub as well as taking over dispatch, thus allowing for such flexibilities. Since the main goal of treating multis as an object was to be able to override the dispatch policy, I think how a user defined policy interacts with different localities is very much on topic. I don't think that the policy should be in the MultiSub object. I'm not sure if I think it should be there either. It just seemed to allow some flexibility in having it there that is otherwise very difficult to do. And quite likely, the policy itself would not be in the MultiSub, but the MultiSub would have a reference to which policy it's using. Your approach would very likely disable all possible optimizations. It's always been in the back of my head that this would be a performance hit. How big of one I don't have a good feel for. I've been attempting to get a feel for how much is gained in return for that hit. So far I am inclined to agree that the benefits do not outweigh the costs, but I like to know exactly what I'm giving up when making those decisions. 1) is there a MultiSub object with one short name that holds all possible long names (and function references)? As for whether such a thing is visible at the Perl level, I think that depends on if we allow user defined dispatch policies or not. If not, it's just an introspection tool that could be addressed in other ways. Don't think so. It's a problem of namespaces and how these multi subs are managed. It touches Perl6 as well as Parrot. What I meant to say was that yes, there does need to be management and introspection capabilities at the Perl6 level, but they do not *require* it to be a MultiSub object to happen. Some non-object solution could likely be found. With that mindset, the compiler could use a PMC object for it, but show the Language something else, or it could show the Language something that looks like an object, but use something different in Parrot. Those are questions I am not able to answer. Some of the management issues I see that need addressing are: - How do I dynamically create a new multi with differing levels of scope? For instance, add a package scoped multi from inside a sub of that package? - If I'm in a lexical scope which overrides a certain long name, how can I call the package scoped version of that long name instead? - Given a method returned from WALKMETH, what scope level is it defined at? - Can I get a CODEREF that points to the short name as a whole, or do I have to take a ref to a given multi? - How can I tell if a given long name already exists? What about multi subs? They can be defined everywhere. Given: multi sub *foo(A $a, B $b) {...} Is this something like: %globals{foo} -- MultiSub{foo_A_B = Sub, ...} What about a not so global multi: multi sub foo(A $a, B $b) {...} This can be
Re: MMD as an object.
Rod Adams [EMAIL PROTECTED] wrote: If I were to need a different policy for a given method .bar, I would likely create something called .bar much like your run_random_bar, which then dispatches amongst methods I name something like ._bar . I see some detractions to this approach: 1) Users wishing to add another multi to the mix must know that they have to make it a ._bar instead of a .bar. Not necessarily, AFAIK. You can define a lexical sub bar, which hides all outer multi subs. This bar can be used to dispatch to the multi subs. 2) What parameter signature do you give the wrapper method, so it does not clobber the arguments, yet still has them to pass on to the appropriate method? And at the same time, determine what signature the wrapper was called with, to determine who to dispatch to... Well, I presume, if you are writing such code, i.e. a bunch of mutli subs with the same signature, you are very well aware of what you are doing. So you'll know, how you call the dispatcher (and what funny effects you'll yield :) ... I hadn't said it before, but I had assumed the dispatch method of the MultiSub would have a signature of something like Str @types passed to it. I don't thing that the MultiSub does dispatch nor that it has a dispatch method. The MultiSub object is just a collection of multi Sub candidates for one of the scopes [lexical, package/module/class, global, builtin]. The current dispatcher has to collect a list of possible candidates from all the possible multis, and then decide, depending on the policy, which sub should actually be called. 3) It does not allow more than one sub with the same signature and short name to be in scope at the same time. That's mainly a Perl6 compiler problem. When the MultiSub is just a list of candidates, you can append whatever signature you like. There is no check for duplicates. It's only the dispatcher that will detect ambiguous signatures, if it cares about, like the default dispatcher. ... For instance, dispatching based on return type. Well, while there is a symmetry in call and return, when Parrot is concerned, dispatching on return types isn't easy, or better, it could just be done for the total static case, where all return results are known beforehand. For that case you could just call different subs in the first case. If the return type is just the runtime result, after the sub is run, you can do nothing in the dispatcher, which long before had called the sub. ... Or off of some user defined trait the different methods have. Or the most common case: on named arguments. A trait creates usually an anonymous subclass of the involved class and therefore has precedence over a not so specific class. MMD on named arguments isn't specified yet, or: ,--[ A12 ] | It is not likely that Perl 6.0.0 will support multiple dispatch on named | arguments, `- My understanding of the P6 Long Names is that if one creates a multi with the same parameter signature as a previously defined multi of same short name, it masks the previous one if in a tighter scope, or erases the previous if the same scope. As said, that's mainly a Perl6 compiler problem. The compiler can't emit two identical long names as one of these wouldn't be callabale then. The original thought was to have the policy take over the acceptance of new multi's into the MultiSub as well as taking over dispatch, thus allowing for such flexibilities. What policy is in effect, if you define somewhere a multi sub? I think, that can't work. And quite likely, the policy itself would not be in the MultiSub, but the MultiSub would have a reference to which policy it's using. No, I don't think so. The current (lexical) scope has the policy, according to A12. Some of the management issues I see that need addressing are: [ good questions for the compiler folks ] leo
Re: MMD as an object.
Leopold Toetsch wrote: Rod Adams [EMAIL PROTECTED] wrote: If I were to need a different policy for a given method .bar, I would likely create something called .bar much like your run_random_bar, which then dispatches amongst methods I name something like ._bar . I see some detractions to this approach: 1) Users wishing to add another multi to the mix must know that they have to make it a ._bar instead of a .bar. Not necessarily, AFAIK. You can define a lexical sub bar, which hides all outer multi subs. This bar can be used to dispatch to the multi subs. I sounds like a good plan, as long as it works. However, I'd want to create the sub at the same scope (most likely class/package) as the multi subs with the same name. I'm presently not clear if that's allowable. If I have to create a lexical method in each user to dispatch to my class, that seems sub optimal. I prefer to stick with .bar vs ._bar 2) What parameter signature do you give the wrapper method, so it does not clobber the arguments, yet still has them to pass on to the appropriate method? And at the same time, determine what signature the wrapper was called with, to determine who to dispatch to... Well, I presume, if you are writing such code, i.e. a bunch of mutli subs with the same signature, you are very well aware of what you are doing. So you'll know, how you call the dispatcher (and what funny effects you'll yield :) Consider the case where I wish to create several multi's with significantly different signatures, but you write each one twice, once with an is debug trait, and once with an is operational trait. I would have some runtime signal to determine if I need to be running the debug versions, or the operational versions. If you put too much onus on the caller function to get the call correct, you might as well just name all the methods something different and forget about MMD altogether. ... I hadn't said it before, but I had assumed the dispatch method of the MultiSub would have a signature of something like Str @types passed to it. I don't thing that the MultiSub does dispatch nor that it has a dispatch method. The MultiSub object is just a collection of multi Sub candidates for one of the scopes [lexical, package/module/class, global, builtin]. Currently you are likely correct. I was proposing to change that. The current dispatcher has to collect a list of possible candidates from all the possible multis, and then decide, depending on the policy, which sub should actually be called. I was offering the ability to change which policy does the decisions, after collecting the candidates. 3) It does not allow more than one sub with the same signature and short name to be in scope at the same time. That's mainly a Perl6 compiler problem. When the MultiSub is just a list of candidates, you can append whatever signature you like. There is no check for duplicates. It's only the dispatcher that will detect ambiguous signatures, if it cares about, like the default dispatcher. So you're saying that if I create a multi with the same scope and long name as a preexisting multi, that old multi will still be around in memory, even though it could never be called without a custom dispatcher? I was under the impression that defining two multi's with the same long name in the same scope clobbered one of the involved parties and triggered a redefinition warning. ... For instance, dispatching based on return type. Well, while there is a symmetry in call and return, when Parrot is concerned, dispatching on return types isn't easy, or better, it could just be done for the total static case, where all return results are known beforehand. For that case you could just call different subs in the first case. I was imagining dispatching based off the C want function, which I have no idea how it will be implemented at the Parrot level, but it's a defined part of Perl. If the return type is just the runtime result, after the sub is run, you can do nothing in the dispatcher, which long before had called the sub. Of course. ... Or off of some user defined trait the different methods have. Or the most common case: on named arguments. A trait creates usually an anonymous subclass of the involved class and therefore has precedence over a not so specific class. A trait added to an object instance creates an anonymous subclass, certainly. But I didn't think that adding a trait to a member of a class created a new subclass... MMD on named arguments isn't specified yet, or: ,--[ A12 ] | It is not likely that Perl 6.0.0 will support multiple dispatch on named | arguments, `- Indeed, that is the current case. My understanding of the P6 Long Names is that if one creates a multi with the same parameter signature as a previously defined multi of same
Re: MMD as an object.
[EMAIL PROTECTED] wrote: It would behave like a tied sub (or method), with a .dispatch method to decide which of the contained routines should be called this particular time. Manhattan would be the default. However, one can override the dispatch logic; implementing Luke's Patterns idea, for example. Hmm, that ties into my wishlist item. Would it be possible to implement method combinators (or rather, multimethod combinators) from Common LISP in addition to this? The only CLOS feature that A12 doesn't mention, can't let that happen. ;) class A { ... } class B is A { ... } 1 multi foo ($a) is before { ... } 2 multi foo (B $a) { ... next METHOD; ...} 3 multi foo (A $a) { ... } 4 multi foo ($a) is after { ... } 5 multi foo ($a) is around { ... next METHOD; } 6 multi foo ($a) is before { ... } and this runs all 5 methods, in order 5 1 2 6 3 (returns to 2) 4 (returns to 5) And yes, 6 and 1 do have the same signature. The rule is to run all before methods in order of the currently selected distance (ties broken in random order ;) ), and all after methods in the reverse order. Oh, and the reason why around methods are useful? multi foo ($a) is around { CATCH { ... } next METHOD; } Note that this catches the exceptions thrown by any version of foo, even though at this point you don't know whether foo will be specialised. before methods aren't useful for this since their stack frame and handler blocks don't linger during the executions of other methods. Common LISP references: Standard method combination (before, after, around) http://www.lispworks.com/documentation/HyperSpec/Body/07_ffb.htm Other method combinations (+, and, etc) http://www.lispworks.com/documentation/HyperSpec/Body/07_ffd.htm Creating your own method combinations (define-method-combination) http://www.lispworks.com/documentation/HyperSpec/Body/m_defi_4.htm Come to think of this, it seems that the only thing that'd need to be modified to accomodate both Rod's and mine proposal is to move CALLONE and CALLALL from the class to be MMD object somehow. Perhaps multi CALLONE ($obj, $method where { $_ == func }, [EMAIL PROTECTED]) { ... } Hmm, but this syntax strikes me as icky. Miro
Re: MMD as an object.
Rod Adams [EMAIL PROTECTED] wrote: It seems to me that there are several advantages to making a group of multi with the same short name a single object, of type MultiSub|MultiMethod, which internally holds references to the all the various routines that share that short name. Discussion seems to have went off into esoteric cases of locally overriden dispatcher policies and what not. What I'd like to know is more basic things: 1) is there a MultiSub object with one short name that holds all possible long names (and function references)? If yes, who is creating it: the Perl6 compiler emits code to do so or it's up to Parrot to do the right thing? 2) namespaces of (multi) subs. A non-multi method is in the classes' namespace. In Parrot terms that's currently: %globals{\0class_name}{method_name} I'm not quite sure, if the method hash shouldn't live inside the class. A multi method is similar, except that their can be more then one with the same short name (which probably means that there has to be a MultiSub object holding the long names) What about multi subs? They can be defined everywhere. Given: multi sub *foo(A $a, B $b) {...} Is this something like: %globals{foo} -- MultiSub{foo_A_B = Sub, ...} What about a not so global multi: multi sub foo(A $a, B $b) {...} Thanks for clarifying, leo
Re: MMD as an object.
On Wed, Mar 09, 2005 at 03:38:52PM -0600, Rod Adams wrote: There lingers the case of: use Foo; # from above, exports bar is MMD::Random multi sub bar {...} Does this generate an error, since one could expect this particular bar to be Manhattan? Or does it assume Random, since there's already a bar in existence? In my head, it currently makes sense to say that the new bar inherits the Random policy. Only something like: This seems like action-at-a-distance to me; I use some random module, define a couple of multis without realizing that they also exist in the module, and am baffled as to why I don't get the dispatch behavior I expect. --Dks
Re: MMD as an object.
[EMAIL PROTECTED] wrote: What about multi subs? They can be defined everywhere. Given: multi sub *foo(A $a, B $b) {...} Is this something like: %globals{foo} -- MultiSub{foo_A_B = Sub, ...} What about a not so global multi: multi sub foo(A $a, B $b) {...} Thanks for clarifying, leo Uh, the real problem is the interaction between multisubs and modules. If you import a multi with the same short name from another module, you get a real issue that needs resolving. Especially if they do fundamentally different things and you don't expect a clash. Like module Users; multi get(Stream $f, UserDescriptor $u) {...} ... module FileTransfer; multi get(Server $s, File $f) {...} Even if this is easy to fix by renaming, the error message would take a while to track down and it'd be annoying distraction during development. I believe the DWIM thing to do would be to merge multis into the same MMD object on module load. This would have to happen during runtime, since that's when the module load can occur. Miro
Re: MMD as an object.
David Storrs wrote: On Wed, Mar 09, 2005 at 03:38:52PM -0600, Rod Adams wrote: There lingers the case of: use Foo; # from above, exports bar is MMD::Random multi sub bar {...} Does this generate an error, since one could expect this particular bar to be Manhattan? Or does it assume Random, since there's already a bar in existence? In my head, it currently makes sense to say that the new bar inherits the Random policy. Only something like: This seems like action-at-a-distance to me; I use some random module, define a couple of multis without realizing that they also exist in the module, and am baffled as to why I don't get the dispatch behavior I expect. Well, if you were not expecting Foo to export some bar's, then you're in for a surprise regardless of dispatch when you call bar in your code and one of Foo::bar gets called instead of one of yours, because it was a closer match. I would say that people should know what they are getting into when they C use something. In Perl 6, that use could conviently swap the meanings of all the + and - signs, and not say a word. In my head, this extends to knowing what it exports, and if there's anything weird about it. If I am consciously adding more multi's into something a package provided, to extend it's functionality, I would think that keeping the original dispatch system would make sense. Otherwise the imported methods could fail to work properly. -- Rod Adams
Re: MMD as an object.
Leopold Toetsch wrote: Rod Adams [EMAIL PROTECTED] wrote: It seems to me that there are several advantages to making a group of multi with the same short name a single object, of type MultiSub|MultiMethod, which internally holds references to the all the various routines that share that short name. Discussion seems to have went off into esoteric cases of locally overriden dispatcher policies and what not. I don't think it's as esoteric as you might think. Consider: package Foo; use MMD::Random; our bar is MMD::Random is export(DEFAULT); multi sub bar ($x) {...}; multi sub bar ($x) {...}; multi sub bar ($x) {...}; == use Foo; multi sub bar ($x) {...}; Note that they all have the same signature. The Manhattan policy would complain about this, since it's looking for the closest parameter match. The Random policy does not care. It's going to randomly pick any member method for each call. So what we then fall into is the problem of which policy is in effect for a given multi can affect what's in scope at a given point. If the later file included: sub baz { my multi sub bar ($x) {...}; bar(5); } A Manhattan policy would have the local bar mask the package bar with the same signature. A Random policy would temporarily add it into the mix. Since the main goal of treating multis as an object was to be able to override the dispatch policy, I think how a user defined policy interacts with different localities is very much on topic. What I'd like to know is more basic things: 1) is there a MultiSub object with one short name that holds all possible long names (and function references)? As for whether such a thing is visible at the Perl level, I think that depends on if we allow user defined dispatch policies or not. If not, it's just an introspection tool that could be addressed in other ways. Even without custom policies, p6c may decide to go the MultiSub object route at the compiler level. But I can't speak to that, nor on the Compiler - Parrot interaction. What about multi subs? They can be defined everywhere. Given: multi sub *foo(A $a, B $b) {...} Is this something like: %globals{foo} -- MultiSub{foo_A_B = Sub, ...} What about a not so global multi: multi sub foo(A $a, B $b) {...} This can be seen as questioning how to keep track of what multi's are in scope at any given point in time, because you must dispatch amongst all the multi's visible, regardless of the differing scope. Method dispatch has a similar issue with hunting down all the C isa s for possible method's to include in dispatch. So far, I think this issue has been politely ignored as p6c's problem, not p6l's. However if you have multi's from a mix of different sources and scopes, all with the same short name, which policy decides how to dispatch amongst them at a given calling locality is very much at issue, and is roughly where we are in the discussion. Thanks for clarifying, Sorry I couldn't clarify more. -- Rod Adams
Re: MMD as an object.
On Thu, Mar 10, 2005 at 02:22:20PM -0600, Rod Adams wrote: David Storrs wrote: On Wed, Mar 09, 2005 at 03:38:52PM -0600, Rod Adams wrote: use Foo; # from above, exports bar is MMD::Random multi sub bar {...} Does this generate an error, since one could expect this particular bar to be Manhattan? Or does it assume Random, since there's already a bar in existence? This seems like action-at-a-distance to me; Well, if you were not expecting Foo to export some bar's, then you're in for a surprise regardless of dispatch when you call bar in your code and one of Foo::bar gets called instead of one of yours, because it was a closer match. I would say that people should know what they are getting into when they C use something. What I'm hearing you say here is Yes, it's action-at-a-distance, but it's your job to make sure it doesn't trip you up. The problem that I see is that I may well be able to keep track of everything from the modules I import, but what about the ones THEY import...and the ones THEY import...and so on. In a medium-to-large software project, that can get to be a lot of modules, very quickly. --Dks
Re: MMD as an object.
Rod Adams wrote: It seems to me that there are several advantages to making a group of multi with the same short name a single object, of type MultiSub|MultiMethod, which internally holds references to the all the various routines that share that short name. It doesn't have to be junctive because for a multi it's irrelevant if it's a method or a sub. This distinction is used only at compile time of the class closure. So I guess there is a class Multi is Code {...} in Perl 6. It would behave like a tied sub (or method), with a .dispatch method to decide which of the contained routines should be called this particular time. Manhattan would be the default. However, one can override the dispatch logic; implementing Luke's Patterns idea, for example. I see. Something like use MMD::Manhattan; use MMD::Symmetric; use MMD::Pattern; ... [..] I don't think there has been syntax introduced thus far that enables this ability. But it's likely I missed it along the way, like I seem to be missing several other things lately. I interpret the hash like syntax fooInt,Array[Int] such that foo represents the complete set of branches of multi sub foo. The only thing I wonder is this also supported for calling particular subs without dispatching: fooInt(17)? Or even partial dispatching on the sliced multi? This would BTW be something the optimizer would use as well. Another thing I haven't seen is how to declare a new multi at runtime. Non-multi's can be created via C func := sub {...}; , but that's destructive to any other routines that might have occupied that namespace. If the above is correct than it would be more like hash assignment. There are likely several rough edges in here, and I've by no means convinced myself that this is the Right Thing, but I thought I'd throw the idea out there to what others thought of it. I see some convergence and choices where that is not the case. MfG -- TSa (Thomas Sandlaß)
Re: MMD as an object.
Thomas Sandlaß wrote: Rod Adams wrote: It seems to me that there are several advantages to making a group of multi with the same short name a single object, of type MultiSub|MultiMethod, which internally holds references to the all the various routines that share that short name. It doesn't have to be junctive because for a multi it's irrelevant if it's a method or a sub. This distinction is used only at compile time of the class closure. So I guess there is a class Multi is Code {...} in Perl 6. I wasn't intending it to be junctive. I was just noting that you needed separate holders for subs and methods, since you shouldn't be able to stuff a method into a multi sub. It would behave like a tied sub (or method), with a .dispatch method to decide which of the contained routines should be called this particular time. Manhattan would be the default. However, one can override the dispatch logic; implementing Luke's Patterns idea, for example. I see. Something like use MMD::Manhattan; use MMD::Symmetric; use MMD::Pattern; ... I was thinking more along the lines of : use MMD::Pattern; our func is MMD::Pattern; multi func (...) {...} multi func (... ...) {...} multi func (... ... ...) {...} multi func2 (...) {...} multi func2 (... ...) {...} multi func2 (... ... ...) {...} Where func would get Pattern MMD, and func2 would get Manhattan MMD. -- Rod Adams
Re: MMD as an object.
Rod Adams writes: I wasn't intending it to be junctive. I was just noting that you needed separate holders for subs and methods, since you shouldn't be able to stuff a method into a multi sub. Keep in mind that the two following definitions are equivalent: class A { method foo () {...} } multi sub foo (A $a) {...} I think stuffing a method into a multi sub should be just fine. Luke
Re: MMD as an object.
Luke Palmer wrote: Keep in mind that the two following definitions are equivalent: class A { method foo () {...} } multi sub foo (A $a) {...} Except for attribute access, I think. For public attrs the accessor is not used and private ones are available: class A { has $.pub = pub; has $:priv = priv; method foo () { say pub = $.pub; say priv = $:priv; } } multi sub foo( A $a ) { say pub = $a.pub(); } Another subtlety is that the method call syntax prefers single dispatch: my $obj = A.new; $obj.foo(); foo( $obj ); I think stuffing a method into a multi sub should be just fine. Me too. The above is irrelevant for the call site. MfG -- TSa (Thomas Sandla)
Re: MMD as an object.
On Wed, Mar 09, 2005 at 06:19:25AM -0600, Rod Adams wrote: : I was thinking more along the lines of : : :use MMD::Pattern; : :our func is MMD::Pattern; : :multi func (...) {...} :multi func (... ...) {...} :multi func (... ... ...) {...} : :multi func2 (...) {...} :multi func2 (... ...) {...} :multi func2 (... ... ...) {...} : : Where func would get Pattern MMD, and func2 would get Manhattan MMD. Might be better to define some modifiers other than multi just for the documentation value, if you're going to have different policies in the same file like that. I expect that's a rarity, though. Most files would have a single MMD policy. But the main problem I see with all this is that MMD is supposedly combining short names from potentially many different scopes across *multiple* files, and what do you do if those have different policies? Plus the OP assumed that all instances of a particular short name are represented by a single object, which is not necessarily the case, since different lexical scopes can see different (and potentially overlapping) sets of multis with the same short name. I suppose one could get around that by placing an implicit constraint on multis you're not supposed to be able to see, though. Except that you really need unique long names as well within one of these objects, and two completely distinct lexical scopes could have long names that would be confused with each other. Oh wait, the lexical scope constraint would be part of the long name, just like any other constraint. Nevermind. Though maybe you still want to have separate objects since it's a performance hit to actually evaluate constraints at run time. But we still have the problem of conflicting policies in different scopes. Maybe it's not a problem if we view different policies as just different ways of marking autogenerated signatures with distance, if we can come up with a single underlying *scalar* distance measure that different policies can map multidimensional distances to differently. Some policies might only choose between 0 and Inf for the scalar distance, for instance, while others might try to finesse additional distance values. It seems to me that both the manhattan scheme and the pure scheme can be subsumed under that, but I could be wrong. Larry
Re: MMD as an object.
Larry Wall wrote: On Wed, Mar 09, 2005 at 06:19:25AM -0600, Rod Adams wrote: : I was thinking more along the lines of : : :use MMD::Pattern; : :our func is MMD::Pattern; : :multi func (...) {...} :multi func (... ...) {...} :multi func (... ... ...) {...} : :multi func2 (...) {...} :multi func2 (... ...) {...} :multi func2 (... ... ...) {...} : : Where func would get Pattern MMD, and func2 would get Manhattan MMD. Might be better to define some modifiers other than multi just for the documentation value, if you're going to have different policies in the same file like that. I expect that's a rarity, though. Most files would have a single MMD policy. Well, my intent was that one should be assigning the policy to a given multi, not a given scope. If people wish to change the default policy for multis defined in a given scope, I have no problems with that. The reason for binding the policy to a given multi was so people could write a package Foo with a pack of multi sub bar's, using policy MMD::Random, and export into a different scope, but still have the caller use the Random policy when calling bar. But the main problem I see with all this is that MMD is supposedly combining short names from potentially many different scopes across *multiple* files, and what do you do if those have different policies? Plus the OP assumed that all instances of a particular short name are represented by a single object, which is not necessarily the case, since different lexical scopes can see different (and potentially overlapping) sets of multis with the same short name. I suppose one could get around that by placing an implicit constraint on multis you're not supposed to be able to see, though. Except that you really need unique long names as well within one of these objects, and two completely distinct lexical scopes could have long names that would be confused with each other. Oh wait, the lexical scope constraint would be part of the long name, just like any other constraint. Nevermind. Though maybe you still want to have separate objects since it's a performance hit to actually evaluate constraints at run time. I'm going to interpret this as This is a solvable problem that just needs a little optimization in the compiler. Please correct me if this a poor interpretation. But we still have the problem of conflicting policies in different scopes. Maybe it's not a problem if we view different policies as just different ways of marking autogenerated signatures with distance, if we can come up with a single underlying *scalar* distance measure that different policies can map multidimensional distances to differently. Some policies might only choose between 0 and Inf for the scalar distance, for instance, while others might try to finesse additional distance values. It seems to me that both the manhattan scheme and the pure scheme can be subsumed under that, but I could be wrong. The problem with this is that it requires people to be very cooperative with how they assign their scalar values. And that feels like asking for trouble. I think a better solution is to make it where a given short name can only have one policy. Trying to assign two policies to the same multi would be a warning at least, and preferably an error. There lingers the case of: use Foo; # from above, exports bar is MMD::Random multi sub bar {...} Does this generate an error, since one could expect this particular bar to be Manhattan? Or does it assume Random, since there's already a bar in existence? In my head, it currently makes sense to say that the new bar inherits the Random policy. Only something like: use Foo; our bar is MMD::Manhattan; multi sub bar {...} Would trigger an error. -- Rod Adams