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 sub"s 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 de
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: 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) {...} Th
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.
From: Leopold Toetsch <[EMAIL PROTECTED]> Date: Thu, 10 Mar 2005 10:53:11 +0100 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? 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. GFs can be created explicitly with defgeneric [2], or implicitly by defining methods. According to that model, the Perl6 compiler would emit code for each method, and ask Parrot to add it to the appropriate MMD object, which may cause effective methods to be recomputed (or be marked as invalid for lazy recomputation). Mind you, I haven't read up on p6 objects, so my $0.02 might not be worth very much. If so, please rub my nose in the relevant apocalypses, etc., and I'll shut up. 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. 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? 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. 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. Or is it possible to have more than one method with the identical signature? And if so, what does that mean? 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 . . . 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," certainly not in the sense that perl5 methods can also be called as subs with the right package qualification. You can't guarantee that they will be unique, correct? 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, ...} This sounds right to me. Or perhaps %globals{"foo"} --> MultiSub{["foo", 'A', 'B'] => Sub, ...} 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. Or is this just my ignorance showing? -- Bob Rogers http://rgrjr.dyndns.org/ [1] http://www.lispworks.com/documentation/HyperSpec/Body/t_generi.htm [2] http://www.lispworks.com/documentation/HyperSpec/Body/m_defgen.htm#defgeneric
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.
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.
David Storrs wrote: 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. The question is not what they import. The question is what they export into your package. If it's not exported into your package, the other multi's are in a different package, and get a different short name. I see the short name as including the package name for subs, class name for methods. Only the signature is chopped off. I'm only asking you to keep track of what gets imported into your current package, which I do not think is asking for too much, even in a large scale project. Whatever your used modules have in their packages which they keep to themselves, including everything _they_ imported from _other_ modules, is not your concern... that's a different package space. If you go pumping new multi's into someone else's package by saying C< multi sub Foo::Bar {...} >, well, you better be familiar with what's already there. So, it could be considered action at a distance, but feels more like keeping track of what you've asked others to dump in your lap. -- 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.
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.
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.
[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.
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.
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.
[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.
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
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.
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.
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.
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 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 &foo 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: foo(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ß)
MMD as an object.
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 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. This would also provide a relatively sane way to take a reference to a single contained routine. I would expect a .matching method which takes a list of types, and returns a reference to which routine would be called given parameters of those types. Or one could get a reference to the entire multi via C< my $ref = &multi; >. 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. 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. Using the object model, one could do this with C< &func.add( sub {...}); >. There could also be a .delete method to remove a routine already in the multi (give it a reference to uniquely identify it). Of course, Luke would need to override the .add method to one that doesn't throw errors when more than one routine with the same type signature is thrown. If this happens, I would expect that C< multi > would become a macro which creates the multi of that short name if it doesn't already exist, and then perform an .add to that multi. 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. -- Rod Adams.