Slurpy nullary vs nonslurpy nullary
After getting Life and Mandel to run on Pugs yesterday (see http://svn.perl.org/perl6/pugs/trunk/examples/ ), today I've made this version of Quicksort to run: use v6; multi sub quicksort ( ) { () } multi sub quicksort ( *$x, [EMAIL PROTECTED] ) { my @pre = @xs.grep{ $_ < $x }; my @post = @xs.grep{ $_ >= $x }; (@pre.quicksort, $x, @post.quicksort); } (1, 5, 2, 4, 3).quicksort.say; Note the use of @xs.grep{} above. Pugs currently has two multisub named "grep": * List as invocant, takes a Code arg * Takes two args: Code and List It sort of makes sense to me. Please correct me if it's wrong. :) But anyway. The real problem is the multisub dispatcher initially complained about the () signature, saying that it is "non-slurpy" and may not take a list, even though the list eventually flattens into an empty list; so I modified the definition to make () explicitly slurpy. However, that feels wrong, as I'd like to distinguish from a slurpy nullnary (something that can take a list, as long as it's empty) and a non-slurpy nullary (something that takes no arguments whatsoever). I have been wondering whether something like quicksort( *[] ) Can mean a slurpy nullnary, but I failed to find relevant text in Synopses, so here I am. :-) (PS. Yes, I understand that I can use array unpacking and have quicksort always take a single array argument, but I'd still like to inquire about slurpy nullary...) Thanks, /Autrijus/ pgpTgAVL1xdj5.pgp Description: PGP signature
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 C) 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: Slurpy nullary vs nonslurpy nullary
On Fri, Feb 18, 2005 at 04:25:49PM +0800, Autrijus Tang wrote: : After getting Life and Mandel to run on Pugs yesterday (see : http://svn.perl.org/perl6/pugs/trunk/examples/ ), today I've : made this version of Quicksort to run: : : use v6; : : multi sub quicksort ( ) { () } : : multi sub quicksort ( *$x, [EMAIL PROTECTED] ) { : my @pre = @xs.grep{ $_ < $x }; : my @post = @xs.grep{ $_ >= $x }; Just as a BTW, that syntax is illegal currently, since those curlies would be interpreted as hash subscripts. Method syntax requires parens if there are any (non-adverbial) arguments. So you either need parens for the argument: my @pre = @xs.grep({ $_ < $x }); my @post = @xs.grep({ $_ >= $x }); or pass an adverbial block: my @pre = @xs.grep:{ $_ < $x }; my @post = @xs.grep:{ $_ >= $x }; : (@pre.quicksort, $x, @post.quicksort); : } : : (1, 5, 2, 4, 3).quicksort.say; : : Note the use of @xs.grep{} above. Pugs currently has two multisub : named "grep": : : * List as invocant, takes a Code arg : * Takes two args: Code and List : : It sort of makes sense to me. Please correct me if it's wrong. :) As long as the first is always called as single dispatch, and the second as multiple dispatch, there should be no confusion. : But anyway. The real problem is the multisub dispatcher initially : complained about the () signature, saying that it is "non-slurpy" : and may not take a list, even though the list eventually flattens : into an empty list; so I modified the definition to make () explicitly : slurpy. : : However, that feels wrong, as I'd like to distinguish from a slurpy : nullnary (something that can take a list, as long as it's empty) and a : non-slurpy nullary (something that takes no arguments whatsoever). Right, it's the anchoring problem--but it's really only a problem for compile time typing, and documenting your intent. At run time we know perfectly well that there are 0 arguments. : I have been wondering whether something like : : quicksort( *[] ) : : Can mean a slurpy nullnary, but I failed to find relevant text in : Synopses, so here I am. :-) No, that'd mean a single array reference that has to be empty. : (PS. Yes, I understand that I can use array unpacking and have : quicksort always take a single array argument, but I'd still like to : inquire about slurpy nullary...) If we decide we need to declare non-anchoring intent (and I'm not convinced we do), then maybe the final (or only) arg of a multi can be declared as bare * to indicate it's not anchored to the end of the argument list. But the () declaration indicates already that the function will never match a non-null list, and people might take (*) to mean that it matches a non-null list and throws away the result. So I think your initial solution is actually the right one from the viewpoint of the Perl programmer. If we need to tweak something, it's perhaps to document the fact that *$x is required to match an argument, while [EMAIL PROTECTED] isn't required to match any arguments at all. So if you had multi sub quicksort ( ) { () } multi sub quicksort ( [EMAIL PROTECTED] ) { then when dispatching 0 arguments you actually have an ambiguity that either has to be illegal or solved by ordered matching. I think ordered matching is more conducive to a Prolog-like mentality, and more fail-soft, and slightly righter for Perl. (But that doesn't say much about ordering across different modules, does it?) Larry
Re: Slurpy nullary vs nonslurpy nullary
On Fri, Feb 18, 2005 at 08:26:26AM -0800, Larry Wall wrote: > Just as a BTW, that syntax is illegal currently, since those > curlies would be interpreted as hash subscripts. Noted. Which reminds me I need to implement hashes... :) > : It sort of makes sense to me. Please correct me if it's wrong. :) > > As long as the first is always called as single dispatch, and the > second as multiple dispatch, there should be no confusion. Cool. I'll see if I can adverbify other builtins, then. > Right, it's the anchoring problem--but it's really only a problem for > compile time typing, and documenting your intent. At run time we know > perfectly well that there are 0 arguments. Uhm, yes and no. Currently, at runtime, I have an "arityMatch" function that compares all potential multisub matches with the invocant and arguments; however, different candidate may impose different contexts on the arguments (slurping == List, nonslurping == usually Scalar). A difficulty arises because the expressions used as arguments is not evaluated when arityMatch is done, and for good reason -- they may do wildly different things depending on its context. When Pugs was only implementing FP6, I could affort to force evaluation for each multisub candidate, and see if they yield values that can match the signature. However, because now the expressions may contain "say" statements, I can no longer do that. As a concrete (not neccessarily correct) example: multi sub foo ($x, Int $y) returns Num { ... } multi sub foo ($x, *$a, *$b) returns Str { ... } sub baz { given want { if (rand > .5) { ... } else { ... } } } foo( bar(), baz() ); I fail to find a way to statically find out how many values (and what type of values) baz() will return under "Int" and "List" contexts, short of actually evaluating it twice. Hence, the return type of foo() can't be analyzed in advance because I don't know which foo() will be invoked. Currently it is an outstanding problem in Pugs implementation, and that was the reason why I had to use destructive "=" instead of the binding ":=" for @pre and @post. I'd be delighted to learn of a solution to that. > So I think your initial solution is actually the right one from the > viewpoint of the Perl programmer. If we need to tweak something, > it's perhaps to document the fact that *$x is required to match an argument, > while [EMAIL PROTECTED] isn't required to match any arguments at all. So if > you > had > > multi sub quicksort ( ) { () } > multi sub quicksort ( [EMAIL PROTECTED] ) { > > then when dispatching 0 arguments you actually have an ambiguity that > either has to be illegal or solved by ordered matching. In pugs, currently it's ordered by local vs global, then by subtyping distance of invocants, then finally by then finally by the order of creation of CODE objects. That's just a working heuristics, though. Thanks, /Autrijus/ pgppdqXsP7VuK.pgp Description: PGP signature
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: Fun with junctions (was Sets vs Junctions)
HaloO Damian, you wrote: Actually, I'd have thought that the type coercion mechanism might be a more appropriate way to go here. After all, the serialization of a data structure is merely a coercion to a subtype of Str. Specifically, I imagine a parameterized Source subtype: class Source[Language ::To] is Str { multi sub *coerce:as (Any $data, To ::Lang) { return Lang.serialize($data) } } What is the return type of &*coerce:as? 1: the implicit ::?CLASS, but how is that constructed from Language subclasses? 2: infered from &Language::serialize which delivers Str or Perl but Str or some such? 3: Str, which doesn't need meta information and is the (final) intension anyway I assume 1, but is that right? 2 and 3 contradict the general idea of &coerce:as which returns the type of the rhs argument. What is entered into the MMD tables for &*coerce:as a:2-ary &*coerce:as b: parametric 2-ary &*coerce:as c: parametric 2-ary &*coerce:as d:3-ary &*coerce:as and would cases b and c be written as &*coerce:as. I assume case b is right, or actually instanciations of that for concrete values of ::To. Then you could just write: my $good = $x as Source[Perl]; my $bad = $x as Source[C::Sharp]; my $ugly = $x as Source[Lisp]; The type of e.g. $good is then Source[Perl], right? And adding a new serialization would simply mean adding a new Language subclass with an appropriate .serialize() method: class YAML is Language { method serialize($data) { ... } } Again, the return type of &YAML::serialize<$> is taken from the lexical ::?CLASS which is of course YAML? Regards, -- TSa (Thomas Sandlaß)
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(<>); # 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 = <>; 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(<>); # 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 = <>; > > gives them a name you can use late
Re: Fun with junctions (was Sets vs Junctions)
Thomas Sandlaß wrote: class Source[Language ::To] is Str { multi sub *coerce:as (Any $data, To ::Lang) { return Lang.serialize($data) } } What is the return type of &*coerce:as? Sorry, I was too lazy (well, I'd claim I was thinking at a much higher level, but it amounts to the same ;-) and I made a mistake in the signature of the coercion. Here's a fully typed, and correctly parameterized, version: class Source[Language ::To] is Str { multi sub *coerce:as (Any $data, Source[To] ::Lang) returns Source[To] { return Lang.serialize($data) } } class YAML is Language { method serialize($data) returns Source[YAML] { ... return Source[YAML].new($source_code); } } Or we could cheat in the coercion, and just do it all with strings: class Source[Language ::To] { multi sub *coerce:as (Any $data, Source[To] ::Lang) returns Str { return Lang.serialize($data) } } class YAML is Language { method serialize($data) returns Str { ... return $source_code; } } As for the MMD table, that's an implementation issue, but presumably it'd have to contain separate entries for each instantiation of the generic Source class: 2-ary &*coerce:as 2-ary &*coerce:as 2-ary &*coerce:as 2-ary &*coerce:as # etc. or (more likely, given the dynamic nature of Perl) a single entry that's a "trampoline" that instantiates particular parameterizations of the generic class as they're needed: 2-ary &*coerce:as Damian
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(<>); # 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 = <>; > > 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 i
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
Jonathan Scott Duff wrote: 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. And nouns either refer to single item, or a group of items as a whole. Not one item that behaves like a chameleon. When you say "The French", you are referring to the entire group of people that associate themselves with the country of France. Not all the people of France juxtaposed into one entity. If you want that, you say "A Frenchmen" or "One of the French", but even then you are referring to a single person, who happens to part of the group "The French". This last is a pure Set membership question. The same "The French" can be used as : "The French are invading!!". With a junction, you can build something that says "any group of people from France", "one person from France", "everyone from France", and even "not from France", but none of them embody the concept that we think of as "The French". If you were to have an embodiment of "The French" (as I proposed way back in "Sets vs Junctions"), it is fairly easy to then create all of the above junctions. Via the introspection that Junctions are being defined with, it's possible to get that back out, but not smoothly. So, linguistically, a noun is either a specific entity, or a group of things, taken as a whole. As Damian so emphatically stated earlier in this long and twisting thread, a Junction is not a group of things, lopped together. It is one single thing, that has several different values at once. In addition, it also has a boolean function (any/all/one/none), declaring how all these values relate when evaluated. The closest linguistic parallel to this I've see is the double entendre, which doesn't even come close. Sets and Junctions are two different things. They are related, but quite different, and should not be confused. 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(<>); # 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 = <>; gives them a name you can use later, as well. Except that you've introduced a definite ordering where one isn't needed. Yes, well, people don't get to use that argument on me after repeatedly saying that sets could be easily stored in arrays and/or hashes. I don't remember if you, personally said it, but it felt like a consensus vote from over here. One I don't really disagree with. Not to mention the definite ordering only matters if you process it in a way that it does. In attempts to better explain: $store->get("eggs" & "bacon" & "toast"); $store->get(<>); say two radically different things. The first statement says: "Go to the store and get Eggs. Go to the store and get Bacon. Go to the store and get Toast. Save the results of each trip separately, and then when someone asks how your trip (not trips) to the store went, you then see if all the results are the same." The second statement says: "Go to the store once. You have the following shopping list: Eggs, Bacon, Toast. Was your trip successful?" -- Rod Adams
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
Ashley Winters wrote: 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 In the context this question was posed, the proposal I was making, sqrt() would throw an exception. But that's likely not what this discussion is about. In the terms of junctions as defined, I expect that it would stop at the lowest value of $x greater than or equal to 4. Unless we start allowing junctive lists as well as junctive scalars... -- Rod Adams.
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 C has no return value. Maybe C 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 C has no return value. Maybe C 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 t
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? (C 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 C 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 C 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 C in scope where $x was assigned to (or the explicit use of some other module that also activates C). 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 C pragma in order for junctions to even be stored in variables. It's as bizarre as requiring C or C or C or C 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 C 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 C 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 C pragma so you can be emphatic about not wanting them. But bowdlerizing the concept of junctions isn't the answer. Damian