raku – How can you assign two 'arrays' (arrays) for a function to return two 'array' variables that have the stealth of 'array' (@)?

Question:

I have a function that returns two 'arrays', but had the difficulty in assigning these results to two variables of 'array'.

my (@A, @N) = volver_dos_arrays;

dd @A;  # muestra lo que está dentro de @A (dd = "data dumper")
dd @N;  

sub volver_dos_arrays
{
    my @alfa = <A B C>;
    my @num  = 1, 2, 3;
    return @alfa, @num;
}

It results in the following: we can see that the first 'array' saved the two 'arrays' that the function returned:

Array @A = [["A", "B", "C"], [1, 2, 3]]
Array @N = []

But, I wanted it to be like this:

Array @A = ["A", "B", "C"]
Array @N = [1, 2, 3]

I know the following works, but I don't like saving an 'array' to a 'scalar'. I don't want to change the sigil of the @A or the @N .

my ($A, $N) = volver_dos_arrays;

dd $A;
dd $N;

sub volver_dos_arrays
{
    my @alpha = <A B C>;
    my @num   = 1, 2, 3;
    return @alpha, @num;
}

How can I do this without changing the sigils?


I learned how to do it, but I still ask the question because it stumped me for a couple of hours. I make an answer if no one gives an answer similar to what I found out.

Answer:

Sure enough as the other answer said, with fixes, you have to use a binding assignment:

my (@A, @N) := volver_dos_arrays();

We can see why using other values:

sub volver-valores { 1,2,3,4 }
my ($a,$b) = volver-valores();
say $a; # 1
say $b; # 2

When we use a list assignment (with my ( … ) ), each variable consumes values ​​according to its stealth, and unnecessary values ​​are discarded. Thus, $a , being scalar, consumes one value ( 1 ), and $b also consumes another. The others ( 3 , 4 ) are discarded.

If we have an array with its corresponding sigil, the last values ​​are not discarded, but are consumed by the array as elements:

sub volver-valores { 1,2,3,4 }
my ($a,@b) = volver-valores();
say $a; # 1
say @b; # 2 3 4

Now, I imagine, you can see the problem. If the first element of the assignment is an array, it will already consume all the values, leaving the second to have the default value (empty, in the case of arrays):

sub volver-valores { 1,2,3,4 }
my (@a,@b) = volver-valores();
say @a; # 1 2 3 4
say @b; # [vacío]

When we use link mapping, the arrays do not consume elements to form the array. We can no longer use the previous sub, because if we use it:

sub volver-valores { 1,2,3,4 }
my (@a,@b) := volver-valores();
# Type check failed in binding to parameter '@a'; expected Positional but got Int (1)

We see that you are trying to make the array 1 . But an array cannot be an integer (although it can contain integers), so it fails. Now we change sub:

sub volver-valores { (1,2,3),<a b c> }
my (@a,@b) := volver-valores();
say @a; # 1 2 3
say @b; # a b c

But beware! the type of @a and @b is not Array, but List. This is because in list binding assignment, we say "let @a be the first value" (and not "let @a be based on the first value). If we use a normal assignment, the difference is clear:

sub volver-valores { (1,2,3),<a b c> }
my (@a,@b) = volver-valores();
say @a; # [1 2 3  a b c] (un arreglo de dos elementos de tipo List)
say @b; # [vacío]

Now, we have said "that @a is made up of the following values", and these two values ​​are a list 1,2,3 and another list a,b,c .

Scroll to Top