3

Background

I have these four lines of code that I am trying to extract into one function:

my @firstList = split /\s+/, $doubleArray{A_I}{B_I};
@firstList = shuffle(@firstList);
my @secondList = split /\s+/, $doubleArray{A_I}{C_I};
@secondList = shuffle(@secondList);

Since the only functional difference is the second index of the two dimensional array , I wanted to make it so that the second index ("B_I" and "C_I") are passed into a function.

Proposed solution

In other words I want to make a function like the one below:

my funkyFunc($){
     my $index = shift;
     my @list = split /\s+/, $doubleArray{A_I}{$index};
     @list = shuffle(@list);
     return @list;
}

I would intend to use it as such:

my @firstList = funkyFunc("B_I");
my @secondList = funkyFunc("C_I");

However, I'm unsure as to how perl would interpret "B_I" or "C_I", or likewise B_I and C_I. Because of this complexity, I wanted to know...

Question

Is there a way in perl to pass in the name of an array index?

isakbob
  • 1,439
  • 2
  • 17
  • 39
  • With some exceptions we can't have "barewords" so you need to quote these literal strings, thus `func('B_I')` (don't need double quotes but they won't hurt here either). Then the rest will work right since `$index` will then have that value. One of the mentioned exceptions is with hash keys -- the fact that `A_I` in `$doubleArray{A_I}` (etc) doesn't have to be quoted is a particular syntax convenience – zdim Dec 02 '19 at 18:36
  • 1
    In `$doubleArray{A_I}{$index}` the `$index` is evaluated and its value used as a key. So if you assigned the string `A_I` to `$index` (from `@_`) then that's used. So yes you can pass an "index" (for an associative array --the hash -- in this case) like that, in a variable. – zdim Dec 02 '19 at 18:40
  • Note though that your function this way needs access to that external `%doubleArray` hash. So if you were to move the function to a module (in which there is no such hash) it would stop working; there are many other chances for errors when a function accesses data from its surrounding scope directly, as opposed to have all needed data passed to it. I'd suggest that you pass a (reference to) that hash to the function as well. – zdim Dec 02 '19 at 18:51
  • NOTE: `{}` indicates that you use hash, string index for hash does not require to be quoted [feature of perl syntax]. You should use `"string $var string"` only if you have variable which should be rendered to it's _value_, otherwise use `'some $var string'` it will be rendered literally _some $var string_. – Polar Bear Dec 02 '19 at 19:20

1 Answers1

4

Those aren't arrays, those are hashes (dictionaries, associative arrays in other languages). With that, the B_I and C_I are then treated as bareword strings. If these were actual arrays, then these would be treated as bareword function calls, and you'd have to have those available to be called in the caller, and no need for quoting there.

Since you're using hashes, the keys are strings, and you passing in 'B_I' will result in $index being a string of B_I, and since your {$index} has something that isn't allowed in a bareword string (the $), perl will interpret it as a variable instead of a literal, and everything will work exactly the way you want.

Tanktalus
  • 21,664
  • 5
  • 41
  • 68
  • Tanktalus is correct. But you may wish to return \@list to return a reference to an array (a simple scalar) rather than the array itself, which has the potential to have many members. The caller than then use the return value, such as @$ret, to get all values. – Gilbert Dec 02 '19 at 18:47
  • Re "*associative arrays in other languages*", Associative arrays are a class of data structure, which has nothing to do with any language. Perl hashes are a type of hash table, and hash tables are associative arrays. – ikegami Dec 02 '19 at 19:27