syntax Single Argument Rule

Documentation for syntax Single Argument Rule assembled from the following types:

language documentation Lists, sequences, and arrays

From Lists, sequences, and arrays

(Lists, sequences, and arrays) Single Argument Rule

It is the rule by which the set of parameters passed to an iterator such as for is treated as a single argument, instead of several arguments; that is some-iterator( a, b, c, ...) will always be treated as some-iterator( list-or-array(a, b, c)). In this example

my @list = [ (123),
             (12, ),
             [<a b c>, <d e f>],
             [[1]] ];
 
for @list -> @element {
    say "{@element} → {@element.^name}";
    for @element -> $sub-element {
        say $sub-element;
    }
}
# OUTPUT: 
#1 2 3 → List 
#1 
#2 
#3 
#1 2 → List 
#1 
#2 
#a b c d e f → Array 
#(a b c) 
#(d e f) 
#1 → Array 
#1 

Since what for receives is a single argument, it will be treated as a list of elements to iterate over. The rule of thumb is that if there's a comma, anything preceding it is an element and the list thus created becomes the single element. That happens in the case of the two arrays separated by a comma which is the third element in the Array we are iterating in this example. In general, quoting the article linked above, the single argument rule ... makes for behavior as the programmer would expect.

This rule is equivalent to saying that arguments to iterators will not flatten, will not de-containerize, and will behave as if a single argument has been handled to them, whatever the shape that argument has.

my @a = 1,2.say for @a|@a;     # OUTPUT: «[1 2]␤1␤2␤» 
my @a = 1,2.say for $[@a|@a ]; # OUTPUT: «[[1 2] 1 2]␤» 

In the second case, the single argument is a single element, since we have itemized the array. There's an exception to the single argument rule mentioned in the Synopsis: list or arrays with a single element will be flattened:

my @a = 1,2.say for [[@a ]];     # OUTPUT: «1␤2␤» 

The result may be a bit surprising in the case of using a trailing comma:

my @a = 1,2.say for @a,;         # OUTPUT: «[1 2]␤» 

But the comma operator is actually building a higher-order List with a single element, which is also a List. So not so surprising. Since it's got a single element, any higher-order list will be also flattened as above:

my @a = 1,2.say for [@a,];       # OUTPUT: «[1 2]␤»