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) But what about: $foo != ($bar | $zot) === not($foo == ($bar | $zot)) === not(($foo == $bar) | ($foo == $zot)) === (not($foo == $bar)) & (not($foo == $zot)) === ($foo != $bar) & ($foo != $zot) Moreover, what about: $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 action-at-a-distance instead? -Martin