In Control flow§
See primary documentation in context for for
The for
loop iterates over a list, running the statements inside a Block
once on each iteration. If the block takes parameters, the elements of the list are provided as arguments. By default, the block takes one parameter, $_
:
my = 1..3;for # prints each value contained in @foofor # same thing, because .print implies a $_ argumentfor # prints 42 as many times as @foo has elements
Pointy block syntax or a placeholder may be used to name the parameter:
my = 1..3;for ->for # same thing
Multiple parameters can be declared, in which case the iterator takes as many elements from the list as needed before running the block.
my = 1..3;for .kv -> ,my = <a b c> Z=> 1,2,3;for .kv -> ,for 1, 1.1, 2, 2.1 # OUTPUT: «1 < 1.12 < 2.1»
Parameters of a pointy block can have default values, allowing the code to handle lists with missing elements.
my = 1,2,3,4;for -> , = 'N/A', = 'N/A'# OUTPUT: «1 2 34 N/A N/A»
When no parameters are specified for a for
loop's block, when
can be used within it similarly to how it's used in a given
block:
# A solution for FizzBuzz:for 1..100
If the postfix form of for
is used, a block is not required and the topic is set for the statement list.
say „I $_ butterflies!“ for <♥ ♥ ♥>;# OUTPUT: «I ♥ butterflies!I ♥ butterflies!I ♥ butterflies!»
A for
may be used on lazy lists – it will only take elements from the list when they are needed, so to read a file line by line, you could use:
for .lines ->
Iteration variables are always lexical, so you don't need to use my
to give them the appropriate scope. Also, they are read-only aliases. If you need them to be writable, use <->
instead of ->
. Alternatively, you can add the is rw
trait; this performs a binding operation so assigning to the parameter changes the value of the variable at the caller side. If instead you want to modify copies of the arguments within the block, add is copy
.
my = 1..3;for <->say ; # OUTPUT: «[Odd Even Odd]»= 1..3;for -> is rwsay ; # OUTPUT: «[Odd Even Odd]»= 1..3;my ;for -> is copysay ; # OUTPUT: «[1 2 3]»say ; # OUTPUT: «[Odd Even Odd]»
This rule also applies to the topic variable $_
, which by default is a read-write alias; it will become read-only if it's used in a ->
loop.
my = 1..3;for -># Error: ...require mutable argumentsfor ->
A for
loop can produce a List
of the values produced by each run of the attached block. To capture these values, put the for loop in parenthesis or assign them to an array:
(for 1, 2, 3 ).say; # OUTPUT: «(2 4 6)»my = do for 1, 2, 3 ; .say; # OUTPUT: «[2 4 6]»my = (for 1, 2, 3 ); .say; # OUTPUT: «[2 4 6]»
This implies that, if the results of the loop are not assigned, they will be in a sink context:
Sunk.new( :titanic() ) for ^3;for 1# OUTPUT:# Sinking 0# Sinking 1# Sinking 2# About to sink# Sinking 1
The first loop creates three elements but they are in a sink context, so its sink
method is called. In the second loop, its last statement will be in a sink context, so it will be also sunk (from version 6.d).
The Empty
constant will act as a no-op for a loop:
say "Not here" for Empty;
Will not do anything. This constant is equivalent to an empty Slip or List.
Undefined values will behave in the same way:
my := Empty;.say for ;say ; # OUTPUT: «()»
Assigning Empty
will effectively undefine an Array
, using for
over an undefined array will not even enter the loop, as shown, effectively behaving in the same way as above when Empty
was used directly.
With hyper
and race
, the for
loop is potentially iterated in parallel. See also the documentation for hyper
and race
in class Map
.
my = hyper for ^10_000 -> ;say .elems; # OUTPUT: «1229»say .tail: 5; # OUTPUT: «(9931 9941 9949 9967 9973)»
with hyper
the order of elements is preserved.
my = race for ^10_000 -> ;say .elems; # OUTPUT: «1229»
Unlike hyper
, race
does not preserve the order of elements.