In Any§
See primary documentation in context for method toggle
method toggle(Any:D: *@conditions where .all ~~ Callable:D, Bool :$off --> Seq:D)
Iterates over the invocant, producing a Seq
, toggling whether the received values are propagated to the result on and off, depending on the results of calling Callables
in @conditions
:
say (1..15).toggle(* < 5, * > 10, * < 15); # OUTPUT: «(1 2 3 4 11 12 13 14)» say (1..15).toggle(:off, * > 2, * < 5, * > 10, * < 15); # OUTPUT: «(3 4 11 12 13 14)»
Imagine a switch that's either on or off (True
or False
), and values are produced if it's on. By default, the initial state of that switch is in "on" position, unless :$off
is set to a true value, in which case the initial state will be "off".
A Callable
from the head of @conditions
is taken (if any are available) and it becomes the current tester. Each value from the original sequence is tested by calling the tester Callable
with that value. The state of our imaginary switch is set to the return value from the tester: if it's truthy, set switch to "on", otherwise set it to "off".
Whenever the switch is toggled (i.e. switched from "off" to "on" or from "on" to "off"), the current tester Callable
is replaced by the next Callable
in @conditions
, if available, which will be used to test any further values. If no more tester Callable
s are available, the switch will remain in its current state until the end of iteration.
# our original sequence of elements: say list ^10; # OUTPUT: «(0 1 2 3 4 5 6 7 8 9)» # toggled result: say ^10 .toggle: * < 4, * %% 2, &is-prime; # OUTPUT: «(0 1 2 3 6 7)» # First tester Callable is `* < 4` and initial state of switch is "on". # As we iterate over our original sequence: # 0 => 0 < 4 === True switch is on, value gets into result, switch is # toggled, so we keep using the same Callable: # 1 => 1 < 4 === True same # 2 => 2 < 4 === True same # 3 => 3 < 4 === True same # 4 => 4 < 4 === False switch is now off, "4" does not make it into the # result. In addition, our switch got toggled, so # we're switching to the next tester Callable # 5 => 5 %% 2 === False switch is still off, keep trying to find a value # 6 => 6 %% 2 === True switch is now on, take "6" into result. The switch # toggled, so we'll use the next tester Callable # 7 => is-prime(7) === True switch is still on, take value and keep going # 8 => is-prime(8) === False switch is now off, "8" does not make it into # the result. The switch got toggled, but we # don't have any more tester Callables, so it # will remain off for the rest of the sequence.
Since the toggle of the switch's state loads the next tester Callable
, setting :$off
to a True
value affects when first tester is discarded:
# our original sequence of elements: say <0 1 2>; # OUTPUT: «(0 1 2)» # toggled result: say <0 1 2>.toggle: * > 1; # OUTPUT: «()» # First tester Callable is `* > 1` and initial state of switch is "on". # As we iterate over our original sequence: # 0 => 0 > 1 === False switch is off, "0" does not make it into result. # In addition, switch got toggled, so we change the # tester Callable, and since we don't have any more # of them, the switch will remain "off" until the end
The behavior changes when :off
is used:
# our original sequence of elements: say <0 1 2>; # OUTPUT: «(0 1 2)» # toggled result: say <0 1 2>.toggle: :off, * > 1; # OUTPUT: «(2)» # First tester Callable is `* > 1` and initial state of switch is "off". # As we iterate over our original sequence: # 0 => 0 > 1 === False switch is off, "0" does not make it into result. # The switch did NOT get toggled this time, so we # keep using our current tester Callable # 1 => 1 > 1 === False same # 2 => 2 > 1 === True switch is on, "2" makes it into the result