Sam Vilain wrote:
Rod Adams wrote:
I do not believe that is possible.
This is the "filtering" or "unification" behavior that people keep wanting junctions to have, which they do not.
Aww! But what about all the great problems that could be expressed with them? I know of two languages that consider this to be a core feature now (Prolog, Oz[1]).
I'm not disputing that it would be powerful. I'm simply saying that as currently defined, junctions do not behave in this fashion. It also does not make a lot of sense to filter out restricting values in a none() junction.
And as one who recently proposed a way of getting Prolog like features in Perl (through Rules, not Junctions), I understand the appeal completely. Junctions are not the way to that goal. They are something different.
A given junction always has all of the values it was made with. No more, no less. If you want something else, you have to make a new junction. Consider that it's been decided that :
$j = 11|0; 10 < $j < 1
Is true. $j retains the 0 even after the 0 failed a test.
I can't see how this can be possible with the possibility of autothreading as described in [2].
because it gets interpreted as:
10 < $j < 1 --> (10 < $j) && ($j < 1) --> (10 < any(0, 11)) && (any(0, 11) < 1) --> any(10 < 0, 10 < 11) && any(0 < 1, 11 < 1) --> any(false, true) && any(true, false) --> true && true --> true.
Maybe the example you suggest is true, if both comparisons happen "simultaneously", but what about this one?
if ($j < 10) { if ($j < 1) { say "$j took on two values at once"; } }
The C<say> would occur, even with the first condition as C< $j > 10 >, as you likely intended it to be.
Taking multiple values at once is what junctions are all about.
People seem to forget the role the predicate plays in junction evaluation. You thread over the different values, gain a result, and then use the predicate to recombine the results into a single scalar.
If instead I had said: $j = 11 & 0; 10 < $j < 1
it would be false, because C< all( true, false) > is false.
$j itself never changes. It is always a collection of values with a predicate. If you wish to have a junction with different values in it, you have to create a new one.
Let's say that the implementation chose to implement the first if() by auto-threading. The first thread where $j == 11 succeeds. The second, where $j == 1 fails. In the second thread, $j == 11 fails.
Except that the threadings are indendent of each other.
$j = any(0,11); $j != $j;
is true.
$j != $j --> any(0,11) != any(0,11) --> any(0 != any(0,11), 11 != any(0,11)) --> any(any(0 != 0, 0 != 11), any(11 != 0, 11 != 11)) --> any(any(false, true), any(true, false)) --> any(true, true) --> true
Similarly:
$j = all(0,11);
$j == $j;
is false.
It is by this assumption that the example in [3] was built.
That assumption is in err, and the example does not generate the solutions desired
See my response to it in http://www.nntp.perl.org/group/perl.perl6.language/19428
But wait, isn't (10 < $j < 1) likely to produce the same opcode tree as if($j<10){if($j<1){}} ?
Well if 10 < $j < 1 { ... } if 10 < $j { if $j < 1 { ... }}
Could easily wind up with the same opcodes. Unless the optimizer saw something in the first one where it could prove C< $j < 1 > is false.
> As for the "current" value, there is only a current value during > threading.
Isn't the threading conceptual, and actual threading invoked only when the optimiser has finished using available logic / set theory operations to prevent absurd numbers of threads being made that exit immediately?
The optimizer can skip threading over values that it can prove will not affect the outcome. That's short circuiting.
But asking the optimizer to know in advance what is absurd is a tall order.
Even without junctions, someone could make $j an object with an overloaded set of compare operators against Num. And there's no way for the compiler to know if those operators are consistent and transitive. (One could hope they were, but you never know).
I would not call the threading conceptual. It's a very real thing.
2. http://dev.perl.org/perl6/synopsis/S09.html
Some contexts, such as boolean contexts, have special rules for dealing
with junctions. In any scalar context not expecting a junction of values,
a junction produces automatic parallelization of the algorithm. In
particular, if a junction is used as an argument to any routine (operator,
closure, method, etc.), and the scalar parameter you are attempting to
bind the argument to is inconsistent with the Junction type, 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.
In the cases above, the routine being threaded over is the comparison operator, not the surrounding code block that contains it.
-- Rod Adams