Motivation for the array construction operator using the 1-arg rule:
- Because it's really just a circumfix operator, not special syntax.
Other operators/keywords that expect a potentially-nested list as input, use the single-argument rule - so for consistency, this one does too.
Motivation for list-transforming operators/keywords in general using the 1-arg rule:
- To facilitate the common case where the whole input list is already stored in one variable.
- To avoid further special-casing literal commas.
Operators don't have argument lists like functions; they accept just one object as their argument (unary/circumfix operators), or one on each side (binary operators).
The expression @a,
constructs a one-element List
, so when passing the result of that expression to a list-transforming operator, it treats that List
just like it would treat any other non-containerized Iterable
passed to it: It iterates it, and operates on its element(s).
- The fact that the argument doesn't get iterated when it is wrapped in an item container (i.e. a
$
variable), is meant to preserve the singular-plural distinction of the sigils, as @p6steve's answer explains.
Here's the aforementioned consistency, demonstrated using one keyword, one binary operator, and one circumfix operator:
for @a { ... } # n iterations
for @a, { ... } # 1 iteration
for @a, @b { ... } # 2 iterations
for $a { ... } # 1 iteration
1..Inf Z @a # new Seq of n elements
1..Inf Z @a, # new Seq of 1 element
1..Inf Z @a, @b # new Seq of 2 elements
1..Inf Z $a # new Seq of 1 element
[ @a ] # new Array with n elements
[ @a, ] # new Array with 1 element
[ @a, @b ] # new Array with 2 elements
[ $a ] # new Array with 1 element
What about subroutines/methods?
These do have argument lists, so the single-argument rule doesn't come as naturally to them as it does to operators.
Note that in the top-level scope of an argument list, commas don't create List
s – they separate arguments.
Subroutines/methods that are considered "list transformation" routines which expect potentially-nested lists as input, still participate in the single-arument rule though, by checking whether they got one argument or multiple, and if just one, whether it is wrapped in an item container:
map {...}, @a; # n iterations
map {...}, (@a,); # 1 iteration (Parens needed to get a List-constructing comma.)
map {...}, @a, @b; # 2 iterations
map {...}, $a; # 1 iteration
User-defined routines can easily get this behavior by using a +@
signature.