1

I do not understand what is going on with this short segment of code.

I have put the output and comments about it in the middle, after the print statements which produce it.

my @regions = (
0,
1,
2,
[ 0, new Point(3,1), new Point(3,2), new Point(3,3) ],
4,
5 );

$reg1 = 3;
print "1: $regions[$reg1] \n";

@reg1 = @{regions[$reg1]};
print "2: $reg1[0]\n";
print "3: $reg1[0][1]\n";
print "4: ", Point::stringPoint($reg1[0][1]), "\n";

# HERE IS THE OUTPUT from the above print statements, with comments about my confusion appended
1: ARRAY(0xe8b0e0)      # ok - element 3 of @regions is an array, as expected.
2: ARRAY(0xe8b0e0)      # It appears to be an array of one element, which is itself. ???
3: Point=HASH(0xfda5e0) # We have go 'down' one more level to get what we want - that makes no sense
4: 3,1                  # Yes, there it is

package Point;
sub new {
   my $class = shift;
   my $self = {
      x => shift,
      y => shift
   };
   bless $self, $class;
   return $self;
}

sub stringPoint
{
 my $p = shift;
 return "$p->{x},$p->{y}";
}

" Code related to new question (with output) " ;

The real question I have is this:
How to work directly and conveniently with an array,
which is inside another array (not a copy of it) ?
Is the only way to do that by (always) de-referencing a reference?
Such as in the two non-working examples which follow.

Here is what I tried:

my $ref1 = \@{$regions[3]};

@{$ref1}[2] = new Point(4, 5);  # changes original array
print1Region(3, $ref1);
# OUTPUT = (3,1) (4,5) (3,3)

my @arr1 = @{$ref1};
$arr1[1] = new Point(2,6);  # does not
print1Region(3, $ref1);
# OUTPUT = (3,1) (4,5) (3,3)

$ref1[0] = new Point(1,4);  # does not
print1Region(3, $ref1);
# OUTPUT = (3,1) (4,5) (3,3)
6
  • 1
    @{regions[$reg1]} - Sure about that? Try changing it to @{$regions[$reg1]}. Commented Mar 15, 2020 at 6:20
  • @Shawn - that change makes THIS program work more sensibly, but let me go back to the 'unsimplified' version to see why I didn't use your construct in the first place. Commented Mar 15, 2020 at 6:39
  • @Shawn - ok I think I got it ... it had to do with passing these things to subroutines, and getting the use of \ right to get references when needed. Thanks for that bit of help. Commented Mar 15, 2020 at 6:50
  • 1
    Note that if you use warnings; like you always should, perl would have warned you abut that line. Commented Mar 15, 2020 at 7:05
  • (What I don't understand, and why I didn't make an actual answer, is why that's being treated as an array slice and not a syntax error) Commented Mar 15, 2020 at 9:42

1 Answer 1

4

@{regions[$reg1]} is a weird and undocumented way of writing @regions[$reg1]. (It's a syntax documented for use in double-quoted string literals.)

@regions[$reg1] is an array slice with one element, which is a weird way of writing $regions[$reg1].

So you aren't getting the first element of the array referenced by $regions[$reg1] as you think you are; you are simply getting the first element of @regions.


Let's look at

my $ref1 = \@{$regions[3]};
@{$ref1}[2] = new Point(4, 5);

Problem #1

\@ "cancel out", so

my $ref1 = \@{$regions[3]};

is just a complicated way of writing

my $ref1 = $regions[3];

(Ok, that's not quite true because the former autovivifies, but that's not relevant here.)

Problem #2

Again you're using an array slice of one element. ALWAYS use use strict; use warnings; and heed the warnings!

@{$ref1}[2] = new Point(4, 5);

should be

${$ref1}[2] = new Point(4, 5);

which is more cleanly written using the "arrow notation".

$ref1->[2] = new Point(4, 5);

Problem #3

Finally, don't use indirect method calls. They cause issues.

$ref1->[2] = new Point(4, 5);

should be

$ref1->[2] = Point->new(4, 5);

Conclusion

my $ref1 = \@{$regions[3]};
@{$ref1}[2] = new Point(4, 5);

should be written as

my $ref1 = $regions[3];
$ref1->[2] = Point->new(4, 5);

Without the variable, this would be

$regions[3]->[2] = Point->new(4, 5);

or just

$regions[3][2] = Point->new(4, 5);
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for all that. I think the way to go will be $ref1->[subscript]. The whole reason for this question in the first place was that I didn't want to have write $regions[$reg1] all the time - it's not just this one line of code, it's a whole section, involving two of them, with many uses of the elements of those arrays. Hence the desire for a temporary variable for the element of regions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.