Martin D Kealey asked:

> Or do we not invert junctions, and run the risk of unexpected
> action-at-a-distance instead?

I think our current approach is correct. That is: we "invert"
junctions on operators that are themselves intrinsically inverted
(such as !=, !~~, !<), but do not invert on those that are not
(such as ==, ~~, >=). Or rather, we *never* invert junctions at all, but
merely honour the standard semantics of the prefix:<!> metaoperator:
hoisting the negation outside the entire operation and applying it
once the underlying operation is complete.

The apparent paradox you demonstrated with the two interpretations of
C<$foo < ($bar | $zot)> is due to the assumption (employed in
the second interpretation) that < is identical to !>=. Certainly that is
true for simple scalar numbers, but not always for vector types such as
tuples, sets, bags, complex numbers...or junctions. That doesn't make
either < or !>= intrinsically invalid on vector types (though they
obviously are inappropriate for *some* vector types); it just means you
can't reasonably treat the two operators as universally interchangeable,
just because they sometimes are.

In summary, the "problem" here seems to be that, algebraically,
junctions don't behave exactly like non-junctions. Which is true, but no
more a problem than the fact that, algebraically, complex numbers don't
behave exactly like non-complex numbers, or that sets don't behave
exactly like non-sets, or that Rats don't behave exactly like Nums,
which don't behave exactly like Ints, which don't behave exactly like
ints either.

And, of course, that's why Perl 6 has strong typing. So that, when these
differences in behaviour do matter, we can specify what kind(s) of data
we want to allow in particular variables, parameters or return
slots...and thereby prevent unexpected kinds of data from sneaking in and
violating (un)reasonable expectations or inducing (apparent) paradoxes. :-)


With regard to your other point:

> If it's about parallel data handling, then we have to be prepared to
> (notionally) fork the entire rest of the runtime, even as far as
> having a definition of what return value the parent process sees (from
> "exit") when those threads are implicitly collapsed at termination.

That's certainly true, although junctions are supposed to guarantee
to coalesce all the threads they may generate back into a single superimposed
result back in the originating thread.

The problem only arises if an operation or subroutine that has been
junctively threaded terminates without returning. But that's just
"having a side-effect", which we already know is inappropriate for
junctions (and hyperoperators, and autothreaded loops, and pretty much
any other kind of parallel construct).

Damian

Reply via email to