Scott Duff essayed:

So, I was all set to show how this could work with junctions, but then
I realized that I don't understand them well enough, so here's what I
came up with:

$j0 = $that_happens | $that_doesnt_happen;
$j1 = !$that_happens | !$that_doesnt_happen;
given ($this) {
when $j0 ~~ $that_happens { ... }
when $j0 ~~ $that_doesnt_happen { ... }
when all($j0) { ... }
when any($j0) { ... }
when any($j1) { ... } # "some" Rare, I expect
when none($j0) { ... }
}

Is that right?
Not quite. The first problem is that if either of the first two C<when>
fire, we immediately break out of the C<given>. There will probably be
a lexical pragma to reverse that default behaviour.

The other problem is that your using junctions of junctions, which have
quite different semantics.

Here's some code that has (what I construe to be) the desired behaviour:

    @possible_states = ($that_happens, $that_doesnt_happen);
    given ($this) {
	use fallthrough;
	when $that_happens          { "Have a party" }
 	when $that_doesnt_happen    { "Sing" }
 	when all(@possible_states)  {
 		# Do something
 	}
 	when any(@possible_states)  {
 		# Do something else
 	}
 	when $_ !~ all(@possible_states) {
 		# Do something other
 	}
 	when none(@possible_states) {
 		# Do something however
 	}
    }


> What happens when there's a
junction on either side of a smart match?
That depends (multimorphically) on the types of the junctions.
Here's a handy table:


	all(A,B) ~~ all(C,D)    -->   (  A~~C  &&   A~~D )  &&  (  B~~C  &&   B~~D )
	all(A,B) ~~ any(C,D)    -->   (  A~~C  ||   A~~D )  &&  (  B~~C  ||   B~~D )
	all(A,B) ~~ one(C,D)    -->   (  A~~C  ^^   A~~D )  &&  (  B~~C  ^^   B~~D )
	all(A,B) ~~ none(C,D)   -->   (!(A~~C) && !(A~~D))  &&  (!(B~~C) && !(B~~D))

	any(A,B) ~~ all(C,D)    -->   (  A~~C  &&   A~~D )  ||  (  B~~C  &&   B~~D )
	any(A,B) ~~ any(C,D)    -->   (  A~~C  ||   A~~D )  ||  (  B~~C  ||   B~~D )
	any(A,B) ~~ one(C,D)    -->   (  A~~C  ^^   A~~D )  ||  (  B~~C  ^^   B~~D )
	any(A,B) ~~ none(C,D)   -->   (!(A~~C) && !(A~~D))  ||  (!(B~~C) && !(B~~D))

	one(A,B) ~~ all(C,D)    -->   (  A~~C  &&   A~~D )  ^^  (  B~~C  &&   B~~D )
	one(A,B) ~~ any(C,D)    -->   (  A~~C  ||   A~~D )  ^^  (  B~~C  ||   B~~D )
	one(A,B) ~~ one(C,D)    -->   (  A~~C  ^^   A~~D )  ^^  (  B~~C  ^^   B~~D )
	one(A,B) ~~ none(C,D)   -->   (!(A~~C) && !(A~~D))  ^^  (!(B~~C) && !(B~~D))

	none(A,B) ~~ all(C,D)   -->   (!(A~~C  &&   A~~D))  &&  (!(B~~C  &&   B~~D))
	none(A,B) ~~ any(C,D)   -->   (!(A~~C  ||   A~~D))  &&  (!(B~~C  ||   B~~D))
	none(A,B) ~~ one(C,D)   -->   (!(A~~C  ^^   A~~D))  &&  (!(B~~C  ^^   B~~D))
	none(A,B) ~~ none(C,D)  -->  !(!(A~~C) && !(A~~D))  && !(!(B~~C) && !(B~~D))

The logic is straightforward and the pattern not too hard to see: the type of
the left operand determines the "top level" (i.e. lower precedence)
logical connective whilst the type of the right operand determines the "bottom level"
(higher precedence) logical connectives.

BTW, the same table works for any boolean operation between junctives.
And, of course, it generalizes to any number of states on either side.

Damian

Reply via email to