method toggle

Documentation for method toggle assembled from the following types:

class Any

From Any

(Any) method toggle

EXPERIMENTAL routine whose behaviour may change (early implementation exists in Rakudo compiler 2017.12+)

Defined as:

method toggle(Any:D: *@conditions where .all ~~ Callable:DBool :$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 Callables 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 
# 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