Slurpy nullary vs nonslurpy nullary

2005-02-18 Thread Autrijus Tang
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

2005-02-18 Thread Brent 'Dax' Royal-Gordon
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: Slurpy nullary vs nonslurpy nullary

2005-02-18 Thread Larry Wall
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

2005-02-18 Thread Autrijus Tang
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

2005-02-18 Thread David Wheeler
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

2005-02-18 Thread Rod Adams
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

2005-02-18 Thread Rod Adams
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

2005-02-18 Thread Luke Palmer
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: Fun with junctions (was Sets vs Junctions)

2005-02-18 Thread Damian Conway
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:asAny,Source[Perl]
  2-ary *coerce:asAny,Source[Python]
  2-ary *coerce:asAny,Source[Lisp]
  2-ary *coerce:asAny,Source[C::Sharp]
  # 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:asAny,Source[*]
Damian


Re: Junction Values

2005-02-18 Thread Jonathan Scott Duff
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

2005-02-18 Thread Rod Adams
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

2005-02-18 Thread Ashley Winters
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

2005-02-18 Thread Eirik Berg Hanssen
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

2005-02-18 Thread Ashley Winters
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

2005-02-18 Thread Ashley Winters
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

2005-02-18 Thread Craig DeForest
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

2005-02-18 Thread Rod Adams
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

2005-02-18 Thread Brent 'Dax' Royal-Gordon
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

2005-02-18 Thread Brent 'Dax' Royal-Gordon
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

2005-02-18 Thread Rod Adams
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

2005-02-18 Thread Rod Adams
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

2005-02-18 Thread Brent 'Dax' Royal-Gordon
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

2005-02-18 Thread Damian Conway
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