Re: Junction Values
On Sat, 19 Feb 2005 18:42:36 +1100, [EMAIL PROTECTED] (Damian Conway) wrote: the Awesome Power of Junctions: As I tried to express elsehwere, this what I'm looking for. Instinctively, and for a long time since I first came across Q::S, I thought that the killer app of Junctions is there somewhere, I'm just not seeing it yet. I'd really like to see some practical demonstrations of the Awesome Power. Something that goes beyond producing a boolean result from a set of values that could equally be done using hyperoperators? Njs.
Re: Junction Values
Rod Adams asked: This sound reasonable enough? Frankly, no. ;-) Sorry, but your latest proposal sounds complex, multiply special-cased, and way too much of an imposition on the programmer (which is specifically what junctions are supposed to avoid). I'm going to continue to strongly recommend that we stick with junctions that are simply another (fully assignable) kind of scalar value, and which always autothread in any scalar context that isn't explicitly typed CJunction. To protect the innocent (or the timorous) I'm also going to recommend a Cno autothreading pragma, which will prevent non-explicit junctions from autothreading. And that's all I'm going to recommend. Then, if you don't want implicit autothreading, you can turn it off completely: Cno autothreading. And if you want explicit (non-auto)threading, you can use an explicit junction, even under Cno autothreading: is_prime( any($x) ) And everywhere else, junctions will just Do The Right Thing, even to the point of ensuring that any side-effects on your unordered data are appropriately non-orderly. ;-) I truly appreciate the thought and effort that all of you--especially Rod and Patrick--have put into this discussion, but I'm afraid I have to bow out of it now. Damian PS: FWIW, I'd have absolutely no objection to us adding a fifth core junctive type (perhaps CAdjunction, perhaps just CSet ;-) that has *no* associated predicate, but which implements full set semantics: my $x = set(1..3); my $y = set(1,3,5,7,9); my $n = 2; $x | $y # set(1,2,3,5,7,9) $x $y # set(1,3) $x - $y # set(2) !$x # set(none(2));-) $x $y # $x is a proper subset of $y $x = $y # $x is a subset of $y $x == $y # $x is the set $y $x ~~ $y # $x is the set $y $n $y # $n is an element of $y $n ~~ $y # $n is an element of $y set()# empty set $x.values# list of elements of set $x $x.powerset # power set of $x $x x $y # cross product of $x and $y # etc., etc.
Re: Junction Values
Nigel Sandever wrote: On Sat, 19 Feb 2005 18:42:36 +1100, [EMAIL PROTECTED] (Damian Conway) wrote: The Awesome Power of Junctions: As I tried to express elsehwere, this what I'm looking for. Instinctively, and for a long time since I first came across Q::S, I thought that the killer app of Junctions is there somewhere, I'm just not seeing it yet. I'd really like to see some practical demonstrations of the Awesome Power. Something that goes beyond producing a boolean result from a set of values that could equally be done using hyperoperators? Well, that was one of my stumbling blocks early on. They don't really give you the power to do anything you couldn't previously do. They just make certain things a lot easier to do. But I'll take a whack at giving you something non-trivial to do without junctions: $re1 = /^ -[x]* x -[x]* $/; # match a string with exactly one 'x' in it. $re2 = /^ -[y]* y -[y]* $/; # ditto 'y' $re3 = /^ -[z]* z -[z]* $/; # ditto 'z' $re4 = all($re1, $re2, $re3); # matches if x,y, z all appear exactly once, in any order. $re5 = one($re1, $re2, $re3); # matches if there is exactly one x, y, or z $re6 = any($re1, $re2, $re3); # matches if there is at least one of x,y,z that appears exactly once. $re7 = none($re1, $re2, $re3); # matches if there are 0 or 2+ of each of x,y,z. And all seven of these can be used as any stored RE can: if $x ~~ $re6 {...}; given $x { when $re5 {...} when 'santa' {...} when ($re1 | $re3) $re3 {...} } Looking at the junctioned RE's: #6 would is straight forward to do as a single RE in this case, and in the general case. #5 would be fairly trivial to in this case, but not in the general case. #4 is possible with a lot of zero-length look aheads and look-behinds, but very ugly. #7 I have no idea how to attack as a single RE in anything close to approaching elegance. So what have we gained here? The ability to join several RE's together, into something that still acts like a single RE. Show me the equivalent code without junctions, and then we'll compare the power of junctions. btw, the examples above assume the ability to store a junction. So you either have to 'use junctions;', or convince Larry to rescind that restriction. HTH. -- Rod Adams
Re: Junction Values
Damian Conway wrote: Rod Adams asked: This sound reasonable enough? Frankly, no. ;-) Sorry, but your latest proposal sounds complex, multiply special-cased, and way too much of an imposition on the programmer (which is specifically what junctions are supposed to avoid). Funny. I thought it was simple and elegant. My explanation might have been complex, as well as the motivations, but I truly considered it a straight forward and simple solution. As for too much of an imposition on the programmer, that's essentially what I was asking for all along. To be imposed upon to decide when threading occurs. I won't apologize for that, or change my position on it. But I was making the imposition optional. And, actually, now that I better understand your latest proposal, I realize how amazing close we are. Then, if you don't want implicit autothreading, you can turn it off completely: Cno autothreading. And if you want explicit (non-auto)threading, you can use an explicit junction, even under Cno autothreading: is_prime( any($x) ) Change that C any($x) to C »$x« , and the important differences between our positions shrink dramatically. Reason I don't like any() here is that $x already has a junctive condition on it. While any() with a single value does not change in the least how this will be evaluated in the long run, it could be confusing to wrap an all() junction inside an any() call. Doubling up the type works for all the types except none(). Use »« for an explicit call designator, and you revert to the type already in the junction. Give me my »« as a secondary way of always explicitly threading, and I'll go away happy. You can keep the rest of your proposal the same. I'll just start using them wherever I think threading should happen, even if I never needed to use them in most of the places I will. It'll be a good visual to myself of what's going on. Don't give them to me, and I'll frown for a while, but then likely get over it. I truly appreciate the thought and effort that all of you--especially Rod and Patrick--have put into this discussion, but I'm afraid I have to bow out of it now. I understand bowing out of this perfectly. There other tasks whose time I've raided for this discussion, and the backlog is starting to look pretty nasty. But it has been a good and healthy discussion. Many things have come of it. Thanks to all the participants. PS: FWIW, I'd have absolutely no objection to us adding a fifth core junctive type (perhaps CAdjunction, perhaps just CSet ;-) that has *no* associated predicate, but which implements full set semantics: my $x = set(1..3); my $y = set(1,3,5,7,9); my $n = 2; $x | $y # set(1,2,3,5,7,9) $x $y # set(1,3) $x - $y # set(2) !$x # set(none(2));-) $x $y # $x is a proper subset of $y $x = $y # $x is a subset of $y $x == $y # $x is the set $y $x ~~ $y # $x is the set $y $n $y # $n is an element of $y $n ~~ $y # $n is an element of $y set()# empty set $x.values# list of elements of set $x $x.powerset # power set of $x $x x $y # cross product of $x and $y # etc., etc. Now THAT is an even better idea than the separate Set class I was going to champion whenever I next had time for such a thing! I support this concept fully! -- Rod Adams PS - Looks like Matt gets his wish. This juggernaut of a thread is coming to a close. I'd be happy to proof his summary of it if he gives me an advanced copy.
Re: Set sigils (was: Re: Junction Values)
On Sat, Feb 19, 2005 at 01:43:57PM -0800, Ashley Winters wrote: Instead of primary sigils, what about secondary sigils on an array to mark it as an unordered set? @|foo = any @foo = all @^foo = one # can arrays be curried arguments? hmm @!foo = none After all, why should scalars get all the good secondary sigils? :) Just noting that secondary sigils aren't limited to scalars: @*biglist = 1... ; # global @::*::biglist has %.dictionary; # public attribute has @:children;# private attribute say @?BLOCK; # which blocks am I in? { sort @^list; } # placeholder array %=POD{'DATA'} # filehandle for =begin DATA stream Pm
Re: Junction Values
On Sun, 20 Feb 2005 03:17:19 -0600, [EMAIL PROTECTED] (Rod Adams) wrote: --020209010404060902000407 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Nigel Sandever wrote: On Sat, 19 Feb 2005 18:42:36 +1100, [EMAIL PROTECTED] (Damian Conway) wrote: The Awesome Power of Junctions: Well, that was one of my stumbling blocks early on. They don't really give you the power to do anything you couldn't previously do. They just make certain things a lot easier to do. But I'll take a whack at giving you something non-trivial to do without junctions: $re1 = /^ -[x]* x -[x]* $/; # match a string with exactly one [SNIP] And all seven of these can be used as any stored RE can: if $x ~~ $re6 {...}; given $x { when $re5 {...} when 'santa' {...} when ($re1 | $re3) $re3 {...} } SNIP] So what have we gained here? The ability to join several RE's together, into something that still acts like a single RE. Show me the equivalent code without junctions, and then we'll compare the power of junctions. By the power of a single good example, you can now count me amongst the convinced. btw, the examples above assume the ability to store a junction. So you either have to 'use junctions;', or convince Larry to rescind that restriction. Patricks's arguement that there is no real difference between a scalar that contains a Junction and a scalar that contains a coderef or any type of ref when it comes to requiring the programmer to know (or test for) what the scalar holds, was enough to convince me that no additional pragmas are required for junctions. Though I wouldn't object to Damian's cno autothreading. My only problem was that I couldn't see the larger benefit of them. Your example above is sufficient to convince that being able to encapsulate not just a set of data, but /required result/ of *any* operations performed using that set data did the trick for me. I now view the junction my $x = any( @values ); as roughly equal to: my $junction = bless [ @values ], 'any'; and similarly for the other three. Simplistic, but enough for my mind to make the transition. Using the hyper operators, you would have to re-state the desired result for each operation, but with a junction you've encapsulated it in. HTH. -- Rod Adams Thanks for taking the time to produce your good example and so carrying me along. njs. --020209010404060902000407-- Examine what is said, not who speaks.
Re: Junction Values
Rod Adams [EMAIL PROTECTED] writes: $re1 = /^ -[x]* x -[x]* $/; # match a string with exactly one 'x' in it. $re2 = /^ -[y]* y -[y]* $/; # ditto 'y' $re3 = /^ -[z]* z -[z]* $/; # ditto 'z' $re7 = none($re1, $re2, $re3); # matches if there are 0 or 2+ of each of x,y,z. #7 I have no idea how to attack as a single RE in anything close to approaching elegance. Depending on your idea of elegance ... anchored zero-width negative lookahead: $re7 = qr/^ (?!= $re1 | $re2 | $re3 ) /x; Oh right. Perl6. Well, if I understand $re1 correctly, I think this is what it will look like: $re7 = /^ !before $re1 | $re2 | $re3 /; I still want junctions, but I also still am not quite sure how they will behave. For instance, I wonder how this would autothread or not: my sub f (Int $x) { if $x { return 0, 1, $x; } else { return 0, 1; } } my $j = 0 | 7; my @a = (1, f($j), 0); - How many elements are there in @a? 3? 5? 4|5? - What is @a[-1]? 0? any(0)? 0|undef? - What is @a[4]? undef? 0|undef? 0? Naïvely, I would expect that setting of @a be equivalent to this: my @a = (1, ([0,1]|[0,1,7]), 0); And so from the callers perspective, f, which usually returns two or three values, suddenly returns a single (junctive) value. New semantics for f, courtesy of autothreading. I expect this is too naïve. But what am I missing? Eirik -- All bridge hands are equally likely, but some are more equally likely than others. -- Alan Truscott
Re: Junction Values
On Sun, Feb 20, 2005 at 07:41:16PM +1100, Damian Conway wrote: Given this: my $x = set(1..3); my $y = set(1,3,5,7,9); my $n = 2; $x | $y # set(1,2,3,5,7,9) $x $y # set(1,3) $x - $y # set(2) !$x # set(none(2));-) I don't understand this last line, even given the context of the preceding three. Why is it none of 2, rather than none of something else? Nicholas Clark
Re: Junction Values
Rod Adams [EMAIL PROTECTED] writes: Eirik Berg Hanssen wrote: Rod Adams [EMAIL PROTECTED] writes: $re1 = /^ -[x]* x -[x]* $/; # match a string with exactly one 'x' in it. $re2 = /^ -[y]* y -[y]* $/; # ditto 'y' $re3 = /^ -[z]* z -[z]* $/; # ditto 'z' $re7 = none($re1, $re2, $re3); # matches if there are 0 or 2+ of each of x,y,z. #7 I have no idea how to attack as a single RE in anything close to approaching elegance. Depending on your idea of elegance ... anchored zero-width negative lookahead: $re7 = qr/^ (?!= $re1 | $re2 | $re3 ) /x; Whoops. For ?!=, read ?!. Now imagine the quality of my Perl6 code ... Oh right. Perl6. Well, if I understand $re1 correctly, I think this is what it will look like: $re7 = /^ !before $re1 | $re2 | $re3 /; That doesn't quite do it, but something along those lines is possible. You'd have to make sure the look ahead/behinds match to the end of the string, not just some substring. And then you'd have to put in something to actually match the string. So possible, but not straightforward in the least. $re1, $re2, and $re3 are already anchored: Covered. And it will match the empty string at pos()==0, given that the assertion is satisfied. This of course differs from a junction of three match objects, each matching the whole string at pos()=0, but that difference is in part to be expected (the point of the exercise was to avoid a junction), and in part trivial to fix: just add .*. In the general case, it will be more complex, yes, but so will the match object returned by the junctive rule. Well, enough pattern matching. Junctions on the agenda, now! ;-) Eirik -- So this is the Sword of Immortality? Huh? What's it doin' in a CRYPT?! --- John S. Novak, III, quoting an unnamed player
Re: Junction Values
NC == Nicholas Clark [EMAIL PROTECTED] writes: NC On Sun, Feb 20, 2005 at 07:41:16PM +1100, Damian Conway wrote: NC Given this: my $x = set(1..3); my $y = set(1,3,5,7,9); my $n = 2; $x | $y # set(1,2,3,5,7,9) $x $y # set(1,3) $x - $y # set(2) !$x # set(none(2));-) NC I don't understand this last line, even given the context of the NC preceding three. Why is it none of 2, rather than none of NC something else? my guess is a typo and $x should be $n. 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: Junction Values
Nicholas Clark wrote: On Sun, Feb 20, 2005 at 07:41:16PM +1100, Damian Conway wrote: Given this: my $x = set(1..3); my $y = set(1,3,5,7,9); my $n = 2; $x | $y # set(1,2,3,5,7,9) $x $y # set(1,3) $x - $y # set(2) !$x # set(none(2));-) I don't understand this last line, even given the context of the preceding three. Why is it none of 2, rather than none of something else? ESTUPIDDAMIAN. Should, of course be: !$x # set(none(1..3));-) Damian PS: This is also a demonstration of the awesome power of junctions: that we can specify the complement of a set without knowing its universal set!
Re: Junction Values
Eirik Berg Hanssen [EMAIL PROTECTED] writes: Rod Adams [EMAIL PROTECTED] writes: Eirik Berg Hanssen wrote: Rod Adams [EMAIL PROTECTED] writes: $re1 = /^ -[x]* x -[x]* $/; # match a string with exactly one 'x' in it. $re2 = /^ -[y]* y -[y]* $/; # ditto 'y' $re3 = /^ -[z]* z -[z]* $/; # ditto 'z' $re7 = none($re1, $re2, $re3); # matches if there are 0 or 2+ of each of x,y,z. $re7 = /^ !before $re1 | $re2 | $re3 /; That doesn't quite do it, but something along those lines is possible. You'd have to make sure the look ahead/behinds match to the end of the string, not just some substring. And then you'd have to put in something to actually match the string. So possible, but not straightforward in the least. $re1, $re2, and $re3 are already anchored: Covered. And it will match the empty string at pos()==0, given that the assertion is satisfied. This of course differs from a junction of three match objects, each matching the whole string at pos()=0, Whoops again: That would be a junction of three match objects, _none_ of which are successful. When the assertion is not satisfied, however, you will be able to inspect the match object junction's states to see how many of the $re\d matched, and in the general case, how they matched. But on the whole, I now get the impression that these match object junctions (or at least match object injunctions) would rarely be used outside boolean context. Eirik -- For every complex problem, there is a solution that is simple, neat, and wrong. -- H. L. Mencken A good plan today is better than a perfect plan tomorrow. -- Patton
Re: Junction Values
On Sun, Feb 20, 2005 at 10:46:15PM +0100, Eirik Berg Hanssen wrote: Eirik Berg Hanssen [EMAIL PROTECTED] writes: Rod Adams [EMAIL PROTECTED] writes: $re1 = /^ -[x]* x -[x]* $/; # match a string with exactly one 'x' $re2 = /^ -[y]* y -[y]* $/; # ditto 'y' $re3 = /^ -[z]* z -[z]* $/; # ditto 'z' $re7 = none($re1, $re2, $re3); # matches if there are 0 or 2+ of each of x,y,z. $re7 = /^ !before $re1 | $re2 | $re3 /; [...lots of discussion about whether the above works or not...] I think it may be even simpler than the above, no lookaheads required: $re7 = / !$re1 !$re2 !$re3 /; Pm
Re: Junction Values
Damian~ On Mon, 21 Feb 2005 08:29:40 +1100, Damian Conway [EMAIL PROTECTED] wrote: Nicholas Clark wrote: On Sun, Feb 20, 2005 at 07:41:16PM +1100, Damian Conway wrote: Given this: my $x = set(1..3); my $y = set(1,3,5,7,9); my $n = 2; $x | $y # set(1,2,3,5,7,9) $x $y # set(1,3) $x - $y # set(2) !$x # set(none(2));-) I don't understand this last line, even given the context of the preceding three. Why is it none of 2, rather than none of something else? ESTUPIDDAMIAN. Should, of course be: !$x # set(none(1..3));-) Damian PS: This is also a demonstration of the awesome power of junctions: that we can specify the complement of a set without knowing its universal set! Or one more thing to drive the mathematicians into a rage... Matt -- Computer Science is merely the post-Turing Decline of Formal Systems Theory. -???
Re: Junction Values
Hmm. On rereading my last message, I feel that it comes across as angry, and critical of this entire discussion or perhaps of particular participants. That was certainly not my intent and I apologize if that's how it appeared. I genuinely respect the contributions of every person on this list, and even when (as now) I strenuously disagree with the ideas expressed, I know that those contributions are sincere and offered with the best interests of Perl at heart. I still stand by every point I made in that last message, but I'm sorry that I let my frustrations leak into the discussion. Damian
Re: Junction Values
On Fri, Feb 18, 2005 at 11:31:54PM -0800, Brent 'Dax' Royal-Gordon wrote: Junctions are intended to ultimately be used in boolean tests. That's why the values of the junction have an any/all/one/none relationship. The proper data structure here is an array. (Actually, ironically enough, it's probably a set, not an array.) It's one set for any()/all()/one() and two sets for none(). Of course, if something (eg. functions) cannot be tested for equality, then we'll have to assume them to be unique from each other anyway, in which case junctions do act as arrays. [1] Note, however, that this needs to be done carefully. For example, while it doesn't really make sense for the string arguments of a call to Cprint to be junctions, the object argument is another matter entirely: #!/usr/bin/perl6 # naive tee $OUT=$OUT open( $_) for @ARGS; print or die Can't write to $!.filename: $! for *$IN;# Or however it's done this week I think it's an unary = this week, according to S04: print for =*$IN; Thanks, /Autrijus/ pgpK2a19S3Fk6.pgp Description: PGP signature
Re: Junction Values
Brent 'Dax' Royal-Gordon wrote: Rod Adams [EMAIL PROTECTED] wrote: The caller is not in a position to know if the callee is internally structured in such a way that passing in a raw junction makes sense. Sure they are. It's called reading the documentation. If it doesn't say it can handle junctions, it probably can't. I don't want to have to stop in the middle of a hundred-line function to think, Does Store::Market.get act sanely when I give it a junction? Do I need to explode it manually, or will it handle the junction nicely on its own? You call functions where you don't know what data types they are expecting? That's... surprising. Even in a loosely typed world like Perl, knowing what a sub or method is expecting to be fed seems like a good idea to me. I see checking for accepting junctions as input as being on the same level as Does it want a list or an arrayref here?. When I'm writing my own insanely large functions, I'm constantly hitting the docs to see the nuances about the method calls I'm not already intimately familiar with. And if I'm going to attempt to use a function in a new way (like feeding it a Junction), I recheck the docs to make sure I'm not setting myself up for trouble down the road. Your mileage may vary. -- Rod Adams. (PS - This should not be construed to be an attack on you or your programming style. It is not. Though I've never seen you in action, I have every reason to believe you are a fully competent developer. It is simply a response to your statement above, explaining why I thought the attitude expressed there represented a weak argument.)
Re: Junction Values
Damian Conway wrote: Rod Adams wrote: All I want now is for autothreading to be explicit. It already *is*. The only way that: is_prime($x) can ever autothread is if $x holds a junction. But that can now only happen if there's an explicit Cuse junctions in scope where $x was assigned to (or the explicit use of some other module that also activates Cuse junctions). So $x having a junction must be a known possibility at that point. Of course, literal junctions *will* autothread in all circumstances: is_prime(any(6,7,8)) is_prime(6|7|8) I had not caught the difference between: use junctions; $x = 6|7|8; if is_prime($x) {...} and if is_prime(6|7|8) {...} before. Is this new, or yet another important detail I missed along the way? Or is this a side effect of not being able to store a Junction, and can go away if C use Junctions is turned on? But they're both explicit too: you're explicitly using junction constructors, so the autothreading can hardly come as a surprise. *If* we are guaranteed than an explicitly created junctions will always autothread, I'll agree with this. I will, however, question if this is optimal. Compare two simple cases: C $x == any(4,5,6) and C $x all(4,5,6) . Both of them are prime candidates to some optimizations, but the optimizations are likely rather different. If we pass the junction into the operator, then it can perform some custom tailored code, to make things much more efficient, instead of relying on a more generalized junction optimizer to handle things. What this also means is that if you wish to pass an anonymous junction, you can't. You have to do something like: { use junctions; some_func(my $x = any(4|5|6)); } Which just seems silly. And if: is_prime($x) does happen to autothread when you weren't expecting it to, then one of two things will happen. Either the subroutine will be 'pure' in which case there's no problem in autothreading it; or else the subroutine will have side effects, in which case you'll get an explicit warning when the autothreading occurs. I addressed earlier concept of how does perl know when there are side effects, particularly with the execution path can weave to parts written in pure-parrot. In particular, if the Patrick responded by implying that there was no such side effect protection. see: http://www.nntp.perl.org/group/perl.perl6.language/19210 (my post) http://www.nntp.perl.org/group/perl.perl6.language/19212 (Patrick's response) I see your statements on the subject, and Patrick's to be at odds. But then again, it might be that I've misread something again, though I'm doing my best to avoid it now. I request some clarification on this. If nothing else, to make sure you and Patrick have the same understanding of what's happening. This problem goes away completely with explicit autothreading. perl would no longer be making assumptions about what to autothread, and what to carp over. Personally, I think it's completely fascist to require a Cuse junctions pragma in order for junctions to even be stored in variables. It's as bizarre as requiring Cuse strings or Cuse references or Cuse undef or Cuse infinities would be. Yes, it *is* possible to get unexpected behaviour from passing a junction where it isn't expected, but it's already possible to get unexpected behaviour by passing a string or an undef or a reference or an object where it isn't expected. Junctions are nothing new in that respect. I had it in my head that if I were to get my »Junction« explicit threading idea, I was going to follow up by saying the block against storing junctions was a case of diminishing returns at that point, and should probably go away. I appreciate the stop-gap measure that it was, but I'd prefer to solve the real problem at hand. Ironically, by using the Awesome Power of Junctions: I hope I never gave the impression that I felt Junctions were not powerful... That was not the case. If anything, I was arguing that they were *too* powerful... But in the end, I realized it's just the implicit autothreading I didn't like. Look, I do understand the arguments in the other direction. I've understood them for the past five years that I've been developing the concept of superpositional data-types. I've thought them through numerous times myself, and in the end: I just don't buy them. The whole point of junctions is to make the threading of operations on datasets both automatic and implicit; to make it Do The Right Thing without the hassles of explicit threading. If you don't want that, that's fine: just don't use junctions. Use arrays and hyperoperators instead. And we'll happily give you a Cno junctions pragma so you can be emphatic about not wanting them. I can certainly understand the hassles of explicit threading if one is thinking: $y = func(any(3|4|5)); has to be explicitly written as: $y = any(any(3|4|5).values().map(func($_))); or some such, but is it
Re: Junction Values
Damian Conway wrote: Hmm. On rereading my last message, I feel that it comes across as angry, and critical of this entire discussion or perhaps of particular participants. That was certainly not my intent and I apologize if that's how it appeared. I genuinely respect the contributions of every person on this list, and even when (as now) I strenuously disagree with the ideas expressed, I know that those contributions are sincere and offered with the best interests of Perl at heart. I still stand by every point I made in that last message, but I'm sorry that I let my frustrations leak into the discussion. Damian Well, I for one, never took any offense to any of the responses sent my way. And I appreciate the patience it's likely taken to not just completely Warnock me. However, I also realize that I might have stepped on some toes of the course of this long discussion. Which was never my intention, and I'll apologize to any who feel I've slighted them in the process. I do believe everyone on this list shares the same goals of making Perl 6 the possible language that it can be. However, opinions will vary as to what that actually means. Being a group of people that can by and large be described as having a fairly large egos, these differences of opinion can become rather passionate. And passion leads to some pretty extreme responses. It certainly hasn't helped matters that the exact nature of my proposal has changed in some fairly drastic ways on a regular basis, as I came to a better understanding of what Junctions were, and how they were being implemented. I apologize for any confusion this may have caused, but I do think the resulting discussions have shed some new insights on Junctions, Sets, what it means to have a sigil, why junctions can't just be another class, and several other topics. Poor Mr. Fowles is likely having nightmares figuring out how to summarize all of this. Positions I still stand by: - Sets belong in the language, and need more support. This can likely be done at the module level, but I'd like them better incorporated, preferably with their own sigil. However, I believe they can peacefully coexist with Junctions, and one concept does not need to crowd out the other. - Implicit autothreading is a Bad Thing, and should not happen. This is almost entirely due to the side effects such behavior can generate. To keep the power of junctions viable, explicit threading should be trivially easy, but it should be explicit, none the less. -- Rod Adams
Re: Junction Values
Rod Adams wrote: I had not caught the difference between: use junctions; $x = 6|7|8; if is_prime($x) {...} and if is_prime(6|7|8) {...} There isn't one. Is this new, or yet another important detail I missed along the way? Or is this a side effect of not being able to store a Junction, and can go away if C use Junctions is turned on? Yes, it's a side-effect of the new default prohibition on junction assignments (though I'm still working hard to convince everyone that that prohibition cripples junctions and that having to use junctions before you can assign a basic Perl 6 scalar datatype to a variable is an abomination). I will, however, question if this is optimal. Compare two simple cases: C $x == any(4,5,6) and C $x all(4,5,6) . Both of them are prime candidates to some optimizations, but the optimizations are likely rather different. If we pass the junction into the operator, then it can perform some custom tailored code, to make things much more efficient, instead of relying on a more generalized junction optimizer to handle things. Sure. That's why we have the ability to specify subroutines where junctive args are *not* autothreaded, by typing the corresponding parameter as taking a junction: multi sub infix:«==» (YourType $x, Junction $y) is symmetrical {...} multi sub infix:«» (YourType $x, Junction $y) is symmetrical {...} These two multisubs can optimize for junctive arguments to their hearts' content. I addressed earlier concept of how does perl know when there are side effects, particularly with the execution path can weave to parts written in pure-parrot. In particular, if the Patrick responded by implying that there was no such side effect protection. see: http://www.nntp.perl.org/group/perl.perl6.language/19210 (my post) http://www.nntp.perl.org/group/perl.perl6.language/19212 (Patrick's response) I don't see that Patrick's response implies that at all. In fact, I think his statement that: Well, the ultimate answer is that both Dan and Patrick (and others) will negotiate the exact interface when we get to that point, and that we don't seem to be too concerned about it at the moment. (It could just be that we're both burying our heads in the sand hoping it'll be magically solved by the other. :-) However, in working out these examples I'm fairly comfortable that it can be made to work at the Perl 6 compiler level if need be, although it will probably be a lot more efficient if we can find a way to do it within Parrot. seems to confirm that detecting and reporting autothreaded side-effects is entirely possible. If nothing else, to make sure you and Patrick have the same understanding of what's happening. I'm sure we will. This problem goes away completely with explicit autothreading. perl would no longer be making assumptions about what to autothread, and what to carp over. But that's the whole point of junctions! Namely that perl works it out for you. If you don't want that to happen then don't use junctions (and don't allow them to be used, by specifying Cno junctions). If you want explicit threading (I refuse to call it autothreading; if it has to be manually specified, it certainly isn't auto) then use arrays instead, and thread your subroutines and operators over them using the explicit hyperoperator notation (see example below). But bowdlerizing the concept of junctions isn't the answer. I'm no longer doing that. Or at least, I'm no doing anything anywhere close to as extreme as some of my other ideas over the last week or two. Which I can see perfectly well, in retrospect, how you felt I was gutting the power away from junctions, and how frustrating that must have been for you. Thank-you for understanding that. But I still don't like implicit autothreading, and likely never will. I don't know how to explain it, but it just feels very wrong. It's down there with using typeglobs to pass filehandles, which is thankfully history. I understand your qualms, even if you can't nail down the exactly reasons for them. However, I still disagree with them. I truly believe that junctions (including their autothreading behaviour) ought to be core to Perl 6...and not ham-strung in any way. I appreciate that some people will not like the potential autothreading of: if is_prime($x) {...} # Might possibly autothread but I think it's sufficient to give those people: # At the top of the program... no junctions; # and then... if is_prime($x) {...} # Can't possibly autothread As for explicit threading: hey, you've already got it. Just use an array instead of a junction, and only allow explicit junctives. Either: # At the top of the program... no junctions 'assignment'; # Junctive constants okay # and then... if is_prime(any(@x)) {...} # Explicitly threaded or, even more
Set sigils (was: Re: Junction Values)
On Sat, 19 Feb 2005 15:20:59 -0600, Rod Adams [EMAIL PROTECTED] wrote: Positions I still stand by: - Sets belong in the language, and need more support. This can likely be done at the module level, but I'd like them better incorporated, preferably with their own sigil. However, I believe they can peacefully coexist with Junctions, and one concept does not need to crowd out the other. Instead of primary sigils, what about secondary sigils on an array to mark it as an unordered set? @|foo = any @foo = all @^foo = one # can arrays be curried arguments? hmm @!foo = none After all, why should scalars get all the good secondary sigils? :) Ashley Winters
Re: Junction Values
On Sat, Feb 19, 2005 at 02:40:00PM -0600, Rod Adams wrote: I addressed earlier concept of how does perl know when there are side effects, particularly with the execution path can weave to parts written in pure-parrot. Patrick responded by implying that there was no such side effect protection. I should've included this in my previous post...and write it now simply to promote clarity/completeness: My response in #19212 was intended to show that the side-effect problems being described don't exist, and therefore there isn't any need for side-effect protections such as the ones being proposed. I didn't mean to imply that they would be needed but not available. Pm
Re: Junction Values
Rod Adams wrote: Simply put, I want my junctions. Standard in Perl 6. I want my hyper operator superstrength arrays. Standard in Perl 6. I want them both at the same time. Standard in Perl 6. I never want to see implicit threading. Ever. If this is the only stumbling block, then it's easily solved. Instead of ruining junctions by imposing all kinds of complex and annoying hoops and hurdles (i.e. Cuse junctions and Cno junctions), we can just offer a Cno autothreading pragma that prevents any non-explicit junction from autothreading any operator or subroutine. Put it at the top of your code and you'll never get any implicit threading. Damian
Re: Junction Values
Damian Conway [EMAIL PROTECTED] wrote: Yes, it's a side-effect of the new default prohibition on junction assignments (though I'm still working hard to convince everyone that that prohibition cripples junctions and that having to use junctions before you can assign a basic Perl 6 scalar datatype to a variable is an abomination). Point of consideration: is accidentally autothreading over a junction any more dangerous than accidentally looping forever over an infinite lazy list? -- Brent 'Dax' Royal-Gordon [EMAIL PROTECTED] Perl and Parrot hacker I used to have a life, but I liked mail-reading so much better.
Re: Junction Values
Damian Conway wrote: Rod Adams wrote: I never want to see implicit threading. Ever. If this is the only stumbling block, then it's easily solved. Instead of ruining junctions by imposing all kinds of complex and annoying hoops and hurdles (i.e. Cuse junctions and Cno junctions), we can just offer a Cno autothreading pragma that prevents any non-explicit junction from autothreading any operator or subroutine. Put it at the top of your code and you'll never get any implicit threading. Well, allow me to explain what I want in a little more detail, so I can be sure I'm getting it. I want to be able to feed a junction to functions that handle it, but I also want to thread over ones that do not. But I do not want the decision of which way to go to be made for me. So, I want to be able to pass a raw junction into C == , because it understands junctions, and will take care of the threading for me, likely in a way that's much more efficient than my generalized »« threading ever could. I do not consider this implicit threading. It's passing the task of threading off to C == , which itself performs some form of explicit threading. But when I'm faced with some function that does not directly support junctions, or one which does, but not in a way that I like, I want to be able to thread my junction over it. I do not think that what you said above is enough to accomplish this. I believe what I need to separate your threading desires from mine is two fold: 1) I need my »« modifier which forces explicit threading, which will not normally be needed under use autothreading; conditions. 2) I need no autothreading; to alter the calling syntax to require »« when threading is desired (or you can do a .values() and .junctiontype() and roll your own if you really want to). But I can still pass junctions around at will, withstanding normal type check requirements. Then the only argument left is whether use autothreading or no autothreading should be default. I would, of course, say no autothreading;, and then turn back on the ability to store junctions. IMO, no autothreading would provide enough cover for the unsuspecting, removing the Bad Side Effects problems that spawned Larry's no junction storage default. At the same time, junctions still have enormous power via the »«. If people don't want to have to bother figuring out when to thread for themselves, they can then turn on use autothreading, and let perl attempt to figure it out for them. Also, if no autothreading is default, the person new to Perl6 will always have something to present to investigate to figure out what is going on. In my code, it'll be the funny looking C »$junction« things. In your code, it'll be the C use autothreading; at the top of the page. The only implementation problem I see is a potential for the »« to be mis-parsed, since » and « seem to be serving several different roles these days, but I don't think any of them conflict with this meaning. If you want to rename »« to something else, I'm open to suggestions. Just leave it fairly simple. As for why implementation should be easy (or at least the delta between your way and my way is easy): - The functionality of »$junction« has to be defined anyways if autothreading happens. It's just calling an already existent chunk of code. - The logic of when to thread becomes: given $situation { when marked_with_»«() { thread } when use_autothreading() damians_ouija_board() { thread } default { don't thread } } And you've already defined how the ouija board works, everything else should be boilerplate for the compiler/runtime to handle. This sound reasonable enough? -- Rod Adams
Re: Junction Values
Rod Adams [EMAIL PROTECTED] wrote: Larry Wall wrote: Junctions can short circuit when they feel like it, and might in some cases do a better job of picking the evaluation order than a human. I was afraid someone was going to say that. And I now must convert my reservations about junction autothreading from very disturbing to you've got to be kidding. ... Not to mention it contradicts S09: ... 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. Now there is some wiggle room in there for short circuiting, but not very much. The wiggle room is that the junction knows when it's being asked to collapse into a Boolean, and can know if there's no possible way the function it's running will have side effects. (That's why we're declaring ties now. There may be cases where we can't know for sure if there will be side effects or not--Halting Problem stuff--but we can make sure the junction optimizer is conservative. The Halting Problem becomes a lot easier if you ask whether a program *might* halt instead of whether it *will*.) In general, it seems to simply be an amazingly bad idea to autothread a function with side effects. In fact, I'd recommend that we warn if a side effect occurs during autothreading. Besides, people were telling me that my Sets were not needed, because they could be rendered with Arrays and Hashes. I fail to see how junctions are that different. Junctions are intended to be used mainly within conditionals and other statements; it's sort of a happy accident that they can be assigned to variables. At the intra-statement level, there's nothing else (short of involving a function like Cgrep) that'll do the job. From what I saw, your sets are mainly designed to be used at the inter-statement level, where we have arrays and hashes to do that sort of thing. I think junctions are important at the statement level because they help make similar things look similar. Consider these two statements: if($foo == $bar) { .. } if(grep { $foo == $_ } $bar, $baz) { ... } What makes these two statements so fundamentally different from each other that they should be expressed in ways that *look* so different? : - Edge cases which, IMHO, do not merit the huffman level of several : single character operators. All of which can be accomplished without the : use of junctions, though not as gracefully. Grace is important. Even more important is mapping naturally to human linguistic structures, to the extent that it can be done unambiguously. In my experience, English tends not to superimpose several values on a given noun at once. No, but nor does it have a concept quite like a variable. There's a reason many people have trouble understanding what 'x' and 'y' are all about in algebra. (And remember, algebra variables can sometimes have multiple values--consider y = x ** 2, for example.) Junctions are equivalent to the English sentence Get eggs, bacon, and toast from the store. (In Perl, that'd be something like C $store-get(eggs bacon toast) .) It's just a bit of orthogonality that allows you to give eggs, bacon, and toast a name and use it later. -- Brent 'Dax' Royal-Gordon [EMAIL PROTECTED] Perl and Parrot hacker I used to have a life, but I liked mail-reading so much better.
Re: Junction Values
On Feb 18, 2005, at 2:04 AM, Brent 'Dax' Royal-Gordon wrote: Junctions are equivalent to the English sentence Get eggs, bacon, and toast from the store. (In Perl, that'd be something like C $store-get(eggs bacon toast) .) It's just a bit of orthogonality that allows you to give eggs, bacon, and toast a name and use it later. Junctions are grocery lists, then. Regards, David
Re: Junction Values
Brent 'Dax' Royal-Gordon wrote: Rod Adams [EMAIL PROTECTED] wrote: Larry Wall wrote: Junctions can short circuit when they feel like it, and might in some cases do a better job of picking the evaluation order than a human. I was afraid someone was going to say that. And I now must convert my reservations about junction autothreading from very disturbing to you've got to be kidding. ... Not to mention it contradicts S09: ... 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. Now there is some wiggle room in there for short circuiting, but not very much. The wiggle room is that the junction knows when it's being asked to collapse into a Boolean, and can know if there's no possible way the function it's running will have side effects. (That's why we're declaring ties now. There may be cases where we can't know for sure if there will be side effects or not--Halting Problem stuff--but we can make sure the junction optimizer is conservative. The Halting Problem becomes a lot easier if you ask whether a program *might* halt instead of whether it *will*.) In general, it seems to simply be an amazingly bad idea to autothread a function with side effects. In fact, I'd recommend that we warn if a side effect occurs during autothreading. Besides, people were telling me that my Sets were not needed, because they could be rendered with Arrays and Hashes. I fail to see how junctions are that different. Junctions are intended to be used mainly within conditionals and other statements; If the set of these other statements is limited, consider creating a Junction class (which needs a use Junction; to activate), which overloads the various comparison operators for when a Junction is involved, and defines any/all/none/one as constructors? Throw in some overloading or bindings for |/^/, and it looks like you get everything your asking for. Having a method evaluate: C 5 == any(4,5,6) means that the interpreter doesn't need to autothread. This also makes it where only functions that were explicitly designed to use Junctions, or ones which didn't declare their signature, and thus are making no assumptions about what they are given, will perform the Junctive evaluations. This way, you get all the happy functionality, at the cost of typing use Junction;, and I get loads of protection against the evil side of autothreading. Doing Junctions this way also makes the them extensible. If someone figures out what a not junction is, they can add it in later. And people like me can't complain about what the module is doing to the language, because all's fair if you predeclare would be in effect. I think junctions are important at the statement level because they help make similar things look similar. Consider these two statements: if($foo == $bar) { .. } if(grep { $foo == $_ } $bar, $baz) { ... } What makes these two statements so fundamentally different from each other that they should be expressed in ways that *look* so different? You mean besides the shift in plurality? A shift in plurality in English forces you to modify a hefty portion of your sentence to accommodate it. At a minimum, you change your verb, in this case the C == . Shifting plurality in programming languages also incurs changes to the code around it. : - Edge cases which, IMHO, do not merit the huffman level of several : single character operators. All of which can be accomplished without the : use of junctions, though not as gracefully. Grace is important. Even more important is mapping naturally to human linguistic structures, to the extent that it can be done unambiguously. In my experience, English tends not to superimpose several values on a given noun at once. No, but nor does it have a concept quite like a variable. Which significantly weakens the mapping naturally to human linguistic structures argument, IMO. Junctions are equivalent to the English sentence Get eggs, bacon, and toast from the store. (In Perl, that'd be something like C $store-get(eggs bacon toast) .) Or just have C get() take a list, and it's: $store-get(eggs bacon toast); # is that the latest use of ? It's just a bit of orthogonality that allows you to give eggs, bacon, and toast a name and use it later. @shopping list = eggs bacon toast; gives them a name you can use later, as well. -- Rod Adams
Re: Junction Values
Larry Wall wrote: The need for junctions first became evident when we found ourselves filling the ~~ tables with various sorts of weird non-symmetries. ~~ can easily be called the DWIM compare operator. It even looks like you're waving your hands, asking for some strange voodoo to happen. It can also be thought of as Here! take these two things, do something with them, and tell me how it went. So it's magic central. And magic is invariably a messy thing to implement. And once the concept is out there, is makes sense to have practically every combination of types do _something_ useful if fed to ~~. Which makes it where ~~ is likely destined to be one of the most overloaded operators in the history of computing. So be it. It's amazingly useful. It also takes a monstrous amount of the Perl 6 DWIMery and puts it all in one place. Not to mention, you've already defined P6 to be good at this multi-sub/method game, so take advantage of it. It's not like this table will be represented all in one function (at least I hope not) -- Rod Adams
Re: Junction Values
Rod Adams writes: Junctions are intended to be used mainly within conditionals and other statements; If the set of these other statements is limited, consider creating a Junction class (which needs a use Junction; to activate), which overloads the various comparison operators for when a Junction is involved, and defines any/all/none/one as constructors? Throw in some overloading or bindings for |/^/, and it looks like you get everything your asking for. Having a method evaluate: C 5 == any(4,5,6) means that the interpreter doesn't need to autothread. This also makes it where only functions that were explicitly designed to use Junctions, or ones which didn't declare their signature, and thus are making no assumptions about what they are given, will perform the Junctive evaluations. Okay, I think your proposal is thinning. Perl is a dynamically typed language. I have no doubts that people will continue to ignore the type system even though it's there. I probably will. Let me demonstrate something: sub is_prime($x) { my @primes; for 2..sqrt($x) { if $_ % none(@primes) == 0 { push @primes, $_; } } return 1 if $x % none(@primes) == 0; } Run through your mind how this would be done with a junction in $x. Particularly focus on: 2..sqrt($x) What the hell does that mean? Do you get a junction of lists out? Or does sqrt die because it's not expecting a junction? When I say: if is_prime(any(@stuff)) {...} I expect to run the codeblock if any of my stuff is prime. Instead I get an error, always. I could always do this: if @stuff.grep:{ is_prime($_) } {...} But the whole point of junctions is to get rid of obscure expressions like that. Brent makes a fantastic case here. The point is that when you say makes no assumptions, you're giving the sub writers too much credit. I think a reasonable assumption (especially for these alledged novices you keep talking about) that these two code segments are equivalent: if $x == 2 {...} elsif $x == 3 {...} And: if $x == 2 {...} if $x == 3 {...} No matter what the value of $x. Yet in the presence of junctions, they are not. Also note that this is a practical example. I like the former, I know people who like the latter. It's a matter of style, and it's one that will bite you if you don't know about junctions. So what's it going to be? Avoiding the evil side of autothreading, or not crippling the usefulness of junctions in the presence of unwary code? It is a trade-off indeed. Java would choose the former. Perl is choosing the latter. Luke This way, you get all the happy functionality, at the cost of typing use Junction;, and I get loads of protection against the evil side of autothreading. Doing Junctions this way also makes the them extensible. If someone figures out what a not junction is, they can add it in later. And people like me can't complain about what the module is doing to the language, because all's fair if you predeclare would be in effect. I think junctions are important at the statement level because they help make similar things look similar. Consider these two statements: if($foo == $bar) { .. } if(grep { $foo == $_ } $bar, $baz) { ... } What makes these two statements so fundamentally different from each other that they should be expressed in ways that *look* so different? You mean besides the shift in plurality? A shift in plurality in English forces you to modify a hefty portion of your sentence to accommodate it. At a minimum, you change your verb, in this case the C == . Shifting plurality in programming languages also incurs changes to the code around it. : - Edge cases which, IMHO, do not merit the huffman level of several : single character operators. All of which can be accomplished without the : use of junctions, though not as gracefully. Grace is important. Even more important is mapping naturally to human linguistic structures, to the extent that it can be done unambiguously. In my experience, English tends not to superimpose several values on a given noun at once. No, but nor does it have a concept quite like a variable. Which significantly weakens the mapping naturally to human linguistic structures argument, IMO. Junctions are equivalent to the English sentence Get eggs, bacon, and toast from the store. (In Perl, that'd be something like C $store-get(eggs bacon toast) .) Or just have C get() take a list, and it's: $store-get(eggs bacon toast); # is that the latest use of ? It's just a bit of orthogonality that allows you to give eggs, bacon, and toast a name and use it later. @shopping list = eggs bacon toast; gives them a name you can use later, as well. -- Rod Adams
Re: Junction Values
On Fri, Feb 18, 2005 at 12:42:31PM -0600, Rod Adams wrote: No, but nor does it have a concept quite like a variable. Which significantly weakens the mapping naturally to human linguistic structures argument, IMO. Why exactly? It's just the variable-nature of variables that isn't exactly expressed linguistically, otherwise variables are just nouns really. Junctions are equivalent to the English sentence Get eggs, bacon, and toast from the store. (In Perl, that'd be something like C $store-get(eggs bacon toast) .) Or just have C get() take a list, and it's: $store-get(eggs bacon toast); # is that the latest use of ? It's just a bit of orthogonality that allows you to give eggs, bacon, and toast a name and use it later. @shopping list = eggs bacon toast; gives them a name you can use later, as well. Except that you've introduced a definite ordering where one isn't needed. This whole analogy has me wishing for an Exegesis. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: Junction Values
Luke Palmer wrote: Rod Adams writes: Junctions are intended to be used mainly within conditionals and other statements; If the set of these other statements is limited, consider creating a Junction class (which needs a use Junction; to activate), which overloads the various comparison operators for when a Junction is involved, and defines any/all/none/one as constructors? Throw in some overloading or bindings for |/^/, and it looks like you get everything your asking for. Having a method evaluate: C 5 == any(4,5,6) means that the interpreter doesn't need to autothread. This also makes it where only functions that were explicitly designed to use Junctions, or ones which didn't declare their signature, and thus are making no assumptions about what they are given, will perform the Junctive evaluations. Okay, I think your proposal is thinning. I'm trying to salvage what I can, since people seem to be rejecting everything I offer. Perl is a dynamically typed language. I have no doubts that people will continue to ignore the type system even though it's there. I probably will. So will I. Let me demonstrate something: sub is_prime($x) { my @primes; for 2..sqrt($x) { if $_ % none(@primes) == 0 { push @primes, $_; } } return 1 if $x % none(@primes) == 0; } Run through your mind how this would be done with a junction in $x. Particularly focus on: 2..sqrt($x) What the hell does that mean? Do you get a junction of lists out? Or does sqrt die because it's not expecting a junction? What on earth does C for (2..sqrt(3|5)) {...} mean in the current state of junctions? But as written, yes, sqrt() would likely throw an exception under my proposal. When I say: if is_prime(any(@stuff)) {...} I expect to run the codeblock if any of my stuff is prime. Instead I get an error, always. I could always do this: if @stuff.grep:{ is_prime($_) } {...} Should also be able to overload Junction ~~ CodeRef to make this work: if any(@stuff) ~~ is_prime {...} In this manner, you are explicitly controlling when and how the autothreading happens. There is no way for is_prime to slurp up the junction and pass it on in this case. However, in the current scheme, if is_prime() is written to accept a slurpy list of parameters (either by design, or just a habit from the P5 days), we can have: sub is_prime { my @primes; for 2..sqrt(@_[0]) { if $_ % none(@primes) == 0 { push @primes, $_; } } return 1 if $x % none(@primes) == 0; } Pushing the autothreading directly onto the C for (2..sqrt(3|5)) {...} , which as you pointed out earlier, is almost definitely _not_ what was wanted, whatever it means. (btw, My current analysis says it will stop at the lowest value in the junction.) I view it as a definite plus to make the autothreading explicit. I doesn't need it to be ugly, just present. In fact, that's all I need to shut up on this whole issue. Something that says: autothreading into functions only happens when you slap (whatever) in there. I can live with auto-autothreading over operators (I'd rather not, though). But calling into a function needs something stronger. Yes, operators are functions, too, but if you're fancy enough to be writing you're own operators, you're fancy enough to take junctions into account. Something like: if is_prime(any(@stuff)) {...} Would more than suffice. It says that you're not attempting to pass the junction, but instead doing something in parallel, which is what the hyper operators are all about, anyways. It's been the side effects of autothreading that has been my big hold up. If you make it happen explicitly, it's just another looping construct ( a very odd one, but one nonetheless ). If it happens implicitly, it's way too magical and dangerous for my tastes. Give me that, and I'll probably start liking Junctions. I've never argued that they weren't powerful. But the whole point of junctions is to get rid of obscure expressions like that. Brent makes a fantastic case here. The point is that when you say makes no assumptions, you're giving the sub writers too much credit. I think a reasonable assumption (especially for these alledged novices you keep talking about) that these two code segments are equivalent: if $x == 2 {...} elsif $x == 3 {...} And: if $x == 2 {...} if $x == 3 {...} No matter what the value of $x. Yet in the presence of junctions, they are not. Also note that this is a practical example. I like the former, I know people who like the latter. It's a matter of style, and it's one that will bite you if you don't know about junctions. You get into this problem when you allow any form of overloading of built in operators, not just with junctions. It'd be trivial to create an AlwaysTrue class, which overloads all forms of comparison against it to always return
Re: Junction Values
On Fri, 18 Feb 2005 12:47:51 -0700, Luke Palmer [EMAIL PROTECTED] wrote: Run through your mind how this would be done with a junction in $x. Particularly focus on: 2..sqrt($x) What the hell does that mean? Do you get a junction of lists out? Or does sqrt die because it's not expecting a junction? sqrt() won't die; it gets threaded and returns a Junction, I would expect. It's the lack of an *infix:..(Int, Junction) function which causes death I suppose you could write one which would pick a random value: multi sub *infix:..(Int $x, Junction $y) { return $x .. first { .does(Int) } $y.values; } Ashley Winters
Re: Junction Values
Ashley Winters [EMAIL PROTECTED] writes: On Fri, 18 Feb 2005 12:47:51 -0700, Luke Palmer [EMAIL PROTECTED] wrote: Run through your mind how this would be done with a junction in $x. Particularly focus on: 2..sqrt($x) What the hell does that mean? Do you get a junction of lists out? Or does sqrt die because it's not expecting a junction? sqrt() won't die; it gets threaded and returns a Junction, I would expect. It's the lack of an *infix:..(Int, Junction) function which causes death Why does that cause death instead of authothreading? Eirik -- Ever heard of .cshrc? That's a city in Bosnia. Right? (Discussion in comp.os.linux.misc on the intuitiveness of commands.)
Re: Junction Values
On Fri, 18 Feb 2005 23:12:40 +0100, Eirik Berg Hanssen [EMAIL PROTECTED] wrote: Ashley Winters [EMAIL PROTECTED] writes: On Fri, 18 Feb 2005 12:47:51 -0700, Luke Palmer [EMAIL PROTECTED] wrote: Run through your mind how this would be done with a junction in $x. Particularly focus on: 2..sqrt($x) What the hell does that mean? Do you get a junction of lists out? Or does sqrt die because it's not expecting a junction? sqrt() won't die; it gets threaded and returns a Junction, I would expect. It's the lack of an *infix:..(Int, Junction) function which causes death Why does that cause death instead of authothreading? Okay, I changed my mind. I think it does it does work for ~~ matching, but not as an iterator given 2 { when 1 .. sqrt(3|6) { ... }# would work } for(1 .. sqrt(3|6)) { ... } # would fail, since Junction doesn't do Iterator or whatever 1 .. sqrt(10) - LazyList of (1..3) 1 .. sqrt(10|20) - Junction of any(1,2,3, 1,2,3,4) LazyList does Iterator, but Junction does not. You'd have to use (1 .. sqrt(3|6)).values to iterate through the possible values semi-randomly. More likely, I'm nuts. Ashley
Re: Junction Values
On Fri, 18 Feb 2005 14:35:53 -0800, Ashley Winters [EMAIL PROTECTED] wrote: 1 .. sqrt(10) - LazyList of (1..3) 1 .. sqrt(10|20) - Junction of any(1,2,3, 1,2,3,4) LazyList does Iterator, but Junction does not. You'd have to use (1 .. sqrt(3|6)).values to iterate through the possible values semi-randomly. Okay, changed my mind again. 1 .. sqrt(10|20) - Junction of any(1,2,3, 1,2,3,4) therefore, for(1 .. sqrt(10|20)) iterates ONCE, but $_ is a junction. Anything inside the loop which uses $_ would autothread. Anything which doesn't use $_ would only get called once. That's insane, right? for(1 .. sqrt(10|20) { if($_ 2) {}# uses junctive value say Here; # called once bar($_); # calls bar() lots of times } More likely, I'm nuts. I'm definitely crazy. I give up! I'll stop now, since I clearly don't get it. :) Ashley Winters
Re: Junction Values
Hmmm... It seems that this way does lie madness -- there's a fundamental ambiguity between autothreading happening inside or outside the declared loop, and there's no least surprising way to implement it. Certainly inside the loop is the easiest and most natural to implement, but that acts strange from an API standpoint. Outside the loop works well from an API standpoint but introduces all sorts of weird cases that the implementation has to consider. P5/PDL has some junction-like aspects, in that it does autothreading. We sidestep the issue by not allowing multiple-element PDLs in boolean comparisons, but treating single-element PDLs as scalars whenever possible. This flows down to '..', so (1..pdl(3)) returns (1,2,3) or does the Right Thing in scalar context -- but (1..pdl(3,4)) probably ought to throw an exception (it actually returns the empty set or always-false, depending on context). I'm no language designer, but it seems to me that certain operators simply won't generalize well to the autothreaded case, and those operators should simply try to pick up the pieces -- ie treat single-element junctions like ordinary scalars, and treat empty junctions like undef values, but otherwise do something exceptional (whether or not that involves throwing an actual exception). My personal preference is that constructs like 1..($a|$b) should be disallowed. It's certainly easy enough to expand the junction manually into a list and loop over that. Note that other weird constructs in perl5, such as (1..[2,3]), do very surprising, architecture-dependent things. Quoth Ashley Winters on Friday 18 February 2005 04:09 pm, On Fri, 18 Feb 2005 14:35:53 -0800, Ashley Winters [EMAIL PROTECTED] wrote: 1 .. sqrt(10) - LazyList of (1..3) 1 .. sqrt(10|20) - Junction of any(1,2,3, 1,2,3,4) LazyList does Iterator, but Junction does not. You'd have to use (1 .. sqrt(3|6)).values to iterate through the possible values semi-randomly. Okay, changed my mind again. 1 .. sqrt(10|20) - Junction of any(1,2,3, 1,2,3,4) therefore, for(1 .. sqrt(10|20)) iterates ONCE, but $_ is a junction. Anything inside the loop which uses $_ would autothread. Anything which doesn't use $_ would only get called once. That's insane, right? for(1 .. sqrt(10|20) { if($_ 2) {}# uses junctive value say Here; # called once bar($_); # calls bar() lots of times } More likely, I'm nuts. I'm definitely crazy. I give up! I'll stop now, since I clearly don't get it. :) Ashley Winters
Re: Junction Values
Craig DeForest wrote: Hmmm... It seems that this way does lie madness -- there's a fundamental ambiguity between autothreading happening inside or outside the declared loop, and there's no least surprising way to implement it. Certainly inside the loop is the easiest and most natural to implement, but that acts strange from an API standpoint. Outside the loop works well from an API standpoint but introduces all sorts of weird cases that the implementation has to consider. I would think that my latest idea of turning off autothreading per se, and replacing it with an explicit threading call/operator, would solve this dilemma. The idea was specifically to have it where threading happened on function calls when a junction was surrounded by hyper operators. Otherwise, the junction is passed as is. So we still get: if $x == 3|4|5|6 {...} would thread over infix:== without any funkiness, since we'll assume operators are well written, and can take junctions as parameters, same as: if is_prime(3|4|5|6) {...} Would pass the junction to is_prime, to do with as it pleases, including throwing an exception. However, if is_prime(»3|4|5|6«) {...} would thread over is_prime, and collate the results outside of call. These semantics also give us the ability to easily mix and match what we send to a function, so we can say: if funky_test(all(@A), »any(@B)«) {...} Basically I'm putting all the power of threading into the hands of the caller. I will further argue that C »junction« should not short circuit. It should do the simple brute force try all values approach, since the side effects are likely desired. Operators, which should be able to accept junctions as parameters, are encouraged to short circuit, since there are no side effects possible for the evaluation of that operator. By the time the operator gets called, it should have all the parameters it needs, and there are no more side effects to be had. As for C .. , I'd say that it should handle junctions being fed into it by throwing an exception. -- Rod Adams
Re: Junction Values
Rod Adams [EMAIL PROTECTED] wrote: if $x == 3|4|5|6 {...} would thread over infix:== without any funkiness, since we'll assume operators are well written, and can take junctions as parameters, same as: if is_prime(3|4|5|6) {...} Would pass the junction to is_prime, to do with as it pleases, including throwing an exception. However, if is_prime(»3|4|5|6«) {...} would thread over is_prime, and collate the results outside of call. So basically you're proposing that, rather than do one implicit loop that'll probably do what you want, the default should be to do an unknown number of implicit loops in somebody else's code, and you have to ask explicitly for the more sensible behavior. Somehow this doesn't strike me as an improvement. These semantics also give us the ability to easily mix and match what we send to a function, so we can say: if funky_test(all(@A), »any(@B)«) {...} sub funky_test ( Junction|Any @a, @b ) { ... } Basically I'm putting all the power of threading into the hands of the caller. The caller is not in a position to know if the callee is internally structured in such a way that passing in a raw junction makes sense. The right place to say I can handle a junction, don't autothread is in the callee; that's the behavior @Larry is proposing. As for C .. , I'd say that it should handle junctions being fed into it by throwing an exception. Why is this more sensible than returning a list of junctions in list context and a junction of arrayrefs in scalar context? (I believe infix:.. will return an arrayref in scalar context, though I could be wrong.) (The array of junctions is negotiable, by the way; whatever it is, though, it should probably be the same as the default meaning for list returns from an autothreaded function.) -- Brent 'Dax' Royal-Gordon [EMAIL PROTECTED] Perl and Parrot hacker I used to have a life, but I liked mail-reading so much better.
Re: Junction Values
Rod Adams [EMAIL PROTECTED] wrote: Luke Palmer wrote: 2..sqrt($x) What the hell does that mean? Do you get a junction of lists out? Or does sqrt die because it's not expecting a junction? What on earth does C for (2..sqrt(3|5)) {...} mean in the current state of junctions? In the current state of junctions, the autothreading is done at the level of the call to do_prime, so $x is never a junction. Only under your notion of junctions as just another object with no autothreading until the operator level will $x ever be a junction. But if it somehow *did* become a junction, I would imagine something like this would happen: for (2 .. sqrt( 3 | 5 )) { ... } for (2 .. ( sqrt 3 | sqrt 5 )) { ... } for ( ( 2 .. sqrt 3 ) | ( 2 .. sqrt 5 ) ) { ... } for ( 2 .. sqrt 3 ) { ... } | for ( 2 .. sqrt 5 ) { ... }#notionally However, it's clear that the last step doesn't make a whole lot of sense, since Cfor has no return value. Maybe Cfor would be declared with a signature that didn't allow junctions at all. However, in the current scheme, if is_prime() is written to accept a slurpy list of parameters (either by design, or just a habit from the P5 days), we can have: I will readily admit that the behavior of junctions in a slurpy subroutine call is suboptimal, and it might be a good idea to reexamine it. However, I will also point out that most newbie programmers probably won't use the @_ behavior, and likely won't be using slurpy parameters either, while more experienced programmers will know better. -- Brent 'Dax' Royal-Gordon [EMAIL PROTECTED] Perl and Parrot hacker I used to have a life, but I liked mail-reading so much better.
Re: Junction Values
Brent 'Dax' Royal-Gordon wrote: Rod Adams [EMAIL PROTECTED] wrote: Luke Palmer wrote: 2..sqrt($x) What the hell does that mean? Do you get a junction of lists out? Or does sqrt die because it's not expecting a junction? What on earth does C for (2..sqrt(3|5)) {...} mean in the current state of junctions? In the current state of junctions, the autothreading is done at the level of the call to do_prime, so $x is never a junction. Actually, if one writes is_prime to have slurpy array passing a la Perl5, as I wrote in a different post, $x most certainly is a junction at this point. Although this does beg the question: If by default one can't assign a junction to a variable, does this apply only in cases with an assignment operator, or does it also happen on parameter passing? I've just reread Larry's post about normally disallowing storage of junctions in a lvalue. He covers the point about declaring parameters that are junctional, and the parameters are otherwise non-junctional. What is not clear here is whether or not the S09 talk about if a junction is inside another container (like a slurpy array), if it gets caught or not. The array itself is not a junction, but one or more of it's elements might be. So do we have to walk the entire reference tree if we are given a complex data type, looking for junctions? This is not an option, think no further than lazy lists to see why. So the other option is to have a runtime check, and as soon as a memory store containing a junction is encountered, then throw an exception. Even if this happens well after the parameter passing step. Hmm. Messy, but possible. Only under your notion of junctions as just another object with no autothreading until the operator level will $x ever be a junction. For the record, I've withdrawn that proposal. All I want now is for autothreading to be explicit. But if it somehow *did* become a junction, I would imagine something like this would happen: for (2 .. sqrt( 3 | 5 )) { ... } for (2 .. ( sqrt 3 | sqrt 5 )) { ... } for ( ( 2 .. sqrt 3 ) | ( 2 .. sqrt 5 ) ) { ... } for ( 2 .. sqrt 3 ) { ... } | for ( 2 .. sqrt 5 ) { ... }#notionally However, it's clear that the last step doesn't make a whole lot of sense, since Cfor has no return value. Maybe Cfor would be declared with a signature that didn't allow junctions at all. Or is it the case that C .. acts a bit like the old flip flop it used to be, and stop at the first true value it sees? AFAIK, the concept of Junctional Lists has not been created yet, so what else would it return? A list of junctions? all of which are ($x|$x) or ($x|undef)? However, in the current scheme, if is_prime() is written to accept a slurpy list of parameters (either by design, or just a habit from the P5 days), we can have: I will readily admit that the behavior of junctions in a slurpy subroutine call is suboptimal, and it might be a good idea to reexamine it. However, I will also point out that most newbie programmers probably won't use the @_ behavior, and likely won't be using slurpy parameters either, while more experienced programmers will know better. Except for the absolutely massive amount of Perl5 code out there that will be hastily translated by people who don't trust the Perl6 - Ponie interplay, and the flocks of Perl5 programmers coming over without learning all the new features of their upgraded language, you're probably right. -- Rod Adams
Re: Junction Values
Brent 'Dax' Royal-Gordon wrote: Rod Adams [EMAIL PROTECTED] wrote: if $x == 3|4|5|6 {...} would thread over infix:== without any funkiness, since we'll assume operators are well written, and can take junctions as parameters, same as: if is_prime(3|4|5|6) {...} Would pass the junction to is_prime, to do with as it pleases, including throwing an exception. However, if is_prime(»3|4|5|6«) {...} would thread over is_prime, and collate the results outside of call. So basically you're proposing that, rather than do one implicit loop that'll probably do what you want, the default should be to do an unknown number of implicit loops in somebody else's code, and you have to ask explicitly for the more sensible behavior. Somehow this doesn't strike me as an improvement. What I'm asking for is to be in control of how often I get the possible side effects of calling a function. If I make a call to a DBI method to go insert a record, I want exactly 0 (on error) or 1 (on success) records inserted into my database, _unless_ I told it do otherwise. Since a junction is a single item, it should produce a single effect _unless_ I tell it to expand the values and act like several items at once. Simply put, I want control over my side effects. As for whether passing the junction as a junction or passing the junction via autothreading should be the default: Junctions exists. I want to say stay a junction or explode into pieces, go your separate ways, and then come back. In one case I'm doing nothing to the junction, in the other case I'm doing quite a bit. So it makes sense that the latter is something additional to the former. Taking into account how common that particular action might be, I chose to propose a rather short modification to it, that still clearly said something special was going on here. One could say I'm just extending the hyper operator from do this operator several times to do this expression several times. More sensible behavior is entirely subject to the exact instance at hand. In the case of let's say C == , I want to feed it the raw, unexploded junction. I well written C == should be able to apply all kinds of optimizations to the task at hand, and provide much more sensible results. I expect calls with operators to be considerably more common than function calls w/ junctions. So if I grant you your default of autothreading, we then get: if $x == »3|4|5« {...} given $x { when »3|4|5« {...} } Which seemed far more suboptimal than the other way around, IMO. These semantics also give us the ability to easily mix and match what we send to a function, so we can say: if funky_test(all(@A), »any(@B)«) {...} sub funky_test ( Junction|Any @a, @b ) { ... } Unless you have a junction, and you wanted it to autothread on the first parameter, rather than be passed in, in order to get some perceived desirable side effect out of funky_test that passing it a Junction would only give a subset of. Suppose funky_test is a derivative of C printf . Only this printf let's you feed it a junction for the format, and it will sort through them and see which one matches best depending on actual number of parameters, parameter types, etc. Ordinarily, this would be fairly cool stuff. But let's say you instead wanted it to print the same data with all the different formats. With my calling, you could make the distinction rather easily. With yours, you have to set up the looping yourself. Basically I'm putting all the power of threading into the hands of the caller. The caller is not in a position to know if the callee is internally structured in such a way that passing in a raw junction makes sense. Sure they are. It's called reading the documentation. If it doesn't say it can handle junctions, it probably can't. The right place to say I can handle a junction, don't autothread is in the callee; that's the behavior @Larry is proposing. I'm sending the same message. Only my message goes to the programmer, not the runtime. I'm also making it where the decision to insert autothreading code or not is made at compile time, not runtime. As for C .. , I'd say that it should handle junctions being fed into it by throwing an exception. Why is this more sensible than returning a list of junctions in list context and a junction of arrayrefs in scalar context? (I believe infix:.. will return an arrayref in scalar context, though I could be wrong.) (The array of junctions is negotiable, by the way; whatever it is, though, it should probably be the same as the default meaning for list returns from an autothreaded function.) About the only thing is could return would be a lazy list of junctions. And about the only places C .. gets used is inside C for and inside array slice indices. Lists of junctions certainly make no sense in a for loop... the loop cannot simultaneously exit and not exit at the same time. Feeding a list
Re: Junction Values
Rod Adams [EMAIL PROTECTED] wrote: Suppose funky_test is a derivative of C printf . Only this printf let's you feed it a junction for the format, and it will sort through them and see which one matches best depending on actual number of parameters, parameter types, etc. Ordinarily, this would be fairly cool stuff. But let's say you instead wanted it to print the same data with all the different formats. With my calling, you could make the distinction rather easily. With yours, you have to set up the looping yourself. I would argue that this function is badly designed. Junctions are intended to ultimately be used in boolean tests. That's why the values of the junction have an any/all/one/none relationship. The proper data structure here is an array. (Actually, ironically enough, it's probably a set, not an array.) IMHO, there are three cases where it's legitimate to specifically ask for junctions to be passed in: 1. When it makes absolutely no sense to use a junction in a particular function, especially one with side effects.[1] 2. When doing some sort of junction-aware serialization, a la Storable or Data::Dumper. 3. When the author of the function can optimize the way junctions are handled without changing their basic semantics. Outside of these cases, it's probably wrong. A junction is *not* a meaningless data structure to be slung around at will; it is a construct that implies a certain type of behavior when used. The caller is not in a position to know if the callee is internally structured in such a way that passing in a raw junction makes sense. Sure they are. It's called reading the documentation. If it doesn't say it can handle junctions, it probably can't. I don't want to have to stop in the middle of a hundred-line function to think, Does Store::Market.get act sanely when I give it a junction? Do I need to explode it manually, or will it handle the junction nicely on its own? Nor do I want to work in a language where most functions don't handle a basic construct elegantly, even when they can. About the only thing is could return would be a lazy list of junctions. And about the only places C .. gets used is inside C for and inside array slice indices. Lists of junctions certainly make no sense in a for loop... the loop cannot simultaneously exit and not exit at the same time. You don't think this makes sense? (Cfor itself wouldn't autothread; the calls and operators inside the loop body would.) for 1|2, 3|4, 5|6 { ... } (Actually, Synopsis 3 talks about what happens when you give Cfor a single junction--essentially, it loops over the contents of the junction in whatever order it feels is most optimal. But in this case we're giving it an array of junctions, which presumably would act differently) Feeding a list of junctions into an array slice index is asking for what? Another list of junctions out? Synopsis 3: print if @foo[any(1,2,3)] [1] Note, however, that this needs to be done carefully. For example, while it doesn't really make sense for the string arguments of a call to Cprint to be junctions, the object argument is another matter entirely: #!/usr/bin/perl6 # naive tee $OUT=$OUT open( $_) for @ARGS; print or die Can't write to $!.filename: $! for *$IN;# Or however it's done this week -- Brent 'Dax' Royal-Gordon [EMAIL PROTECTED] Perl and Parrot hacker I used to have a life, but I liked mail-reading so much better.
Re: Junction Values
Rod Adams wrote: All I want now is for autothreading to be explicit. It already *is*. The only way that: is_prime($x) can ever autothread is if $x holds a junction. But that can now only happen if there's an explicit Cuse junctions in scope where $x was assigned to (or the explicit use of some other module that also activates Cuse junctions). So $x having a junction must be a known possibility at that point. Of course, literal junctions *will* autothread in all circumstances: is_prime(any(6,7,8)) is_prime(6|7|8) But they're both explicit too: you're explicitly using junction constructors, so the autothreading can hardly come as a surprise. And if: is_prime($x) does happen to autothread when you weren't expecting it to, then one of two things will happen. Either the subroutine will be 'pure' in which case there's no problem in autothreading it; or else the subroutine will have side effects, in which case you'll get an explicit warning when the autothreading occurs. Junctions are just another type of scalar value. All the arguments I hear against that seem to mirror the arguments we always hear against Perl scalars being dynamically typed at all: but how will you know whether $x has a number or a string or a reference in it??? And of course the answer is: most people know most of the time, simply by paying attention to the data flow of their program. And when they occasionally mess up and accidentally give a function or subroutine the wrong kind of value, Perl usually warns them about it. Personally, I think it's completely fascist to require a Cuse junctions pragma in order for junctions to even be stored in variables. It's as bizarre as requiring Cuse strings or Cuse references or Cuse undef or Cuse infinities would be. Yes, it *is* possible to get unexpected behaviour from passing a junction where it isn't expected, but it's already possible to get unexpected behaviour by passing a string or an undef or a reference or an object where it isn't expected. Junctions are nothing new in that respect. I think junctions ought to be first class scalar data types and not have to ask permission before they can even be assigned. If you want to be sure that a particular variable doesn't have a junction in it, you should have to specify that, in exactly the same way you have to be explicit in order to prevent a variable storing a string or a reference or an object...by giving it an explicit type: my Num $x; # Can't store a string or reference my Ref $y; # Can't store a number or string my Nonjunctive $x; # Can't store junctions And where did CNonjunctive come from? I created it. Ironically, by using the Awesome Power of Junctions: type Nonjunctive ::= none(Junction); And if typing a variable to prevent it storing a junction is too onerous, it would still be perfectly sufficient to simply provide a Cno junctions pragma, under whose geas no junction shall be suffered to live. Look, I do understand the arguments in the other direction. I've understood them for the past five years that I've been developing the concept of superpositional data-types. I've thought them through numerous times myself, and in the end: I just don't buy them. The whole point of junctions is to make the threading of operations on datasets both automatic and implicit; to make it Do The Right Thing without the hassles of explicit threading. If you don't want that, that's fine: just don't use junctions. Use arrays and hyperoperators instead. And we'll happily give you a Cno junctions pragma so you can be emphatic about not wanting them. But bowdlerizing the concept of junctions isn't the answer. Damian
Re: Junction Values
Brent 'Dax' Royal-Gordon wrote: Rod Adams [EMAIL PROTECTED] wrote: Larry Wall wrote: That, and we'd like a novice to be able to write given $x { when 1 | 2 | 3 {...} when 4 | 5 | 6 {...} } Or just change Cwhen to accept a list of things to compare against, followed by a coderef. And change if, unless, while and until to do the same thing. Actually, upon further investigation, I believe we get this all of this without junctions. According to S03, The scalar comma |,| now constructs a list reference of its operands. Then S04 mentions that C $scalar ~~ @array is true if $scalar is in @array. Since C given ... when uses smart matching for it's evaluation, one should be able to write the above as: given $x { when 1, 2, 3 {...} # at worst, this is: when (1,2,3) {...} when 4, 5, 6 {...} } The simple if is: if $x ~~ (1,2,3,4) {...} # parens needed here since , is lower than ~~ in precedence. Same for unless/while/until. And all of this from the entirely useful C ~~ . The S04 code describing @Array ~~ $Scalar (for Num/Str) uses junctions, but I'd argue a better implementation would be a short circuiting C for loop, even if junctions exist. It's just plain faster that way. So what I see now for utility of junctions is thus: - Common cases which C ~~ appears to handle for us suitably well. - Edge cases which, IMHO, do not merit the huffman level of several single character operators. All of which can be accomplished without the use of junctions, though not as gracefully. I see no need for junctions in core. And lose the ability to say: when none(1, 2, 3) { ... } when 1 ^ 2 ^ 3 { ... }# More useful with classes, regexen, etc. when 1 2 3 { ... }# Likewise All so that a newbie doesn't confuzzle himself. You can always write your switch statements the Perl 5 way. Or you could write: when ({$^a ~~ /1/ $^a ~~ /2/ $^a ~~/3/}) {...} And the like. Look up what C $scalar ~~ $coderef does if you're not convinced. (side question: what is the proper syntax for using a closure as the evaluation expression in a C when statement?) hmm, since the $_ is set, you could likely get away with: when ({/1/ /2/ /3/}) {...} in the case of RE's. Personally, I'd rather have a chain saw than a nail trimmer, even if I'm less likely to hurt myself with the nail trimmer. And it looks like we'll have a warning or stricture to keep newbies from chopping their legs off anyway. I can understand your sentiments here, but I'd be a lot more sympathetic to your cause if the alternative ways of accomplishing these things were actually difficult. I think it's been demonstrated that any of the junction evaluations could be done with a call to C grep , with numerous other ways to perform them as well. -- Rod Adams
Re: Junction Values
On Thu, Feb 17, 2005 at 02:18:55AM -0600, Rod Adams wrote: : The simple if is: : : if $x ~~ (1,2,3,4) {...} # parens needed here since , is lower than ~~ : in precedence. That is asking if $x is a list containing 1,2,3,4. : Same for unless/while/until. And all of this from the entirely useful C : ~~ . The S04 code describing @Array ~~ $Scalar (for Num/Str) uses : junctions, but I'd argue a better implementation would be a short : circuiting C for loop, even if junctions exist. It's just plain : faster that way. Junctions can short circuit when they feel like it, and might in some cases do a better job of picking the evaluation order than a human. : So what I see now for utility of junctions is thus: : : - Common cases which C ~~ appears to handle for us suitably well. Only if we make lists second-class citizens. The need for junctions first became evident when we found ourselves filling the ~~ tables with various sorts of weird non-symmetries. : - Edge cases which, IMHO, do not merit the huffman level of several : single character operators. All of which can be accomplished without the : use of junctions, though not as gracefully. Grace is important. Even more important is mapping naturally to human linguistic structures, to the extent that it can be done unambiguously. : I see no need for junctions in core. I do, and I'm not likely to change my mind on this one. Sorry. Larry
Re: Junction Values
On Thu, Feb 17, 2005 at 09:06:47AM -0800, Larry Wall wrote: Junctions can short circuit when they feel like it, and might in some cases do a better job of picking the evaluation order than a human. Hmm, yes, there is an interesting interaction with lazy evaluation ranges here. $x = any( 1 .. 1_000_000_000 ); if( $y == $x ) { ... } It would be nice if the junction equality test here was much smarter than a for loop (regardless of whether the for loop short circuited - suppose $y happens to be -1!). A range need not enumerate all of its components to be used in a useful way. --
Re: Junction Values
Larry Wall wrote: On Thu, Feb 17, 2005 at 02:18:55AM -0600, Rod Adams wrote: : The simple if is: : : if $x ~~ (1,2,3,4) {...} # parens needed here since , is lower than ~~ : in precedence. That is asking if $x is a list containing 1,2,3,4. Quoting S04: $_ $xType of Match ImpliedMatching Code == = == Array Array arrays are identical match if $_ »~~« $x Array any(list) list intersectionmatch if any(@$_) ~~ any(list) Array Rule array grep match if any(@$_) ~~ /$x/ Array Num array contains numbermatch if any($_) == $x Array Str array contains stringmatch if any($_) eq $x And since there are no tell tell *'s on these saying that they are _not_ reversible, I must assume they _are_. In C if $x ~~ (1,2,3,4) {...} , if $x is type Num or Str, then I see no way of reconciling your statement above. : Same for unless/while/until. And all of this from the entirely useful C : ~~ . The S04 code describing @Array ~~ $Scalar (for Num/Str) uses : junctions, but I'd argue a better implementation would be a short : circuiting C for loop, even if junctions exist. It's just plain : faster that way. Junctions can short circuit when they feel like it, and might in some cases do a better job of picking the evaluation order than a human. I was afraid someone was going to say that. And I now must convert my reservations about junction autothreading from very disturbing to you've got to be kidding. According to Patrick, and since no one has corrected him, I will assume he is right, perl6 -e say1 'cat'|'dog'; sub say1 ($x) {say $x} Should output cat\ndog\n or dog\ncat\n. Now, if we allow Junctions to short circuit, and since there is no fixed order of values in a junction, we could get any of cat\ndog\n, dog\ncat\n, cat\n, or dog\n. What's that get us? non-deterministic output! I could handle non-deterministic *order* of output, because by the simple fact that you were using a junction, you didn't care about order. Non-deterministic output! how fun! Not to mention it contradicts S09: ... 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. Now there is some wiggle room in there for short circuiting, but not very much. : So what I see now for utility of junctions is thus: : : - Common cases which C ~~ appears to handle for us suitably well. Only if we make lists second-class citizens. The need for junctions first became evident when we found ourselves filling the ~~ tables with various sorts of weird non-symmetries. So what other semantic makes sense for: Str ~~ Array Num ~~ Array which would better appeal to your sense of symmetry? Besides, people were telling me that my Sets were not needed, because they could be rendered with Arrays and Hashes. I fail to see how junctions are that different. : - Edge cases which, IMHO, do not merit the huffman level of several : single character operators. All of which can be accomplished without the : use of junctions, though not as gracefully. Grace is important. Even more important is mapping naturally to human linguistic structures, to the extent that it can be done unambiguously. In my experience, English tends not to superimpose several values on a given noun at once. : I see no need for junctions in core. I do, and I'm not likely to change my mind on this one. Sorry. I realized that fairly early on. The situation I'm in is that while I don't agree with all the design initiatives that come out here, it's been the case that the more I think about them, the more I like them. I always achieve at least a state of ambivalence or better about it. With Junctions, it's been the case that at first I thought they were useful and cool, but the more I think about them, the more I dislike them. I'll argue my case for a few more days, and if I haven't gotten anywhere by then, I'll likely give up. -- Rod Adams
Re: Junction Values
Jonathan Scott Duff [EMAIL PROTECTED] writes: On Wed, Feb 16, 2005 at 12:17:35PM +1100, Damian Conway wrote: none($a, $a) == undef True. Isn't this one false in the case when $a is undef? Since it is numerical comparison, it is false as long as $a == 0. (I would hope.) Eirik -- So this is the Sword of Immortality? Huh? What's it doin' in a CRYPT?! --- John S. Novak, III, quoting an unnamed player
Re: Junction Values
On Wed, 16 Feb 2005 12:17:35 +1100, [EMAIL PROTECTED] (Damian Conway) wrote: ..values tells you what raw values are inside the junction. The other kind of introspection that's desirable is: what raw values can *match* this junction. There would probably be a .states method for that. To see the difference between the two, consider: my $ideal_partner = all( any(tall dark rich), any(rich old frail), any(Australian rich), ); $ideal_partner.values would return the three distinct values in the junction: ( any(tall dark rich), any(rich old frail), any(Australian rich), ); But $ideal_partner.states would return only those non-junctive values that (smart-)match the junction. Namely, rich. I, and I think many others, have been trying to follow along on the discussions regarding junctions, and I have to say that for the most part, much of it goes insert graphic of open hand, palm down, waving to and fro above head. Any chance that you could provide one or two simple but realistic examples of using Junctions and their operators? I see individual snippets of use and they appear to make sense, but when I try envisage using them in code I have recently written, I find nothing leaping off the page at me as an obvious candidate. Thanks.
Re: Junction Values
On Wed, Feb 16, 2005 at 01:06:22PM +, Nigel Sandever wrote: Any chance that you could provide one or two simple but realistic examples of using Junctions and their operators? I'll give it a shot, but keep in mind that I'm somewhat new to this also. :-) First, junctions are an easy way to represent the relationships any, all, one, or none. So, where we once had to say: if ($x==$a or $x==$b or $x==$c or $x==$d) { ... } we can now say if $x == any($a, $b, $c, $d) { ... } Similarly, where we once had to say if (grep { $x == $^z } @list) { ... } if (grep { $x == $^z } @list) == 0 { ... } we can now say if $x == any(@list) { ... } if $x == none(@list) { ... } And for fun, try writing the equivalent of if $x == one($a, $b, $c, $d) { ... } without a junction. (Okay, one can cheat with Cgrep.) A programmer can easily use these without having to worry about the notions of autothreading or superpositions or the like, and their translations to English are fairly obvious. I suspect that constructs like the above will be the majority of use for junctions. Things start to get weirder when we start storing junctions into variables, and/or passing those variables/junctions into subroutines. But I think this is not *too* far removed from the idea of placing a subroutine or a rule into a scalar -- i.e., using a scalar to represent something more than a single-valued primitive type. Thus, just as one can write $x = new CGI; $y = rule { \d+ }; $z = sub { ... }; and then use $x, $y, and $z later on for an object, rule, and sub (which may have a variety of side-effects associated with them), it makes sense that one can write $w = any(@list); and then use $w to refer to the junction later. And a programmer who does this is taking on some responsibility for understanding that $w isn't one of the trivial scalars anymore (same as for $x, $y, and $z). However, one difference is that when one typically uses an object, rule, or subroutine in a scalar there is some syntax that makes their nature apparent. Some feel that Junctions might be just a bit too magical in this respect (e.g., Luke has made some syntactic suggestions to try make the existence/threading of a junction more apparent). Pm
Re: Junction Values
On Wed, 16 Feb 2005 09:18:42 -0600, [EMAIL PROTECTED] (Patrick R. Michaud) wrote: On Wed, Feb 16, 2005 at 01:06:22PM +, Nigel Sandever wrote: Any chance that you could provide one or two simple but realistic examples of using Junctions and their operators? I'll give it a shot, but keep in mind that I'm somewhat new to this also. :-) First, junctions are an easy way to represent the relationships any, all, one, or none. So, where we once had to say: if ($x==$a or $x==$b or $x==$c or $x==$d) { ... } we can now say if $x == any($a, $b, $c, $d) { ... } Similarly, where we once had to say if (grep { $x == $^z } @list) { ... } if (grep { $x == $^z } @list) == 0 { ... } we can now say if $x == any(@list) { ... } if $x == none(@list) { ... } I'd write the P5 none() case as if ( grep { $x != $_ } @list ) { ... } or unless( grep{ $x == $_ } @list ) { ... } which tends to reduce the sugaryness of the new syntax slightly. And for fun, try writing the equivalent of if $x == one($a, $b, $c, $d) { ... } I'm also not entirely sure at this point whether that means if( grep( { $x == $_ } $a, $b, $c, $d ) == 1 ) { ... } or something different? without a junction. (Okay, one can cheat with Cgrep.) But most of those examples pretty clear and understandable. I'm not sure that I see their convenience alone as a convincing arguement for the existance of Junctions. I keep thinking that there is something altogether more fundementally useful and ...well... cleverer underlying their inclusion, but at this stage I am not seeing it. In this usage, they appear to be replicating functionality that is already being provided via the inclusion of the hyper-operators. ('scuse me if I skip the unicode and/or get the syntax wrong!) if( $x == @list ){ ... } ## any? if( $x != @list ){ ... } ## none? if( ( $x == @list ) == 1 ) { ... } ## one? if( ( $x == @list ) == @list ) { ... } ## all? It would very much depend upon what a hyper operator returns in a boolean context, but they /could/ be made to work as I've indicated I think. If the hyper operator returned one boolean result for each comparison it made, and if a list of boolean values in a boolean context collapsed to a count of the trues/1s it contained, I think those would work. You would also get the bonus of if( ( $x == @list ) == 2 ) { ... } ## two() ( three(), ten() etc. ) if( ( $x = @list ) == @list/2 ) { ... } ## fify percent below... But I think the promise of Junctions appears to come from using them in conjunction with each other. $x = any( @list1 ); $y = all( @list2 ); $z = none( @list3 ); if( $x = $y ) { ... } if( any( $x != $y ) or all( $y == $z ) ) { ... } except that I haven't got a clue what those mean? I've sat and starred at the worked examples given elsewhere in this and the other thread, and whilst I can follow how the results are derived when someone lays them out for me--though I fell into the trap of accepting the one where Damian made a mistake, which probably means I wasn't paying close enough attention--when I get to the the last line and see that the answer it true (or false), I look back at the original unexpanded statement and think: Yes! But what does it mean? When and where is that going to be useful? A programmer can easily use these without having to worry about the notions of autothreading or superpositions or the like, and their translations to English are fairly obvious. I suspect that constructs like the above will be the majority of use for junctions. Things start to get weirder when we start storing junctions into variables, and/or passing those variables/junctions into subroutines. But I think this is not *too* far removed from the idea of placing a subroutine or a rule into a scalar -- i.e., using a scalar to represent something more than a single-valued primitive type. Thus, just as one can write $x = new CGI; $y = rule { \d+ }; $z = sub { ... }; and then use $x, $y, and $z later on for an object, rule, and sub (which may have a variety of side-effects associated with them), it makes sense that one can write $w = any(@list); and then use $w to refer to the junction later. And a programmer who does this is taking on some responsibility for understanding that $w isn't one of the trivial scalars anymore (same as for $x, $y, and $z). However, one difference is that when one typically uses an object, rule, or subroutine in a scalar there is some syntax that makes their nature apparent. Some feel that Junctions might be just a bit too magical in this respect (e.g., Luke has made some syntactic suggestions to try make the existence/threading of a junction more apparent). I see the dangers of scalars that aren't
Re: Junction Values
On Wed, Feb 16, 2005 at 06:04:37PM +, Nigel Sandever wrote: On Wed, 16 Feb 2005 09:18:42 -0600, [EMAIL PROTECTED] (Patrick R. Michaud) wrote: And for fun, try writing the equivalent of if $x == one($a, $b, $c, $d) { ... } without a junction. (Okay, one can cheat with Cgrep.) I'm also not entirely sure at this point whether that means if( grep( { $x == $_ } $a, $b, $c, $d ) == 1 ) { ... } or something different? Yes, that's essentially correct. In this usage, they appear to be replicating functionality that is already being provided via the inclusion of the hyper-operators. ('scuse me if I skip the unicode and/or get the syntax wrong!) if( $x == @list ){ ... } ## any? if( $x != @list ){ ... } ## none? if( ( $x == @list ) == 1 ) { ... } ## one? if( ( $x == @list ) == @list ) { ... } ## all? Ouch, this makes my head hurt. :-) A syntax note -- C== is an infix operator, thus the correct syntax would have to be if( $x == @list ){ ... } ## any? if( $x != @list ){ ... } ## none? and the result of $x == @list would end up being a list of true/false values. If the hyper operator returned one boolean result for each comparison it made, and if a list of boolean values in a boolean context collapsed to a count of the trues/1s it contained, I think those would work. Part of the problem is that we don't have a list of boolean values that is somehow distinguishable from list of values. (And a list evaluated in boolean context is true if the list is non-empty.) If we create a list of boolean values type, it effectively becomes a junction. :-) But I think the promise of Junctions appears to come from using them in conjunction with each other. $x = any( @list1 ); $y = all( @list2 ); $z = none( @list3 ); if( $x = $y ) { ... } if( any( $x != $y ) or all( $y == $z ) ) { ... } except that I haven't got a clue what those mean? Well, if ($x = $y) { ... } is better written out as: if ( any(@list1) = all(@list2) ) { ... } which reads if any of the elements of list1 are less than or equal to all of the elements of list2. One could arguably claim/show that this is mathematically equivalent to if ( min(@list1) = min(@list2) ) { ... } except that junctions could potentially work with relationships that aren't transitive as C = is. I'll have to think about your second Cif statement a bit -- I agree that it's not immediately obvious what it means, but I'm not sure that we could come up with an alternate way of writing it which is also immediately obvious. Phrased another way -- regardless of the construct being discussed we can probably write an expression using that construct that isn't easily deciphered at first. I've sat and starred at the worked examples given elsewhere in this and the other thread, and [...] I look back at the original unexpanded statement and think: Yes! But what does it mean? When and where is that going to be useful? Part of the reason for this may simply be that many of the examples discussed in these threads are in fact edge cases that have been designed to illustrate a point rather than to be useful. Indeed, they're discussed simply because they aren't obvious. And whilst the simple examples show some syntatic sugaryness, I think that it will not be until I begin to see how to apply the more complex cases to real-world problems that I could reach a conclusion about whether the value of their inclusion outweights the onus of awareness the impose upon the programmer. I think one can make this observation for many features slated for Perl 6 -- i.e., the simple cases look simple but the full application of complex cases isn't always immediately obvious. I know I get this feeling from looking at things like roles, mixins, slurpy arrays, slurpy hashes, Ctemp declarations, hypotheticals, hyperoperators, etc. However, just as I don't have to be aware of every CPAN module that exists in order to write Perl programs, I don't think having these features built into the language will require a great deal of awareness on the programmer until the programmer chooses to use them. Others could reasonably disagree with this statement. And to anticipate the followup question of Well, why not make features such as junctions into optional modules?, I think a partial answer is that features like these really need deep language support to work effectively in their complex applications. Otherwise we'd just stick with Perl 5. :-) Pm
Re: Junction Values
On Wed, Feb 16, 2005 at 01:55:31PM -0600, Patrick R. Michaud wrote: : And to : anticipate the followup question of Well, why not make features such : as junctions into optional modules?, I think a partial answer is that : features like these really need deep language support to work : effectively in their complex applications. Otherwise we'd just : stick with Perl 5. :-) That, and we'd like a novice to be able to write given $x { when 1 | 2 | 3 {...} when 4 | 5 | 6 {...} } without having to know there are junctions there underneath. Forcing them to cargo-cult a use junctions declaration merely to get switch alternatives would not solve any problems I can think of. Nor would inventing a separate switch syntax for alternatives be appropriate when we can make junctions work for that in a semi-orthogonal fashion. As I said elsewhere, the training wheels probably belong on the variable's type checking, not on the underlying type space. Variable types are *views* into the actual underlying object types bound to the variable, and so variable types can place arbitrary restrictions on the use of those underlying general types. Larry
Re: Junction Values
Patrick R. Michaud wrote: On Wed, Feb 16, 2005 at 06:04:37PM +, Nigel Sandever wrote: If the hyper operator returned one boolean result for each comparison it made, and if a list of boolean values in a boolean context collapsed to a count of the trues/1s it contained, I think those would work. Part of the problem is that we don't have a list of boolean values that is somehow distinguishable from list of values. (And a list evaluated in boolean context is true if the list is non-empty.) If we create a list of boolean values type, it effectively becomes a junction. :-) What if we instead redefine any/all/one/none to be functions (and/or list methods) that take a list, evaluates each element in boolean context, and returns boolean? Therefore, Nigels's examples become: if any( $x »==« @list) { ... } if none($x »==« @list) { ... } if all( $x »==« @list) { ... } if one( $x »==« @list) { ... } Then case that I see happening most often will then be: if any($x »==« (1,2,10,100,200,1000,2000)) { ... } I'll also throw in the argue that anything much more complex than this definitely falls into the category of edge case, and is of dubious utility, and IMHO, a lot of danger. It occurred to me that junctions felt a lot like typeglobs. Very powerful thing, that little *. But also something that experienced programmers tell inexperienced ones something like Don't mess with them unless you really understand them. Then throw in that most programmers use a heavy dose of lexicals, which aren't typeglobable. In the end, you are left with only one useful idiom left: *NewFunc = sub {...}; Which will usually appears inside an AUTOLOAD. (yes, I'm sure that Damian and some others on this list can create exceptionally cool use of typeglobs, in ways that would warp our minds, but I'm talking overall utility). How does this relate to junctions? All I think anyone ever *asked* for out of a junction was an easier way to write: if ($x==$a or $x==$b or $x==$c or $x==$d) { ... } The rest of the invention feels like Magic, and is something the experienced will tell the inexperienced not to mess with until they really understand the consequences of using them. And even then, few of the experienced will make more use of it than the simple case. -- Rod Adams
Re: Junction Values
Larry Wall wrote: That, and we'd like a novice to be able to write given $x { when 1 | 2 | 3 {...} when 4 | 5 | 6 {...} } Or just change Cwhen to accept a list of things to compare against, followed by a coderef. -- Rod Adams
Re: Junction Values
On Wed, 16 Feb 2005 14:29:14 -0600, Rod Adams [EMAIL PROTECTED] wrote: Larry Wall wrote: That, and we'd like a novice to be able to write given $x { when 1 | 2 | 3 {...} when 4 | 5 | 6 {...} } Or just change Cwhen to accept a list of things to compare against, followed by a coderef. Well, I don't think anyone can argue that having ~~ behave properly with junctions is wrong. After all, we can make it do whatever we want. $foo ~~ 1 | 2 | 3 Perhaps we can make ~~ an even more magical comparison operator. $x ~~ $y is a huffmanized version of $x ~==~ $y @x ~~ $y is a smart-match based on instead of == Or perhaps you can choose on which side the magic works: @x ~ $y OK, enough craziness for today. $foo ~~ $bar # uses Clt for strings, C+for numbers, voodoo for junctions, etc... Ashley
Junction Values
Okay, so we've established that: $x = any(3,4,5); @l = $x.values.sort; Leaves us with @l == (3,4,5), and that makes a fair amount of sense. What do the following evaluate to: @l1 = all(3,4,5).values.sort; @l2 = one(3,4,5).values.sort; @l3 = none(3,4,5).values.sort; @l4 = any(all(1,2),all(3,4)).values.sort; If C.values doesn't it cut it for these cases, what other forms of introspection are we going to allow on junctions, to determine what they are? On a slightly different topic, do the following equivalences work: any($a, $a) == $a any($a,$a,$b) == any($a,$b) any(any($a,$b),any($c,$d)) == any($a,$b,$c,$d) all($a, $a) == $a all($a,$a,$b) == all($a,$b) all(all($a,$b),any($c,$d)) == all($a,$b,$c,$d) none($a, $a) == undef none($a,$a,$b) == none($a,$b) none(none($a,$b),none($c,$d)) == none($a,$b,$c,$d) one($a, $a) == false one($a,$a,$b) == ($a == $b ?? undef :: $b) -- Rod Adams
Re: Junction Values
Rod Adams wrote: Okay, so we've established that: $x = any(3,4,5); @l = $x.values.sort; Leaves us with @l == (3,4,5), and that makes a fair amount of sense. What do the following evaluate to: @l1 = all(3,4,5).values.sort; Same. @l2 = one(3,4,5).values.sort; Same. @l3 = none(3,4,5).values.sort; Same. @l4 = any(all(1,2),all(3,4)).values.sort; = (all(1,2),all(3,4)).sort = (all(1,2),all(3,4)) If C.values doesn't it cut it for these cases, what other forms of introspection are we going to allow on junctions, to determine what they are? .values tells you what raw values are inside the junction. The other kind of introspection that's desirable is: what raw values can *match* this junction. There would probably be a .states method for that. To see the difference between the two, consider: my $ideal_partner = all( any(«tall dark rich»), any(«rich old frail»), any(«Australian rich»), ); $ideal_partner.values would return the three distinct values in the junction: ( any(«tall dark rich»), any(«rich old frail»), any(«Australian rich»), ); But $ideal_partner.states would return only those non-junctive values that (smart-)match the junction. Namely, rich. On a slightly different topic, do the following equivalences work: (I will assume in all my answers that $a, $b, $c, $d have different values, except where it doesn't matter either way). any($a, $a) == $a True. any($a,$a,$b) == any($a,$b) True. any(any($a,$b),any($c,$d)) == any($a,$b,$c,$d) True. all($a, $a) == $a True. all($a,$a,$b) == all($a,$b) False. The autothreading makes that: all( $a==$a, $a==$b, $b==$b, $b==$a) and they're not (in general) all true. all(all($a,$b),any($c,$d)) == all($a,$b,$c,$d) False. Because all($a,$b) != all($a,$b,$c,$d) none($a, $a) == undef True. none($a,$a,$b) == none($a,$b) True. none(none($a,$b),none($c,$d)) == none($a,$b,$c,$d) True. one($a, $a) == false True. one($a,$a,$b) == ($a == $b ?? undef :: $b) True. Damian
Re: Junction Values
On Wed, Feb 16, 2005 at 12:17:35PM +1100, Damian Conway wrote: none($a, $a) == undef True. Isn't this one false in the case when $a is undef? -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: Junction Values
Jonathan Scott Duff wrote: none($a, $a) == undef True. Isn't this one false in the case when $a is undef? Yes. Apologies for not being more precise. Damian
Re: Junction Values
On Wed, Feb 16, 2005 at 12:17:35PM +1100, Damian Conway wrote: Rod Adams wrote: On a slightly different topic, do the following equivalences work: [...] none($a, $a) == undef True. Scott already caught (and Damian acknowledged) this one, it's false if $a == undef. none($a,$a,$b) == none($a,$b) True. Okay, I follow this one -- here's the derivation. - none($a == none($a, $b), $b == none($a, $b)) - none(none($a==$a, $a==$b), none($b==$a, $b==$b)) - none(none(1, 0), none(0, 1)) - none(0, 0) - true none(none($a,$b),none($c,$d)) == none($a,$b,$c,$d) True. H... - none(none($a,$b) == none($a,$b,$c,$d), none($c,$d) == none($a,$b,$c,$d)) - none(none($a == none($a,$b,$c,$d), $b == none($a,$b,$c,$d)), none($c == none($a,$b,$c,$d), $d == none($a,$b,$c,$d))) - none(none(none($a==$a, $a==$b, $a==$c, $a==$d), none($b==$a, $b==$b, $b==$c, $b==$d)), none(none($c==$a, $c==$b, $c==$c, $c==$d), none($d==$a, $d==$b, $d==$c, $d==$d))) - none(none(none(1, 0, 0, 0), none(0, 1, 0, 0)), none(none(0, 0, 1, 0), none(0, 0, 0, 1))) - none(none(0, 0), none(0, 0)) - none(1,1) - false Ummm, what am I missing? To state it another way... we can show that none($a,$b) == none($a, $b, $c, $d) is true, so none( none($a,$b), none($c,$d) ) == none($a, $b, $c, $d) is equivalent to none( none($a,$b) == none($a, $b, $c, $d), none($c,$d) == none($a, $b, $c, $d)) which is none(1, 1), or false. Did I autothread wrongly here? And for completeness... one($a,$a,$b) == ($a == $b ?? undef :: $b) True. ...except when $a == $b == undef. Pm
Re: Junction Values
Damian Conway wrote: .values tells you what raw values are inside the junction. The other kind of introspection that's desirable is: what raw values can *match* this junction. There would probably be a .states method for that. To see the difference between the two, consider: my $ideal_partner = all( any(tall dark rich), any(rich old frail), any(Australian rich), ); $ideal_partner.values would return the three distinct values in the junction: ( any(tall dark rich), any(rich old frail), any(Australian rich), ); But $ideal_partner.states would return only those non-junctive values that (smart-)match the junction. Namely, rich. One would need a method of determining whether the C.values are in an any/all/none/one relationship. Trivial, but necessary. That and C.values are likely enough introspection. Leave the C.state for CPAN to solve. On a slightly different topic, do the following equivalences work: (I will assume in all my answers that $a, $b, $c, $d have different values, except where it doesn't matter either way). all($a,$a,$b) == all($a,$b) False. The autothreading makes that: all( $a==$a, $a==$b, $b==$b, $b==$a) and they're not (in general) all true. I knew I was typing this all wrong. Whipping out math symbols, replace the == with , or identical to. In other words, I was not asking how C if all($a,$a,$b) == all($a,$b) {...} evaluated, but instead if if all($a,$a,$b) {...} if all($a,$b) {...} would both evaluate the same. And I was making no assumptions about the values of $a .. $d. all(all($a,$b),any($c,$d)) == all($a,$b,$c,$d) False. Because all($a,$b) != all($a,$b,$c,$d) Should have been all(all($a,$b), all($c,$d)) all($a,$b,$c,$d) Sorry for any confusion. It's just a real pain to type chars that are not bound on your keyboard. As for the undef's, I didn't know what else to call the empty junctive. -- Rod Adams
Re: Junction Values
Patrick R. Michaud wrote: none(none($a,$b),none($c,$d)) == none($a,$b,$c,$d) True. H... - none(none($a,$b) == none($a,$b,$c,$d), none($c,$d) == none($a,$b,$c,$d)) - none(none($a == none($a,$b,$c,$d), $b == none($a,$b,$c,$d)), none($c == none($a,$b,$c,$d), $d == none($a,$b,$c,$d))) - none(none(none($a==$a, $a==$b, $a==$c, $a==$d), none($b==$a, $b==$b, $b==$c, $b==$d)), none(none($c==$a, $c==$b, $c==$c, $c==$d), none($d==$a, $d==$b, $d==$c, $d==$d))) - none(none(none(1, 0, 0, 0), none(0, 1, 0, 0)), none(none(0, 0, 1, 0), none(0, 0, 0, 1))) - none(none(0, 0), none(0, 0)) - none(1,1) - false Ummm, what am I missing? To state it another way... we can show that none($a,$b) == none($a, $b, $c, $d) is true, so none( none($a,$b), none($c,$d) ) == none($a, $b, $c, $d) is equivalent to none( none($a,$b) == none($a, $b, $c, $d), none($c,$d) == none($a, $b, $c, $d)) which is none(1, 1), or false. Did I autothread wrongly here? No, upon closer looking, you're right that it should both evaluate false, and that they are not equivalent in what I meant to be asking. none(none($a,$b),none($c,$d)) ? all(any($a,$b),any($c,$d)) Should work, though. Not that it helps simplify matters at all. In essence, what I'm doing is attempting to create a set of rules whereby one can simplify a junction, by removing the nestedness of it, or removing terms outright. In the process, I'm making sure that I understand what they mean. -- Rod Adams
Re: Junction Values
Patrick R. Michaud wrote: none(none($a,$b),none($c,$d)) == none($a,$b,$c,$d) True. H... - none(none($a,$b) == none($a,$b,$c,$d), none($c,$d) == none($a,$b,$c,$d)) RHS distributes first. So the expansion is this instead... - none(none(none($a,$b),none($c,$d)) == $a, none(none($a,$b),none($c,$d)) == $b, none(none($a,$b),none($c,$d)) == $c, none(none($a,$b),none($c,$d)) == $d, ) - none(none(none($a,$b)=$a, none($c,$d)=$a), none(none($a,$b)=$b, none($c,$d)=$b), none(none($a,$b)=$c, none($c,$d)=$c), none(none($a,$b)=$d, none($c,$d)=$d), ) - none(none(0, 1), none(0, 1), none(1, 0), none(1, 0), ) - none(0, 0, 0, 0, ) - true Ummm, what am I missing? To state it another way... we can show that none($a,$b) == none($a, $b, $c, $d) is true, RHS distributes first again: none($a,$b) == none($a, $b, $c, $d) - none( none($a,$b)==$a, none($a,$b)==$b, none($a,$b)==$c, none($a,$b)==$d, ) - none( 0, 0, 1, 1, ) - false Damian
Re: Junction Values
On Wed, Feb 16, 2005 at 02:53:15PM +1100, Damian Conway wrote: Patrick R. Michaud wrote: none(none($a,$b),none($c,$d)) == none($a,$b,$c,$d) True. H... - none(none($a,$b) == none($a,$b,$c,$d), none($c,$d) == none($a,$b,$c,$d)) RHS distributes first. So the expansion is this instead... Ummm, okay, but that's not what I interpreted from S09, where it says that the left-most conjunction or injunction is autothreaded first. In this I've also assumed that $a == $b is equivalent to infix:==($a, $b) so I'm missing the piece that says to distribute the RHS first. Pm
Re: Junction Values
Patrick R. Michaud wrote: RHS distributes first. So the expansion is this instead... Ummm, okay, but that's not what I interpreted from S09, where it says that the left-most conjunction or injunction is autothreaded first. In this I've also assumed that $a == $b is equivalent to infix:==($a, $b) so I'm missing the piece that says to distribute the RHS first. Probably because that piece is still only in my head. Or because I got that bit of S09 wrong. Or because Larry or Luke overrode me on it and I haven't updated my Perl6::Junctions module accordingly. ;-) So forget what I said, and go with what Patrick said. Since it's easy to argue the outcome of these corner cases either way (depending on how you backtranslate them to English), it will be best to make the rules consistent (i.e. left-most first for both functions and operators). Apologies all...and thanks Patrick. Damian