I'm looping through the depends
array from a META6.json
. I've loaded into a Hash
using JSON::Fast
. When I'm looping through it using a for
loop, however, it only goes through the loop once, and the item is the same array:
use JSON::Fast;
my %meta = from-json(slurp("META6.json"));
for %meta<depends> -> $dependency {
dd $dependency;
}
This piece of code returns
Array $dependency = $["Config::Parser::toml:ver<1.0.1+>", "Config:api<1>:ver<1.3.5+>", "Dist::Helper:ver<0.21.0+>", "Hash::Merge", "Terminal::Getpass:ver<0.0.5+>", "zef"]
I'm expecting it to loop through the %meta<depends>
6 times, which each iteration holding a different element from that array.
For good measure, this is the output of dd %meta<depends>
from the example:
Array %meta = $["Config::Parser::toml:ver<1.0.1+>", "Config:api<1>:ver<1.3.5+>", "Dist::Helper:ver<0.21.0+>", "Hash::Merge", "Terminal::Getpass:ver<0.0.5+>", "zef"]
Why is the loop not looping the way I expected?
EDIT: I'm using the latest Rakudo Star:
This is Rakudo Star version 2018.04.1 built on MoarVM version 2018.04.1
implementing Perl 6.c.
We can use iteration with a for loop to visit each element of an array. This is called traversing the array. Just start the index at 0 and loop while the index is less than the length of the array.
Iterating over an array You can iterate over an array using for loop or forEach loop. Using the for loop − Instead on printing element by element, you can iterate the index using for loop starting from 0 to length of the array (ArrayName. length) and access elements at each index.
Use a for loop to iterate over an array. Use a for loop when you know the loop should execute n times. Use a while loop for reading a file into a variable.
In VBA, to loop through an array you can use the For Loop (For Next). And to write this loop code you need to know the size of the array (upper and lower bound) so that you can use both as the counter for the loop. Basically, for loop will start from the first element of the array and loop up to the last.
Even though %meta<depends>
contains an Array
, it is contained inside an item (container). The for
statement looks at that and decides there's only 1 thing to iterate over (the container).
This is easily remedied: by suffixing .list
you convert the item to something Iterable
, and thus it will iterate over the Array
in the container:
for %meta<depends>.list -> $dependency {
A slightly shorter syntax for this is @()
:
for @(%meta<depends>) -> $dependency {
EDIT: or use the syntax suggested by jjmerelo, which decontainerizes the element, and thus exposes the underlying Array
to for
:
for %meta<depends><> -> $dependency {
This is a pitfall. Essentially this is like:
my $var = ['a', 'b', 'c'];
for $var -> $v {
dd $v;
}
Which gives you: $["a", "b", "c"]
If you iterate an array with @ sigil it already acts as an Array, but when you have a list inside a scalar it will return the Array and not iterate inside it.
The solution is to use .list
to make it act as a list instead of as a scalar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With