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: Junctions - feedback and desires
Rod Adams <[EMAIL PROTECTED]> wrote: > Well > if 10 < $j < 1 { ... } > if 10 < $j { if $j < 1 { ... }} > Could easily wind up with the same opcodes. No. In the first case $j is evaluated just once. In the second case it's evaluated twice. leo
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.
[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: Junctions - feedback and desires
Leopold Toetsch wrote: Rod Adams <[EMAIL PROTECTED]> wrote: Well if 10 < $j < 1 { ... } if 10 < $j { if $j < 1 { ... }} Could easily wind up with the same opcodes. No. In the first case $j is evaluated just once. In the second case it's evaluated twice. You're right. I just dived through the archives and found that chained operators are an exception. Sorry for missing that. Which can be a mess explaining to someone how if 0 < $x && $x < 10 {...} can be true when if 0 < $x < 10 {...} is false. Though I suppose if we can extend this to a general rule of "if it only appears once, it can only be threaded once", it makes a certain amount of sense. -- Rod Adams
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: Adding linear interpolation to an array
Doug McNutt wrote: A word of caution: Just as in "vector operators" had their names changed to pacify the > mathematicians - thank you - there is a conflict in terms. Covariant and > contravariant tensors are the meat of Einstein's formulation of relativity. > It all has to do with transformations being in the same direction or the > opposite direction as the coordinate differentials. Perhaps there is some > similarity. Yes, that's what is meant by these two words. But of course the concrete meaning depends on the subject area. The above is from tensor algebra. Mine is from type theory. Einstein's presentation is a whole lot easier to understand than the one above. Sorry, I make a second attempt in another reply. -- TSa (Thomas Sandlaß)
Re: Adding linear interpolation to an array
HaloO David, you wrote: I appreciate you attempting to explain this, but it remains clear as mud, at least to me. Could you please try again, using very short, very non-technical words and not assuming a mathematical or scientific background on the part of your reader? Ok, second attempt! The <: is the subtype relation operator. Saying Int <: Num means Int is a subtype of Num. With generic types like the Array of ... the question is how this relation shall carry over to the Array type instances. Int @i; Num @n = @i; # type error? Regards, -- TSa (Thomas Sandlaß)
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: Adding linear interpolation to an array
On Fri, Mar 11, 2005 at 03:58:13PM +0100, Thomas Sandlaß wrote: : Int @i; : Num @n = @i; # type error? I think the naive user is going to expect that to work, and I also suspect the naive user is right to expect it, because it makes sense. This may be one of those areas where we can successfully hide the high-falutin' theory from mere mortals simply because it maps onto what they expect already. On the other hand, that's an assignment, which presumably copies value types. Binding is another matter--I wouldn't necessarily expect this to work: Num @n := @i; But these might be made to DWIM since copying is allowed: Num @n is copy := @i; Num @n is constant := @i; On the other hand, the plain rw binding *could* be made to work under the view that @n is providing a view of @i. It's just that @n could provide only the Int subset of semantics. As such, it's acting as a kind of tie on @n, so I expect it wouldn't be allowed unless you declared @n to be some kind of tyable that allows delegating @n to @i. Plus the variable type would have to capture the binding semantics and force the delegation past the compiler (presuming the compiler cares about the type mismatch). But it's okay to disallow some things now on the basis that they're just not implemented yet, as long as people don't mistake such restrictions for strong typing. Larry
Re: SEND + MORE = MONEY (works now in pugs with junctions!)
There's no doubt that the QM view of extended entanglement is very useful. After all, that's what the whole universe runs on. But most mortals will want the classical view to be the default, so we'll require some kind of explicit markup or pragma if you want to extend entanglement further out than comparisons. That's why junctions can't be passed into a function unless the function specifically allows it, for instance. (Then there's the matter of sneaky return values.) The only alternative is to autothread every conditional, and I don't think we'd survive the lynch mobs if we did that. Maybe there's some middle ground here that I don't see, but if so, I don't see it. And if I don't see it, all the other Pooh bears will have trouble with it too. Larry
Re: SEND + MORE = MONEY (works now in pugs with junctions!)
Larry Wall writes: > There's no doubt that the QM view of extended entanglement is very > useful. After all, that's what the whole universe runs on. But most > mortals will want the classical view to be the default, so we'll > require some kind of explicit markup or pragma if you want to extend > entanglement further out than comparisons. That's why junctions can't > be passed into a function unless the function specifically allows it, > for instance. (Then there's the matter of sneaky return values.) > > The only alternative is to autothread every conditional, and I don't > think we'd survive the lynch mobs if we did that. Maybe there's some > middle ground here that I don't see, but if so, I don't see it. And > if I don't see it, all the other Pooh bears will have trouble with it > too. The collapsing behavior of Quantum::Entanglement (and what is being expressed as wanted here) is actually a sort of parallel logic programming. Instead of trying and backtracking, it's just doing it all at once. Instead of providing a collpasing junction type which will confuse the heck out of people, I think it's best to concentrate on how we will integrate logic programming in the language. And the best way to concentrate on that at this point might be not to think about it at all. But junctions might be our ticket into the world of logic programming. We'd have to change them, but there are some amazing parallels between what junctions currently do and what regexes do (regexes even use the same symbols) and what my "Argument Patterns" proposal does with junctive types, which are both logical programming frameworks. So let's put it in the back of our minds. It's going to be in the front of mine for the day, but I might not come up with anything. Luke
Re: Adding linear interpolation to an array
Larry Wall skribis 2005-03-11 8:45 (-0800): > On Fri, Mar 11, 2005 at 03:58:13PM +0100, Thomas Sandlaß wrote: > : Int @i; > : Num @n = @i; # type error? > I think the naive user is going to expect that to work, and I also > suspect the naive user is right to expect it, because it makes sense. > This may be one of those areas where we can successfully hide the > high-falutin' theory from mere mortals simply because it maps onto > what they expect already. It'd be great if this were a standard feature you can also use for your own objects. I believe $foo.Num in this case should return the Num-ified version of $foo. And maybe the int method numbers have is redundant, and should be spelled Int instead. Or, well, if this is the case, int should return an int (not Int) for consistency. Maybe +$foo even maps to $foo.Num, and ~$foo maps to $foo.Str and ?$foo maps to $foo.Bool? Hm, are charsets representable as classes/roles? my Str::utf8 $bar = ...; my Str::latin1 $foo = $bar; Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
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: SEND + MORE = MONEY (works now in pugs with junctions!)
Sam Vilain wrote: I've changed examples/sendmoremoney.p6 in the pugs distribution to use junctions correctly to demonstrate that they *can* be used to solve these sorts of problems, and that it is just a matter of semantics and writing code correctly. However, poor semantics can make the task of writing optimisers unnecessarily difficult or impractical, as Bourne demonstrated. in short, it seems people want this: my $a = any(1..9); my $b = any(1..9); my $c = any(0..9); if ( $a != $b && $b != $c && $a != $c && ($a + $b == $a * 10 + $c) ) { print "$a + $b = $a$c"; } To mean this (forgive the duplication of collapse() here): sub collapse($x, $sub) { $sub.($x) } sub collapse($x, $y, $sub) { $sub.($x,$y) } my $a = any(1..9); my $b = any(1..9); my $c = any(0..9); collapse($a, $b, -> $a, $b { ($a != $b) && collapse($c, -> $c { if ( ( $b != $c ) && ( $a != $c ) && ($a + $b == $a * 10 + $c) ) { say "$a + $b = $a$c"; } }); }); (and YES THAT WORKS ). Yes, it does work, given the current state of autothreading. Well, you'd need a C< use junctions; > in order to store a junction in a variable. And I'm not certain if that changes the autothreading behavior of the closures or not. You might have to declare the collapses as: multi sub collapse ($x is none(Junction), $sub) {...}; multi sub collapse ($x is none(Junction), $y is none(Junction), $sub) {...}; to get it to thread correctly. I'm not sure. (Pretty sure you'd need the 'multi' in there). It's also a perfect example of where my hyperthreader operator (it hasn't been nailed down yet what the exact syntax is (or even if it exists), I'm waiting for Damian to get back to continue that thread.) is a better tool than junctions. Assuming we use my »« syntax, SEND+MORE==MONEY could be written as: sub test ($s, $e, $n, $d, $m, $o, $r, $y) { if "$s$e$n$d" + "$m$o$r$e" == "$m$o$n$e$y" && all($s,$e,$n,$d,$m,$o,$r,$y) == one($s,$e,$n,$d,$m,$o,$r,$y) { say "$s$e$n$d + $m$o$r$e == $m$o$n$e$y"; } } test(»1..9«, »0..9«, »0..9«, »0..9«, »1..9«, »0..9«, »0..9«, »0..9«); Using Damian's every() syntax, the last line becomes: test(every(1..9), every(0..9), every(0..9), every(0..9), every(1..9), every(0..9), every(0..9), every(0..9)); It's extremely brute force and inefficient, but it works. I have the philosophical problem with your use of junctions in this context due to the fact that you are completely ignoring the predicate of the junction. The C< all(...) == one(...) > is an excellent use of junctions, that makes use of the predicates when the junctions are evaluated. If you want threading without the predicate, I give you the hyperthreader (well, I'm trying to). I'll also point out that what you wrote above is a lot more readable as: for 1..9 -> $a { for 1..9 -> $b { next unless $b == none($a); for 0..9 -> $c { next unless $c == none($a, $b); if $a + $b == $a * 10 + $c { say "$a + $b = $a$c" } } } } I mean, wouldn't it really be nice if you could write stuff like this: my @users is persistent("users.isam"); my @accounts is persistent("accounts.isam"); my $r_user = any(@user); my $r_account = any(@account); if ( $r_account.user == $r_user ) { say("That junction is:", $r_user); } I'm fairly certain that I'll be writing a Set class if no one beats me to it. use Sets; my @users is persistent("users.isam"); my @accounts is persistent("accounts.isam"); my $s_validusers = set(@accounts».user) - @users; for values $s_validusers -> $user { say "$user is a valid user"; } $r_user at that point represents only the users which have at least one object in @accounts for which there exists an $r_account with a `user' property that is that $r_user member[*]. The closure would then either be run once, with $r_user still a junction (if the interpreter/`persistent' class was capable of doing so), or once for every matching tuple of ($r_account, $r_user). We're still talking in terms of Set Theory, right? If you want Set Theory.. use Sets. Or use some form of Logical Programming which builds the sets implicitly for you, and does all the filtering and backtracking you're asking for. Both topics have been explored recently. The results of that exploration can be summarized as: - Sets would make a nifty module to have around. - Integrating Logical Programming into Perl needs a lot more thought and effort than will likely happen before 6.0.0. Modules grafting LP into Perl and/or Parrot are welcome. -- Rod Adams