Re: junctions and conditionals
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]
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
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]
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]
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
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]
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
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
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
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
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
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
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