Perl Массив содержит себя? - PullRequest
1 голос
/ 15 марта 2020

Я не понимаю, что происходит с этим коротким сегментом кода.

Я поместил вывод и комментарии о нем посередине после операторов печати, которые его производят.

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) " ;

Вопрос real у меня такой:
Как работать напрямую и удобно с массивом,
, который находится внутри другого массива (а не его копии)?
Является ли единственный способ сделать это путем (всегда) отмены ссылки на ссылку?
Например, в следующих двух нерабочих примерах.

Вот что я попробовал:

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)

1 Ответ

4 голосов
/ 15 марта 2020

@{regions[$reg1]} - странный и недокументированный способ написания @regions[$reg1]. (Этот синтаксис задокументирован для использования в строковых литералах в двойных кавычках.)

@regions[$reg1] - это фрагмент массива с одним элементом, что является странным способом записи $regions[$reg1].

вы не получаете первый элемент массива, на который ссылается $regions[$reg1], как вы думаете; вы просто получаете первый элемент @regions.


Давайте рассмотрим

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

Задача № 1

\@ "cancel out", так что

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

- это просто сложный способ записи

my $ref1 = $regions[3];

(Хорошо, это не совсем так, потому что первое автоматически активируется, но здесь это не актуально. )

Задача # 2

Снова вы используете фрагмент массива одного элемента. ВСЕГДА используйте use strict; use warnings; и обращайте внимание на предупреждения!

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

должно быть

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

, что более аккуратно написано с помощью "обозначения стрелки".

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

Задача № 3

Наконец, не используйте косвенные вызовы методов. Они вызывают проблемы.

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

должно быть

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

Заключение

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

должно быть записано как

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

Без переменной это будет

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

или просто

$regions[3][2] = Point->new(4, 5);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...