RFC: general feedback on module port
If any of you are willing, I would appreciate any general feedback on my first complete module port to Perl 6, including test suite, particularly if any parts don't look like proper Perl 6. I haven't tried executing it yet, since Pugs lacks some features. But it will be easier on them if what they try to execute is correct in the first place. I am referring to any file in the Pugs version control under this directory: /modules/Locale-KeyedText You can browse the whole Pugs source tree on the web here: http://rt.openfoundry.org/Foundry/Project/Source/index.html/pugs/browse/ Alternately, the core module itself is visible here: http://rt.openfoundry.org/Foundry/Project/Source/index.html/pugs/checkout/modules/Locale-KeyedText/lib/Locale/KeyedText.pm I have already applied or considered everything said on this list in answer to my questions. On a side note, I also decided to apply one of Larry's style preferences to all of my Perl 5 modules (and the above Perl 6 module), which is to not use parenthesis with 'return'. I will start porting another module that is about 25 times larger in a week or two; any feedback I get meanwhile may also aid that task being done correctly. Thanks to the rest of you who are working on driving Perl 6 in some fashion; we're much better off for your contributions. Have a good day. -- Darren Duncan
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: some misc Perl 6 questions
Larry Wall wrote: That's...sick... I love it. *Please* don't tell Damian. whisper Well there are some people who consider it quite sane :) http://www.cduce.org/papers/icalp04.pdf Abstract: This paper studies the problem of matching sequences against regular expressions in order to produce structured values. To me handling XML data is an area where Perl 6 could|should|will excel! I think Perl 5 already does. /whisper MfG -- TSa (Thomas Sandlaß)
Junctions - feedback and desires
I gave a talk on Perl 6 Junctions at the Thousand Oaks Perl Mongers meeting last night http://www.hcoop.net/~terry/perl/talks/p6-junctions/index.html and two questions/desires came out of it: 1: will it be possible to know which element of a junction is currently being used? E.g.: my @first_set = qw(1 1); my @new_set = qw(1 1.4 1 1 8 1 1 1 0.8); my $any_new_set = any(@new_set); my $any_first_set = any(@first_set); if ( (abs($any_first_set - $any_new_set)) 0.5) { a variation in the readings is too large.say; printf we we examining %d and %d when it happened, $any_new_set.current, $any_first_set.current ; # desired feature } 2: Unless the array of values can be specified lazily, it will not be practical to use Perl 6 Junctions on large datasets. For example I might like to be able to specify a sub ref/closure whose execution yields a new array value or undef when no more values. I.e.: sub mynext { my($age) = $sth-fetchrow_array; $age } my $junction = any(\mynext) ; 3: Do junctions short circuit? I.e., whenever the condition is met, does it continue immediately. Using the example from point #1, can we assume that the body of the then branch will fire when 8 of @new_set is encountered?
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: Adding linear interpolation to an array
HaloO Luke, you wrote: The words 'covariant' and 'contravariant' in this context seem like voodoo math. Please explain what you mean. 'Co' means together like in coproduction. And 'contra' is the opposite as in counterproductive. With instanciating parametric types the question arises how a subtype relation between instanciating types propagates to the template. E.g with Int : Num, covariance would result in Array[Int] : Array[Num]. Referential classes are actually quite difficult because upon write they are contravariant and covariant when read! So a third case of uncomparable types is needed as well, or it is the default if nothing else is specified. That's not true. I don't believe it would be an error to specify all nine combinations. Ohh, sorry. Of course implementing all is fine as well. But a bit tedious for larger collections of classes. MfG -- TSa (Thomas Sandla)
Re: Adding linear interpolation to an array
On Thu, 10 Mar 2005, [UTF-8] Thomas Sandla~_ wrote: 'Co' means together like in coproduction. And 'contra' is the opposite 'Streaming of digestive byproducts'? ;-) Sorry for the OT - couldn't resist! This pun first occurred to me wrt (cathegorical) coproducts... Michele -- SILVIO CLEPTOMANE - Scritta su un muro, Via F. Sforza, Milano
Re: Adding linear interpolation to an array
At 17:53 +0100 3/10/05, Thomas Sandlaß wrote: 'Co' means together like in coproduction. And 'contra' is the opposite as in counterproductive. With instanciating parametric types the question arises how a subtype relation between instanciating types propagates to the template. E.g with Int : Num, covariance would result in Array[Int] : Array[Num]. Referential classes are actually quite difficult because upon write they are contravariant and covariant when read! So a third case of uncomparable types is needed as well, or it is the default if nothing else is specified. 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. Einstein's presentation is a whole lot easier to understand than the one above. -- -- Marriage and kilo are troubled words. Turmoil results when centuries-old usage is altered in specialized jargon --.
Re: Adding linear interpolation to an array
At 17:53 +0100 3/10/05, Thomas Sandlaß wrote: [request for clarification of 'covariant' and 'contravariant' usage] 'Co' means together like in coproduction. And 'contra' is the opposite as in counterproductive. With instanciating parametric types the question arises how a subtype relation between instanciating types propagates to the template. E.g with Int : Num, covariance would result in Array[Int] : Array[Num]. Referential classes are actually quite difficult because upon write they are contravariant and covariant when read! So a third case of uncomparable types is needed as well, or it is the default if nothing else is specified. Thomas, 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? Something that would help: We could all look the words up in a dictionary, so we don't need a definition. What we need is a clarification, in simple terms, of what *you* mean by them, in this context. Thank you. --Dks
Re: Junctions - feedback and desires
Terrence Brannon wrote: I gave a talk on Perl 6 Junctions at the Thousand Oaks Perl Mongers meeting last night http://www.hcoop.net/~terry/perl/talks/p6-junctions/index.html and two questions/desires came out of it: 1: will it be possible to know which element of a junction is currently being used? E.g.: my @first_set = qw(1 1); my @new_set = qw(1 1.4 1 1 8 1 1 1 0.8); my $any_new_set = any(@new_set); my $any_first_set = any(@first_set); if ( (abs($any_first_set - $any_new_set)) 0.5) { a variation in the readings is too large.say; printf we we examining %d and %d when it happened, $any_new_set.current, $any_first_set.current ; # desired feature } I do not believe that is possible. This is the filtering or unification behavior that people keep wanting junctions to have, which they do not. A given junction always has all of the values it was made with. No more, no less. If you want something else, you have to make a new junction. Consider that it's been decided that : $j = 11|0; 10 $j 1 Is true. $j retains the 0 even after the 0 failed a test. As for the current value, there is only a current value during threading. In this example, the threading is fully contained in C (abs($any_first_set - $any_new_set)) 0.5 . By the time the printf comes, the threading is long past. If you wish to change the behavior, you're welcome to put out some proposals. But I'll warn you from experience that Damian is rather stubborn about the current behavior. =) 2: Unless the array of values can be specified lazily, it will not be practical to use Perl 6 Junctions on large datasets. For example I might like to be able to specify a sub ref/closure whose execution yields a new array value or undef when no more values. I.e.: sub mynext { my($age) = $sth-fetchrow_array; $age } my $junction = any(\mynext) ; You now have a junction whose only value is a coderef. I do not believe that you can create a 'lazy junction'. But I don't recall the topic coming up before, so we'll have to wait for Damian to come back unless someone else knows for certain. 3: Do junctions short circuit? I.e., whenever the condition is met, does it continue immediately. Using the example from point #1, can we assume that the body of the then branch will fire when 8 of @new_set is encountered? Yes, they short circuit. However, your second statement might be a bit misleading. When the 8 is encountered, the evaluation of the junctions terminates, and then processing moves on to the next statement, in this case the say. What you said might be construed as the junctions were still being threaded when the the say and printf occurred. HTH, -- 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
sub and method name overlap.
Given: class Foo { method Bar () {...}; } sub Bar (Any $x) {...}; my Foo $f; Bar $f; Is that last line the same as: Bar.($f); or $f.Bar; Does it matter if we change C sub Bar to C multi sub Bar ? Is there some form of implicit multi sub that gets created to make C Bar $f; C $f.Bar ? Or does it only work if there is no C multi? sub bar in sight? -- 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: Junctions - feedback and desires
Rod Adams wrote: I do not believe that is possible. This is the filtering or unification behavior that people keep wanting junctions to have, which they do not. Aww! But what about all the great problems that could be expressed with them? I know of two languages that consider this to be a core feature now (Prolog, Oz[1]). A given junction always has all of the values it was made with. No more, no less. If you want something else, you have to make a new junction. Consider that it's been decided that : $j = 11|0; 10 $j 1 Is true. $j retains the 0 even after the 0 failed a test. I can't see how this can be possible with the possibility of autothreading as described in [2]. Maybe the example you suggest is true, if both comparisons happen simultaneously, but what about this one? if ($j 10) { if ($j 1) { say $j took on two values at once; } } Let's say that the implementation chose to implement the first if() by auto-threading. The first thread where $j == 11 succeeds. The second, where $j == 1 fails. In the second thread, $j == 11 fails. It is by this assumption that the example in [3] was built. But wait, isn't (10 $j 1) likely to produce the same opcode tree as if($j10){if($j1){}} ? As for the current value, there is only a current value during threading. Isn't the threading conceptual, and actual threading invoked only when the optimiser has finished using available logic / set theory operations to prevent absurd numbers of threads being made that exit immediately? Sam. References: 1. http://xrl.us/fehh (Link to www.mozart-oz.org) A representation of send+more=money in Oz 2. http://dev.perl.org/perl6/synopsis/S09.html Some contexts, such as boolean contexts, have special rules for dealing with junctions. In any scalar context not expecting a junction of values, a junction produces automatic parallelization of the algorithm. In particular, if a junction is used as an argument to any routine (operator, closure, method, etc.), and the scalar parameter you are attempting to bind the argument to is inconsistent with the Junction type, that routine is autothreaded, meaning the routine will be called automatically as many times as necessary to process the individual scalar elements of the junction in parallel. 3. An implementation of send+more=money using Perl 6 Junctions http://svn.openfoundry.org/pugs/examples/sendmoremoney.p6 http://xrl.us/feis (revision at time of writing this message)
Re: Junctions - feedback and desires
Rod Adams wrote: I do not believe that you can create a 'lazy junction'. But I don't recall the topic coming up before, so we'll have to wait for Damian to come back unless someone else knows for certain. My understanding is that all lists are conceptually lazy. any(2..Inf) is perfectly valid.
Re: Junctions - feedback and desires
Sam Vilain wrote: Rod Adams wrote: I do not believe that is possible. This is the filtering or unification behavior that people keep wanting junctions to have, which they do not. Aww! But what about all the great problems that could be expressed with them? I know of two languages that consider this to be a core feature now (Prolog, Oz[1]). I'm not disputing that it would be powerful. I'm simply saying that as currently defined, junctions do not behave in this fashion. It also does not make a lot of sense to filter out restricting values in a none() junction. And as one who recently proposed a way of getting Prolog like features in Perl (through Rules, not Junctions), I understand the appeal completely. Junctions are not the way to that goal. They are something different. A given junction always has all of the values it was made with. No more, no less. If you want something else, you have to make a new junction. Consider that it's been decided that : $j = 11|0; 10 $j 1 Is true. $j retains the 0 even after the 0 failed a test. I can't see how this can be possible with the possibility of autothreading as described in [2]. because it gets interpreted as: 10 $j 1 -- (10 $j) ($j 1) -- (10 any(0, 11)) (any(0, 11) 1) -- any(10 0, 10 11) any(0 1, 11 1) -- any(false, true) any(true, false) -- true true -- true. Maybe the example you suggest is true, if both comparisons happen simultaneously, but what about this one? if ($j 10) { if ($j 1) { say $j took on two values at once; } } The Csay would occur, even with the first condition as C $j 10 , as you likely intended it to be. Taking multiple values at once is what junctions are all about. People seem to forget the role the predicate plays in junction evaluation. You thread over the different values, gain a result, and then use the predicate to recombine the results into a single scalar. If instead I had said: $j = 11 0; 10 $j 1 it would be false, because C all( true, false) is false. $j itself never changes. It is always a collection of values with a predicate. If you wish to have a junction with different values in it, you have to create a new one. Let's say that the implementation chose to implement the first if() by auto-threading. The first thread where $j == 11 succeeds. The second, where $j == 1 fails. In the second thread, $j == 11 fails. Except that the threadings are indendent of each other. $j = any(0,11); $j != $j; is true. $j != $j -- any(0,11) != any(0,11) -- any(0 != any(0,11), 11 != any(0,11)) -- any(any(0 != 0, 0 != 11), any(11 != 0, 11 != 11)) -- any(any(false, true), any(true, false)) -- any(true, true) -- true Similarly: $j = all(0,11); $j == $j; is false. It is by this assumption that the example in [3] was built. That assumption is in err, and the example does not generate the solutions desired See my response to it in http://www.nntp.perl.org/group/perl.perl6.language/19428 But wait, isn't (10 $j 1) likely to produce the same opcode tree as if($j10){if($j1){}} ? Well if 10 $j 1 { ... } if 10 $j { if $j 1 { ... }} Could easily wind up with the same opcodes. Unless the optimizer saw something in the first one where it could prove C $j 1 is false. As for the current value, there is only a current value during threading. Isn't the threading conceptual, and actual threading invoked only when the optimiser has finished using available logic / set theory operations to prevent absurd numbers of threads being made that exit immediately? The optimizer can skip threading over values that it can prove will not affect the outcome. That's short circuiting. But asking the optimizer to know in advance what is absurd is a tall order. Even without junctions, someone could make $j an object with an overloaded set of compare operators against Num. And there's no way for the compiler to know if those operators are consistent and transitive. (One could hope they were, but you never know). I would not call the threading conceptual. It's a very real thing. 2. http://dev.perl.org/perl6/synopsis/S09.html Some contexts, such as boolean contexts, have special rules for dealing with junctions. In any scalar context not expecting a junction of values, a junction produces automatic parallelization of the algorithm. In particular, if a junction is used as an argument to any routine (operator, closure, method, etc.), and the scalar parameter you are attempting to bind the argument to is inconsistent with the Junction type, that routine is autothreaded, meaning the routine will be called automatically as many times as necessary to process the individual scalar elements of the junction in parallel. In the cases above, the routine being threaded over is the comparison operator, not the surrounding code block that contains it. -- Rod Adams
Re: Junctions - feedback and desires
Dave Whipp wrote: Rod Adams wrote: I do not believe that you can create a 'lazy junction'. But I don't recall the topic coming up before, so we'll have to wait for Damian to come back unless someone else knows for certain. My understanding is that all lists are conceptually lazy. any(2..Inf) is perfectly valid. The list being fed into the junction can be lazy. But I believe that the list gets iterated over completely in the creation of the junction, so C any(2..Inf) is valid, but melts your processor similar to C sort 2..Inf . My impression has been that after the creation of a junction, the values that junction has are set in stone. Allowing some form of lazy list to add values at will seems a bit counter to me. But if @Cabal think it's okay to have lazy junctions, I won't argue with them. -- Rod Adams
Re: Junctions - feedback and desires
RA == Rod Adams [EMAIL PROTECTED] writes: My understanding is that all lists are conceptually lazy. any(2..Inf) is perfectly valid. RA The list being fed into the junction can be lazy. But I believe that RA the list gets iterated over completely in the creation of the RA junction, so C any(2..Inf) is valid, but melts your processor RA similar to C sort 2..Inf . i was under the impression that junctions could be smart about ranges like that and do it correctly. sort can't possibly handle that but some junctions and ranges would work fine. it isn't hard to convert that (with the proper boolean) to a boolean expression internally. RA My impression has been that after the creation of a junction, the RA values that junction has are set in stone. Allowing some form of lazy RA list to add values at will seems a bit counter to me. But if @Cabal RA think it's okay to have lazy junctions, I won't argue with them. lazy only when you can actually cheat IMO. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
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: sub and method name overlap.
On Thu, Mar 10, 2005 at 03:27:23PM -0600, Rod Adams wrote: Given: class Foo { method Bar () {...}; } sub Bar (Any $x) {...}; my Foo $f; Bar $f; Is that last line the same as: Bar.($f); or $f.Bar; I don't see how it can be anything but the former. As I understand things, when searching for a matching sub/method, the subs are given preference over indirect objects. Does it matter if we change C sub Bar to C multi sub Bar ? Nope. Is there some form of implicit multi sub that gets created to make C Bar $f; C $f.Bar ? I don't think so. Or does it only work if there is no C multi? sub bar in sight? That's how I see (no sub or multi in sight) You can always be explicit if you really want to use the IO notation: Bar $f:; -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: Junctions - feedback and desires
Rod Adams writes: Dave Whipp wrote: Rod Adams wrote: I do not believe that you can create a 'lazy junction'. But I don't recall the topic coming up before, so we'll have to wait for Damian to come back unless someone else knows for certain. My understanding is that all lists are conceptually lazy. any(2..Inf) is perfectly valid. The list being fed into the junction can be lazy. But I believe that the list gets iterated over completely in the creation of the junction, so C any(2..Inf) is valid, but melts your processor similar to C sort 2..Inf . Well, if we guarantee that .states never returns two of the same value, then of course you can not call .states on an infinite junction. And indeed, while it's possible to do this (taking the range to be an arbitrary infinite list): if any(2...) 100 {...} You'll melt if you do this: if any(2...) 2 {...} We could make junctions smart about ranges, so that the latter can just fail, but I argue that we can only do it well in the simplest of cases. It's probably better not to allow infinite ranges in junctions. On the other hand, if we give junctions well-defined semantics in terms of their underlying lists (such as orderedness), then lazy junctions may be just fine. There's a lot you can do with lazy lists, and there are a lot of very nice idioms having to do with junctions, and I'd like to find a way to make those two things not be mutually exclusive. Luke
SEND + MORE = MONEY (works now in pugs with junctions!)
Rod Adams wrote: And as one who recently proposed a way of getting Prolog like features in Perl (through Rules, not Junctions), I understand the appeal completely. Junctions are not the way to that goal. They are something different. Taking multiple values at once is what junctions are all about. People seem to forget the role the predicate plays in junction evaluation. You thread over the different values, gain a result, and then use the predicate to recombine the results into a single scalar. That assumption is in err, and the example does not generate the solutions desired 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 g). However, the former keeps the optimisation out of the algorithm, so that when someone comes along later with a nice grunty optimiser there is more chance that it gets a go at the entire solution space rather than having to fall back to exhaustive searching. (which might have to find ways to prove associativity of , etc, to make `real' optimisations). I'm trying to see a way that these two ways of using junctions are compatible. As I see it, people want to stretch out the time that the junction is true, to something non-zero, without having to explicitly create all those closures. Getting the old behaviour would be easy, just set a variable in the `if' clause: my $j1 = any(1..5); my $j2 = any(5..9); my $they_equal; if ($j1 == $j2) { # intersection of sets - $j1 and $j2 are any(5), any(5) $they_equal = 1; } else { # symmetric difference of sets - $j1 and $j2 are now # any(1..5), any(5..9) (where $j1 != $j2 :)) } if ($they_equal) { } Now, the `where $j1 != $j2' bit there, which looks like it's on crack, is a way of representing that instead of actually calling that second branch 24 times, it could be calling it with two junctions which are `entangled' (or, if you prefer, `outer joined'). $j1 and $j2 appear almost untouched - except any test that uses $j1 and $j2 together will not see the combination of ($j1 == 5) and ($j2 == 5). 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); } $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? One last thing - that comment about any(@foo) == one(@foo) not checking for uniqueness in a list is right - the correct version is: all(@foo) == one(@foo) Sam. Footnotes: * - any relational database `experts' who want to remind me of which normalisation form rules this breaks, please remember that RDBMSes and normalised forms approximate Set Theory, which this is trying to do as well, so I believe such discussion is irrelevant.