# Re: Tweaking junctions

```I have to admit to feeling uneasy about the whole action-at-a-distance
effect that junctions are capable of producing. They sit around pretending
to be a scalar, only to pop up and wreak havoc with ones expectations of
linearity when you're not expecting it.```
```
That unexpected-action-at-a-distance is somewhat mitigated by autothreading
functions where the junction is presented as a direct parameter, but being
able to defer a junction by putting it inside an aggregate seems like asking
for trouble unless we make sure that it behaves as much like an ordinary
scalar as possible when it does finally get collapsed.

I think we need to decide whether junctions are just about flow control, or
are more generalized parallel data handling, typified as a way of handling
sets.

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. And deciding what
happens when, in the process of autothreading junction A, you wind up
collapsing junction B in different ways (including perhaps not collapsing
it)? Right now I don't think we're up for all that.

For the sake of flow control, do we have a formal algebra of how we apply
distributive rules so that all the elements of the resulting junction are
booleans and the result of the collapse is "obvious"?

In the simple cases it's (supposedly) obvious:
\$foo == (\$bar | \$zot)   ===     (\$foo == \$bar) | (\$foo == \$zot)

\$foo != (\$bar | \$zot)   ===     not(\$foo == (\$bar | \$zot))
===     not((\$foo == \$bar) | (\$foo == \$zot))
===     (not(\$foo == \$bar)) & (not(\$foo ==
\$zot))
===     (\$foo != \$bar) & (\$foo != \$zot)

\$foo < (\$bar | \$zot)    ===     (\$foo < \$bar) | (\$foo < \$zot)
versus:
\$foo < (\$bar | \$zot)    ===     not(\$foo >= (\$bar | \$zot))
===     not((\$foo >= \$bar) | (\$foo >= \$zot))
===     (not(\$foo >= \$bar)) & (not(\$foot >=
\$zot))
===     (\$foo < \$bar) & (\$foo < \$zot)

In short, in order to avoid unexpected action at a distance, it's logical to
invert the junction type, but in doing so you hit some very nasty corner
cases. How do you know whether a function is saying "X has property Y" or
"X does not have property ~Y" ? Which of "Y" or "~Y" are we talking about?

It seems fair enough to infer that equality comparison is "Y" rather than
"~Y", but any other sort of comparison is fraught.

This leads me to the conclusion that collapsing a junction over an ordered
comparison should fail in the same way that an ordered comparison involving
complex numbers or vectors should fail (or more generally, an ordered
comparison of any aggregate should fail unless the aggregate type defines some
sensible ordering; there should be no "default").

Indeed, the whole notion of autothreading a junction over an arbitrary
function (to produce a boolean that can be used for flow control) starts to
sound fishy: how do we decide whether a given function should be treated
like "==", where the distributive rule produces the same junction type, or
like "!=", where the distributive rule produces the inverse junction type?

Or do we not invert junctions, and run the risk of unexpected