Re: junctions and conditionals

2009-04-03 Thread Miroslav Silovic

Dave Whipp wrote:
I'm thinking that the solution to this issue may be a little more 
radical than to-date: don't permit junctions to be stored in $ 
variables! Instead, require junctions to use a twiggle, to alert the 
reader that the surprises may be lurking.


my $x = 1|2; #error
my $|x = 1|2; # ok

Then you just need to invent some syntax to say that collapse is (or 
perhaps isn't) desired:


if [[ $|x  1 ]] { say $|x collapsed }

The most important thing that this does is that it leaves open the 
option to allow $ variables to hold junctions in some future version 
of Perl, without that future version being constrained by legacy 
semantics.




I'd second the twigil idea. Reason: I'd -really- like perl6 to be 
compilable into an efficient machine code without a JIT magic that we 
can currently only handwave about.


For that, I'd propose a rule of a thumb: ints are ints. Of course, 
floats and other unboxed types should also be just plain unboxed types, 
but I'd like the rule of a thumb to be short and to the point.


So,

int $x = 1|2;

should be an error.

Also,

int $x = 1 but not really a number;

should also be an error or at least a warning that mixin stripping and 
unboxing took place. If you want polymorphic here, use Ints. That'd also 
mean that


my @x of int;

can be implemented as a homogenous int vector, meaning -really- 
efficient and manipulable through the kind of code that modern CPUs are 
really good at (since as soon as you know you won't be lazy, you only 
need to be polymorphic about asking for the beginning of the in-memory 
buffer that can be manipulated directly. Even if that buffer doesn't 
contain all the elements, you can refill it as needed, and that could 
still be fast as long as the other side of the partially-lazy barrier 
also speaks int). Also, as far as I'm aware, there is no tracing VM that 
can create a homogenous arrays for you if you can't already do them.


From the above, the need for twigils in junctions should be apparent.

   Miro



Re: [Fwd: Re: junctions and conditionals]

2009-04-02 Thread Martin D Kealey
On Wed, 1 Apr 2009, Richard Hainsworth wrote:
 A closer examination of Martin's message indicates that he tends to think
 that hitting a junction ought to thread the entire program throughout the
 rest of the lifespan of said junction

Yes -- and well put, thank-you.

The trick is that since conditionals generally force full or partial
resolution on junctions, that lifetime won't tend to be very long.

Re: Tsa's comment about junctions being value types. In principle I agree,
except that the value semantics are only within the eigenthreads; outside
that, they are collections of indeterminate state. Indeterminate states
aren't sufficiently value-like to justify constant folding.

-Martin


Re: junctions and conditionals

2009-04-02 Thread Jon Lang
Martin Kealey wrote:
 On Tue, 31 Mar 2009, Jon Lang wrote:
 Another issue: what happens if conditional code mutates a junction
 that it filtered?  For example:

     $x = any (-5 .. 5);
     if $x  0 { $x++ };

 At this point, which of the following does $x equal?

     any(-4 .. 6) # the original junction gets mutated
     any(-5 .. 0, 2 .. 6) # the filtered part of the original junction
 gets mutated; the rest is untouched
     any(2 .. 6) # the filtered part of the original junction gets
 mutated; the rest is lost

 I choose #3.

 Reality can only take one path through a conditional; which one depends
 on the one/any/all/none binding of the junction.

 Once you've passed the conditional, you have:

        one - single matching value (no longer a junction)
        any - filtered list
        all - original junction
        none - empty (*1)

I'm a bit worried about 'none', for reasons that I'll get to in a moment.

 The threading is an implementation detail; the important thing is a
 junction is collection of values and a smart way of rewriting
 expressions that contain them, with special treatment for comparison
 operators (or indeed anything that forces Boolean content):

        $x CMP all($y,$z)       $x CMP $y  $x CMP $z
        $x CMP one($y,$z)       $x CMP $y ^^ $x CMP $z  (*2)
        $x CMP none($y,$z)      all($x !CMP $y, $x !CMP $z)
        $x CMP any($y,$z)       $x !CMP none($y, $x)

        $x OP all($y,$z)        all( $x OP $y, $x OP $z)
        $x OP any($y,$z)        any( $x OP $y, $x OP $z)
        $x OP one($y,$z)        one( $x OP $y, $x OP $z)
        $x OP none($y,$z)       none($x OP $y, $x OP $z)

 -Martin

 (*1: An argument could be made that none should leave the junction alone,
 the same as all.)

 (*2: I would like to suggest that the semantics of one be changed to mean
 pick one (randomly) rather than exactly one. In this respect it
 would be the same as any except it wouldn't have the overhead of
 filtering *every* match, just at least one.)

A few thoughts here.  First: should autothreading be lazy or eager?
As things stand, it seems to be eager: the moment you pass a junction
into a routine that doesn't ask for a junction in its signature, you
autothread that routine.  This has the nice benefit of being easy to
implement (autothread if the parameter doesn't specify 'junction';
don't autothread if it does); but as has been mentioned before, making
life easy on the implementor isn't a primary design goal for Perl.  I
submit that autothreading should be lazy.

As I see it, there are currently three things that can be done with a junction:

  1. Nothing.  Using the junction as threads paradigm, you bundle
the threads together and route them through a given part of the
program as a single rope.

  2. Autothreading.  You feed each thread through individually, and
rebundle the results on the other side.

  3. Sieving.  You feed only some of the threads through a decision
point into its guarded region, and rebundle at the end of the guarded
region.

Option 3 raises some additional questions.  What do you rebundle at
the end of the guarded region?  Just the threads that were passed
through it, or all of the original threads?  And what happens if the
program flow gets rerouted inside the guarded region such that it
never comes out the other side?

If I say:

$x = any(-5 .. 5)
if $x  0 { $x++ }
if $x ~~ (-1 .. 1) { $x *= 2 }

What is $x just before and just after '$x++'?  What is $x just before
and just after 'if $x  0 { $x++ }'?  Ditto with '$x *= 2' and 'if $x
 0 { $x *= 2 }'?

If I say:

$x = any(-5 .. 5)
if $x  0 { return }
if $x ~~ (-1 .. 1) { doit($x) }

What junction should doit be receiving?

Second:

sub sayit (Str $s) { say $s }
sayit 'S' | 5;

What should happen?  Should the junction be autothreaded, and then one
of the threads fail due to a type mismatch?  Or does parameter-passing
count as a kind of decision-point, such that you only get the sayit
'S' thread?

And what happens with the following?

sayit none('S');

-- 
Jonathan Dataweaver Lang


[Fwd: Re: junctions and conditionals]

2009-04-01 Thread Richard Hainsworth

This email was mistakenly not sent to the p6l list.

Jon writes:

On Wed, Apr 1, 2009 at 12:54 AM, Richard Hainsworth
rich...@rusrating.ru wrote:

Jon Lang wrote:


In Junction Algebra, Martin Kealey wrote:



On Mon, 30 Mar 2009, Mark J. Reed wrote:



  ( $a = any(-1,+1) = $b ) ==



( $a = any(-1,+1)  any(-1,+1) = $b )(*A)



Clearly, the RHS is true for $a == $b == 0, but I'm not sure the LHS
shouldn't also be.  Isn't it just syntactic sugar for the RHS?



I suspect not. Rather I think that

  $a = any(-1,+1) = $b

corresponds to

  $tmp = any(-1,+1);
  $a = $tmp = $b

and thence to

  $tmp = any(-1,+1);
  $a = $tmp  $tmp = $b (*B*)




Quite how the lines I have labelled (A) and (*B*) are
different, I do not understand. Unless wrapping a junction in a variable
produces a different result.


That was my initial reaction as well.  A closer examination of
Martin's message indicates that he tends to think that hitting a
junction ought to thread the entire program throughout the rest of the
lifespan of said junction, so that (e.g.) the thread that runs the
comparison $a = -1 in (*B*) is the same thread that runs
the comparison -1 = $b.  OTOH, since (*A*) spells out two
separate junctions, it would thread each one separately; resulting in
four threads being used to resolve the expression.  In theory, at
least; in practice, he's looking for ways to simulate such threading
without actually having to mess with all of the overhead that a
literal implementation thereof would entail.


In both cases, the problem arises when you apply a predicate to a
junction, and then use the junction within code that only gets
executed according to the truth of the predicate.




Using a junction implies the extraction of the eigenstates. That is being
frowned upon - I understand


I've been doing my utmost to avoid making said implication.


The possible solution to both of these: junctions collapse when they
hit conditional statements - but only within the conditioned scope.
So: within the code block for the if $x  0 statement above, $x only
equals +1, since -1 didn't pass the test.


This is the sieving functionality. Since perl6 is being written explicitly
to avoid sieving out eigenstates, this will not happen.


What I'm hearing is that a decision has already been made on this
matter, so we're stuck with it no matter how counterintuitive the
results of that decision are.


Thus, say $x is the same
as say 1.  In the case of the range test, the code on the RHS of the
 only executes if the code on the LHS evaluated to true; therefore,
when evaluating the RHS, $tmp doesn't include any of the
possibilities that would have failed on the LHS.  That means that:

   0 = -1 | +1 = 0



which is true, because using standard chaining semantics we have
0 = -1|1 and -1|1 = 0
Since the first condition is true (+1 = 0) and the second condition is true
(-1 =0), the compound is true.
Why you might want such a condition, I dont know. But that is the way
junctions are designed to work.


Right now, yes.  I'm arguing that the way that they're designed to
work doesn't DWIM.  Try a slightly different example:

   0 = $x = 1 # 0 is less than $x is less than 1.
   $x ~~ 0..1 # $x is in the range of 0 to 1.

I submit that most people would expect these two statements to be
conceptually equivalent to each other: they may go about tackling the
issue from different angles, but they should always end up reaching
the same conclusion.  But as things stand now, if $x = -2 | 2, these
result in two very different conclusions: the first evaluates as true,
the second as false.  This most certainly doesn't do what I mean until
I have been indoctrinated into the intricacies of Perl and learned to
think like it does - which runs directly counter to the principle of
DWIM.


Perhaps instead of 0 = any(-1,1) = 0, the programmer might want 0 =
all(-1,1) = 0, which is false.


You're assuming that the programmer gets to choose which junction he's
sticking in the middle of the comparison chain.


...becomes:

   0 = -1 | +1  +1 = 0

...which, obviously, is false.



The question really is what is the desired meaning of this conditional.


Yes.  And my answer is that the desired meaning of 0 = -1 | +1 = 0
is closer to (0 = -1 = 0) or (0 = +1 = 0) than it is to (0 =
-1 or 0 = +1) and (-1 = 0 or +1 = 0).  The trick is to figure out
how to get this result without needing a nightmarish amount of
overhead to do it.

--
Jonathan Dataweaver Lang



Re: [Fwd: Re: junctions and conditionals]

2009-04-01 Thread Henry Baragar
On Wednesday, April 01 2009 07:38 am, Richard Hainsworth wrote:
 Right now, yes.  I'm arguing that the way that they're designed to
 work doesn't DWIM.  Try a slightly different example:

     0 = $x = 1 # 0 is less than $x is less than 1.
     $x ~~ 0..1 # $x is in the range of 0 to 1.

 I submit that most people would expect these two statements to be
 conceptually equivalent to each other: they may go about tackling the
 issue from different angles, but they should always end up reaching
 the same conclusion.  But as things stand now, if $x = -2 | 2, these
 result in two very different conclusions: the first evaluates as true,
 the second as false.  This most certainly doesn't do what I mean until
 I have been indoctrinated into the intricacies of Perl and learned to
 think like it does - which runs directly counter to the principle of
 DWIM.

When you say DWIM, I take it you mean that there is an assumption that $x is a 
point in a field (http://en.wikipedia.org/wiki/Field_theory_(mathematics)).  
As you have illustrated, junctions do no form a field.

You would run into the similar problems if $x was a point in a ring 
(http://en.wikipedia.org/wiki/Ring_(mathematics)).   Consider the ring of 
integers modulo 8:
my Ring8 $x = 5 + 3;# evaulates to 0
say OMG, its 0! unless $x;# prints the message 
which does not DWIM if I am expecting $x to be part of a field.

Maybe the problem is that junctions are too easy to create, which is causing 
people to confuse the mathematical structure of the space created by using 
a junction with that of the structure of the space of the underlying 
(non-junctioned) object.

Regards,
Henry


Re: junctions and conditionals

2009-04-01 Thread TSa

HaloO,

Jon Lang wrote:

Another issue: what happens if conditional code mutates a junction
that it filtered?  For example:

$x = any (-5 .. 5);
if $x  0 { $x++ };

At this point, which of the following does $x equal?

any(-4 .. 6) # the original junction gets mutated
any(-5 .. 0, 2 .. 6) # the filtered part of the original junction
gets mutated; the rest is untouched
any(2 .. 6) # the filtered part of the original junction gets
mutated; the rest is lost


This is an example why the controlled block should not be
auto-threaded. That is the assembly point of the resulting
junction any(0,0,0,0,0,1,1,1,1,1) is before the block. Thus
I'm opting for any(-4..6).


Regards, TSa.
--

The unavoidable price of reliability is simplicity -- C.A.R. Hoare
Simplicity does not precede complexity, but follows it. -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12  -- Srinivasa Ramanujan


Re: [Fwd: Re: junctions and conditionals]

2009-04-01 Thread TSa

HaloO,

Richard Hainsworth wrote:

( $a = any(-1,+1)  any(-1,+1) = $b )(*A)

[..]

  $tmp = any(-1,+1);
  $a = $tmp  $tmp = $b (*B*)


Quite how the lines I have labelled (A) and (*B*) are
different, I do not understand. Unless wrapping a junction in a variable
produces a different result.


That was my initial reaction as well.  A closer examination of
Martin's message indicates that he tends to think that hitting a
junction ought to thread the entire program throughout the rest of the
lifespan of said junction, so that (e.g.) the thread that runs the
comparison $a = -1 in (*B*) is the same thread that runs
the comparison -1 = $b.  OTOH, since (*A*) spells out two
separate junctions, it would thread each one separately; resulting in
four threads being used to resolve the expression.  In theory, at
least; in practice, he's looking for ways to simulate such threading
without actually having to mess with all of the overhead that a
literal implementation thereof would entail.


I like to throw in that junctions are value types. That is the two
literal junctions in (*A*) are one and the same object and hence
the global auto-threading should be the same as with an explicit
variable. I like the idea of global auto-threading because it matches
the behavior of the unitary state changes of quantum systems. That is
it is the individual states that interact in a non-entangled fashion
as part of a larger ensemble of execution paths ala Feynman. Just as
in quantum mechanics there are collapse points of junctions in boolean
context e.g. in an if statement. But if we define that  is not
collapsing than it becomes part of a scope that a junction auto-threads
through. Note that the collapse points are statically known from the
structure of the source code! Literal junctions within this stretch of
code need to be assembled as implicit parameters of the code block that
implements the conditional of an if block. With the parameters upfront
it is unimportant if the runtime systems starts multiple threads or
iterates the junction sequentially. But a lightweight thread
implementation boosts performance, of course.

An important thing that has to go into the spec is how side-effective
code is handled in conditionals. E.g.

   if $x.foo  $x.bar  $x.baz {...}

first of all is specced to evaluate $x.bar only ones. But is it also
specced that the three calls are evaluated left to right such that .foo
can influence .bar? Also the $x.baz can be short circuited.

The point I want to make is that in quantum computation a NOT gate
*does* flip the individual value of the entangled states of a qubit.
That is !any(0,1) becomes any(1,0) in such a way that it knows which
0 has become 1 and vice versa for as long as the scope of the junction 
runs. As of now this negation in Perl 6 is a no-op! And we should stop

to compare the current junctions to quantum superposition!

Other equivalences should hold as well. E.g. if one expands $x ^ $y
to (!$x  $y) || ($x  !$y) it should result in the same program
behavior irrespective of $x or $y being junctions.



In both cases, the problem arises when you apply a predicate to a
junction, and then use the junction within code that only gets
executed according to the truth of the predicate.


This implies that junctions also thread through the controlled block
of an if. I hope that my assertion that structural analysis of the code
suffices to define the points where the auto-threads are re-assembled
into a junction still holds in this case.



What I'm hearing is that a decision has already been made on this
matter, so we're stuck with it no matter how counterintuitive the
results of that decision are.


You mean the decision that junction is now a native type with
a private .eigenstates method? I think that is reasonable. The
nativeness of the type is reflected in the fact that the junctive
behavior becomes a structural property of the code. That is the
junction as such has no magic. This magic is in the compiler!
The junction as a native type is a simple list of values.

The above to me implies BTW some finer control for signatures
to specify what kind of junction they allow. E.g. :(Int $)
auto-threads from the outside, :(Object $) passes a junction
without auto-threading. But is :(junction of Int $) the right
way to say that you want to deal with any(1,2,3) but not
any('a','b','c')?



That means that:

   0 = -1 | +1 = 0



which is true, because using standard chaining semantics we have
0 = -1|1 and -1|1 = 0


No, there should be an outer scope that is in charge of auto-threading
the junction through which was created by the compiler from the -1|+1
even though it sits in the middle of the conditional. I would call that
junction propagation.



Since the first condition is true (+1 = 0) and the second condition 
is true

(-1 =0), the compound is true.
Why you might want such a condition, I dont know. But that is the way
junctions are 

Re: junctions and conditionals

2009-04-01 Thread Dave Whipp

Jon Lang wrote:
[proposal that conditional statements should collapse junctions]


$x = +1 | -1;
if $x  0 { say $x is positive. }
else { say $x is negative. }

I suspect that both codeblocks would be executed; but within the first
block, $x == +1, and within the second codeblock, $x == -1.


The problem I see with this (other than implementation issues) is that 
it would lead to unintuitive behavior in some cases:


my $x = one(10,20);
if $x  15 {
  # here, $x collapsed to 20
  if $x  5 { say $x  5 } else { say not $x  5 }
}
if $x  5 { say $x  5 } else { say not $x  5 }

Some people might be surprised if the two tests of $x  5 result in 
two different results.


I don't think that there is any single semantics that won't cause 
surprises (unintuitive behavior) in some cases. So I'd vote for going 
with simple semantics that are easy to explain -- that is, don't attempt 
implicit junctional collapse. Provide operators to collapse when needed, 
but don't attempt to be too clever.


Re: junctions and conditionals

2009-04-01 Thread Mark J. Reed
On Wed, Apr 1, 2009 at 11:49 AM, Dave Whipp d...@dave.whipp.name wrote:

 The problem I see with this (other than implementation issues) is that it
 would lead to unintuitive behavior in some cases:

 my $x = one(10,20);
 if $x  15 {
  # here, $x collapsed to 20
  if $x  5 { say $x  5 } else { say not $x  5 }
 }
 if $x  5 { say $x  5 } else { say not $x  5 }

 Some people might be surprised if the two tests of $x  5 result in two
 different results.


That's surprising, yes, but I'd say the surprise comes from the fact that
it's a one() junction, which has extra weirdness on top of the general
junctional weirdnesses.

So yes, if we collapse the junction, $x is both   5 and not  5 according
to the output.  If we *don't* collapse, $x will consistently fail the $x  5
test - but then you have a value that is somehow both greater than 15 and
not greater than 5, which I would still call surprising.

I don't think that there is any single semantics that won't cause surprises
 (unintuitive behavior) in some cases.


Probably true.


 So I'd vote for going with simple semantics that are easy to explain --
 that is, don't attempt implicit junctional collapse. Provide operators to
 collapse when needed, but don't attempt to be too clever.


While it's easier to find clever programmers than to write clever software,
the gains from the latter are significant, as Larry's work pre- and
post-Perl has repeatedly demonstrated. When a language implementation
provides a feature like junctions that is arguably too clever by half to
start with, I'd rather there be a commensurate amount of cleverness in the
support of that feature.

Basically, I want the specified behavior to make sense as much as possible,
and for it to be easy to explain the places where it doesn't seem to make
sense.  Even if it means we don't get that behavior in 6.0.0.

-- 
Mark J. Reed markjr...@gmail.com


Re: junctions and conditionals

2009-04-01 Thread Dave Whipp

Mark J. Reed wrote:

[I] wrote:

So I'd vote for going with simple semantics that are easy to explain --
that is, don't attempt implicit junctional collapse. Provide operators to
collapse when needed, but don't attempt to be too clever.



While it's easier to find clever programmers than to write clever software,
the gains from the latter are significant, as Larry's work pre- and
post-Perl has repeatedly demonstrated. When a language implementation
provides a feature like junctions that is arguably too clever by half to
start with, I'd rather there be a commensurate amount of cleverness in the
support of that feature.

Basically, I want the specified behavior to make sense as much as possible,
and for it to be easy to explain the places where it doesn't seem to make
sense.  Even if it means we don't get that behavior in 6.0.0.


I'm thinking that the solution to this issue may be a little more 
radical than to-date: don't permit junctions to be stored in $ 
variables! Instead, require junctions to use a twiggle, to alert the 
reader that the surprises may be lurking.


my $x = 1|2; #error
my $|x = 1|2; # ok

Then you just need to invent some syntax to say that collapse is (or 
perhaps isn't) desired:


if [[ $|x  1 ]] { say $|x collapsed }

The most important thing that this does is that it leaves open the 
option to allow $ variables to hold junctions in some future version 
of Perl, without that future version being constrained by legacy semantics.


Re: junctions and conditionals

2009-04-01 Thread Martin Kealey
On Tue, 31 Mar 2009, Jon Lang wrote:
 Another issue: what happens if conditional code mutates a junction
 that it filtered?  For example:

 $x = any (-5 .. 5);
 if $x  0 { $x++ };

 At this point, which of the following does $x equal?

 any(-4 .. 6) # the original junction gets mutated
 any(-5 .. 0, 2 .. 6) # the filtered part of the original junction
 gets mutated; the rest is untouched
 any(2 .. 6) # the filtered part of the original junction gets
 mutated; the rest is lost

I choose #3.

Reality can only take one path through a conditional; which one depends
on the one/any/all/none binding of the junction.

Once you've passed the conditional, you have:

one - single matching value (no longer a junction)
any - filtered list
all - original junction
none - empty (*1)

The threading is an implementation detail; the important thing is a
junction is collection of values and a smart way of rewriting
expressions that contain them, with special treatment for comparison
operators (or indeed anything that forces Boolean content):

$x CMP all($y,$z)   $x CMP $y  $x CMP $z
$x CMP one($y,$z)   $x CMP $y ^^ $x CMP $z  (*2)
$x CMP none($y,$z)  all($x !CMP $y, $x !CMP $z)
$x CMP any($y,$z)   $x !CMP none($y, $x)

$x OP all($y,$z)all( $x OP $y, $x OP $z)
$x OP any($y,$z)any( $x OP $y, $x OP $z)
$x OP one($y,$z)one( $x OP $y, $x OP $z)
$x OP none($y,$z)   none($x OP $y, $x OP $z)

-Martin

(*1: An argument could be made that none should leave the junction alone,
the same as all.)

(*2: I would like to suggest that the semantics of one be changed to mean
pick one (randomly) rather than exactly one. In this respect it
would be the same as any except it wouldn't have the overhead of
filtering *every* match, just at least one.)



junctions and conditionals

2009-03-31 Thread Jon Lang
In Junction Algebra, Martin Kealey wrote:
 On Mon, 30 Mar 2009, Mark J. Reed wrote:
         ( $a = any(-1,+1) = $b ) == ( $a = any(-1,+1)  any(-1,+1) = 
  $b )

 Clearly, the RHS is true for $a == $b == 0, but I'm not sure the LHS
 shouldn't also be.  Isn't it just syntactic sugar for the RHS?

 I suspect not. Rather I think that

        $a = any(-1,+1) = $b

 corresponds to

        $tmp = any(-1,+1);
        $a = $tmp = $b

 and thence to

        $tmp = any(-1,+1);
        $a = $tmp  $tmp = $b

 The more I think about this, the more I come to the conclusion that a
 junction should appear to have a uniform (single) value in each
 eigenthread.

Ugh.  Let me float another problem, and a possible solution to both,
that doesn't require persistent threading environments:

$x = -1 | +1;
if $x  0 { say $x }

As I understand junctions right now, the result of this code is identical to:

   say -1 | +1;

In both cases, the problem arises when you apply a predicate to a
junction, and then use the junction within code that only gets
executed according to the truth of the predicate.

The possible solution to both of these: junctions collapse when they
hit conditional statements - but only within the conditioned scope.
So: within the code block for the if $x  0 statement above, $x only
equals +1, since -1 didn't pass the test.  Thus, say $x is the same
as say 1.  In the case of the range test, the code on the RHS of the
 only executes if the code on the LHS evaluated to true; therefore,
when evaluating the RHS, $tmp doesn't include any of the
possibilities that would have failed on the LHS.  That means that:

0 = -1 | +1 = 0

...becomes:

0 = -1 | +1  +1 = 0

...which, obviously, is false.

Extending this further:

$x = +1 | -1;
if $x  0 { say $x is positive. }
else { say $x is negative. }

I suspect that both codeblocks would be executed; but within the first
block, $x == +1, and within the second codeblock, $x == -1.

$x = +1 | -1;
say $x  0 ?? $x + 2 :: $x * 2;

In this case, $x is +1 when evaluating $x + 2, and it is -1 when
evaluating $x * 2.  After this expression is fully evaluated, they
get recombined into a single junction: +3 | -2.

This last one might be easier to manage simply by having $x autothread
through the ?? :: operator, since you need to be able to reassemble
a junction on the other end.

-- 
Jonathan Dataweaver Lang


Re: junctions and conditionals

2009-03-31 Thread Jon Lang
I've been having some second thoughts concerning this.  Here's where I
stand on it now:

In Perl 6, you have the following decision points, where code may or
may not be executed depending on a condition:
if/unless/while/until/loop/when statements; if/unless/while/until
statement modifiers; short-circuit operators; the trinary conditional
operator.  When you apply a junction to a decision point, only one of
the possible paths will be taken; and the any/all/one/none nature of
the junction will determine which one.  (Without this, there would be
no reason to have a distinction between any/all/one/none.)  However, I
stand by my proposal that after passing one of these decision points,
and until you get back to code that would have been reached regardless
of the decision point, every junction that was involved in the
decision point should be limited such that it acts as if only those
possibilities within it that would have passed the decision point
exist.

With unless, while, until, and loop, the associated block is
the conditional block where the junction gets filtered.  With if,
the main block likewise filters the junctions; but the else block
also provides junction filtering, but in a way that's complementary to
what the main block does.

With short-circuit operators, the RHS counts as a block that
provides junction filtering based on what it would take for the LHS to
avoid tripping the short-circuit behavior.  Similarly, ?? :: treats
the expression following the ?? as a junction-filtering block and
the expression following the :: as a complementary junction-filtering
block, in direct analogy to if/else, above.

Finally, there's the when statement: as with if, etc., the block
that follows the when statement filters junctions according to the
match criterion.  However, when is a bit more complicated in terms
of getting it to DWIM w.r.t. junctions.  Because of the way that
when works conceptually, I'd recommend that for the rest of the
block containing the when statement, it should provide the same sort
of complementary filtering that an else block does for an if
statement.  That is:

given $x {
when $a { ... }
when $b { ... }
when *
}

...should not be thought of as being equivalent to:

given $x {
if $_ ~~ $a { ...; break }
if $_ ~~ $b { ...; break }
if $_ ~~ * {...; break }
}

...but rather:

given $x {
if $_ ~~ $a { ... }
else {
if $_ ~~ $b { ... }
else {
if $_ ~~ * { ... }
}
}
}

--

Another issue: what happens if conditional code mutates a junction
that it filtered?  For example:

$x = any (-5 .. 5);
if $x  0 { $x++ };

At this point, which of the following does $x equal?

any(-4 .. 6) # the original junction gets mutated
any(-5 .. 0, 2 .. 6) # the filtered part of the original junction
gets mutated; the rest is untouched
any(2 .. 6) # the filtered part of the original junction gets
mutated; the rest is lost

--
Jonathan Dataweaver Lang

-- 
Jonathan Dataweaver Lang