0

I dont usually use my keyword for scopes. But I have decided to do so for submodule. Here is the code:

sub aros{
   open my $fh, shift;
   while(<$fh>){
   my @{"ar" . ++$i} = split unless /\A\s+\z/;
   }
}

The purpose is to make a chunk of lists, named with an incremented number at the end of its name. And making them private for the scope of the while loop (the closest block). But when i tried to compile, this error arise:

Can't declare array dereference in "my" at ./a line 4, near "} ="

Can someone explain me, how "my" - scope oriented keywords - works innerly? I supposed that no matter what kind of name is used, or what kind of type (whether scalar or list) is used, the "my" keyword should make it private. Do I suppose wrongly?

Herdsman
  • 609
  • 4
  • 17
  • 2
    The whole [point of `my`](https://stackoverflow.com/q/20889609/589924) is to limit the scope of your variables (to limit where they can be seen). I applaud you for knowing that limiting the scope of the variables is a fundamental tenet of computer science because of the slew of benefits it has. (It reduces coding, maintenance and debugging time.) However, that necessarily requires knowing the variable names at compile-time. You are trying to generate the name at run-time. – ikegami Nov 16 '19 at 23:10

1 Answers1

4

my is not an ordinary function. What follows it must be a variable (or a list of variables), not an expression.

You seem to be creating a variable name dynamically. That's not recommended, see for example Why it's stupid to `use a variable as a variable name'.

The common way is to declare the array before starting the loop. Also, to add a new element to an array, use push instead of assigning to a new index - but it's unclear what you want to store in the array.

sub aros{
    open my $fh, '<', shift or die $!;
    my @ar;
    while (<$fh>) {
        push @ar, [split] unless /\A\s+\z/;
    }
}
choroba
  • 200,498
  • 20
  • 180
  • 248
  • Well i used the dynamic naming for purpose, since the `` is a line from a file and I do not know how many of them will be - so therefor naming them with numbers is logical. Second - I am assigning the splitted line (`split $_` - where `$_` is the line from ``), so it is not ambiguous a I dont know why I should push a scalar split (an list) - I think when you make `scalar @somelist` you are returning the length of that list, not its elements and that is not what I want. Hope my purpose is clearer now. – Herdsman Nov 16 '19 at 21:49
  • 1
    @Herdsman: Not at all. Creating a unknown number of variables doesn't sound logical to me, creating an array of unknown length does. I changed `scalar split` into `[split]`, i.e. storing an array reference containing the result of [split](http://p3rl.org/split). – choroba Nov 16 '19 at 22:39
  • 2
    @Herdsman, Re "*therefor naming them with numbers is logical*", Quite the opposite, having a structure that knows exactly how many items are in the structure makes far more sense. What do you do when you have an arbitrary number of things? You either count them or you iterate over them. This is done using `@a` in scalar context and `for (@a)` respectively for arrays. Using numbered variables? Not so easy. – ikegami Nov 16 '19 at 23:13
  • They did? I don't see that. ...ok, I suppose they might have meant "bunch of lists" when they said "chunk of lists"? That's really the opposite of what chunk means. Deleted comment. – ikegami Nov 17 '19 at 02:07
  • @choroba well yeah, storing reference to the array `[split]` could be solution. But I wanted to make it without references (as part of learning). Nevertheless thanks. – Herdsman Nov 17 '19 at 13:01