Разве все ссылки не разыменованы одинаково? - PullRequest
0 голосов
/ 11 октября 2018

Я создаю программу с несколькими подпрограммами, которые я хотел бы использовать снова и снова.О, я также абсолютный новичок в Perl, так что это так.Итак, у меня есть массивы, которые я заполняю строками текста, которые я извлекаю из файлов, чтобы я мог анализировать, изменять, сравнивать и т. Д. Либо с пользовательским вводом, либо с другими битами данных, которые я извлекаю из других файлов в зависимости отв программе подпрограмма развернута в.

Итак, у меня есть одна подпрограмма, которой я передаю три ссылки на массивы:

@sorted = &sort_arrays(\@order, \@ktms, \@sorted);

Разыменовываю массивы после передачи в подпрограмму для проверки работоспособностивот так:

sub sort_arrays {
my ($ref_array, $list_array, $sorted_r) = @_;
print "@{$ref_array} \n"; print "@{$list_array} \n"; print "@{$sorted_r} \n";

и я получаю значения каждой ячейки каждого массива, напечатанные в одной строке, каждая с одним пробелом между ними.Большой!У меня фактически была эта работа как отдельная программа для сортировки случайно сгенерированного файла из мастера на основе порядка, в котором случайные значения появляются в мастере.Сейчас я пытаюсь сделать другие подпрограммы общими и многократно используемыми со ссылками, но мне не так повезло с разыменованием их.Например:

@that = &get_ktms_from_program(\@this, \@that);

Но, когда я пытаюсь разыменовать их, я получаю плохие новости!

    print "\nEntered get_lines_from_program sub\n"; 
    my ($lines_r, $parsed_r) = @_;
    print "@{$lines_r}\n";

Вывод:

Entered get_lines_from_program sub
ARRAY(0x81c20dc)

Итак, дляпо какой-то причине я не могу разыменовать этот массив тем же методом, который использовался ранее.Что дает?ТИА за помощь!

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

Это зависит от того, что вы делаете с теми, кто в ваших подводных лодках.Вот несколько заметок, которые могут помочь

Если вы передадите ссылку и будете работать со ссылкой

func(\@ary);
...
sub func {
    my ($ra) = @_;
    ...
    push @$ra, @some_values;  # changes @ary in the caller
}

, то вы только что изменили @ary в вызывающей стороне.

Однако, если вы создаете локальную копию в подпункте

sub func {
    my ($ra) = @_;
    my @local_ary = @$ra;
    ...
    return \@local_ary;    # return reference to brand new @local_ary
}

, тогда изменения на @local_ary не влияют на @ary в вызывающем абоненте (если только это не связано с возвратом курса -- перезаписывается им, или возвращается push, редактируемый на нем).

Другой момент: аргументы, передаваемые в массив, имеют псевдоним в @_, так что если в подпрограмме вы работаете с $_[0] (и т. д.) затем вы напрямую изменяете данные в вызывающей стороне.

Из того, что вы показываете, ясно, что у вас есть один элемент в @lines_r, который сам является ссылкой на массив.Как ты это понял, трудно понять, не увидев код.Одна возможность состоит в том, что вы вернули arrayref из некоторой функции, return \@local_ary, которую вы не разыменовали в вызывающей программе, а просто добавили ее в @this или @that (на что ссылается $list_r).


Несколько комментариев к коду в вопросе

& перед сабвуфером имеет тонкие эффекты, которые вам почти наверняка не нужны.Раньше он был нужен давным-давно, но теперь он не используется и не должен использоваться для «нормального» вызова.

Массивы передаются в подпункт по ссылке, что хорошо, так какизбегает возможного огромного количества копирования данных.Однако вы четко возвращаете список, так как он присваивается массивам.Если в этих массивах может быть много данных, лучше вернуть ссылку и разыменовать ее в вызывающей стороне

my $ra = func(...);   # func() returns an array reference
my @ary = @$ra;

или

my @ary = @{ func(...) };

Я бы рассмотрел всегда возвращая ссылку на массив с данными (в отличие от небольшого набора скалярных переменных, которые нужно вернуть в список, где выбор зависит только от предпочтений вызывающего).

Наконец, будьте очень, очень осторожны с тем, что выделать, если вы передадите массив по ссылке и назначите возврат этому же массиву.

0 голосов
/ 11 октября 2018

Вероятно, вы сохранили ссылку на этот массив в массиве где-нибудь.Это означает, что теперь у вас есть массив с одним элементом: ссылка на массив.(Ссылки, как вы вкладываете структуры данных в Perl; см. perllol ).Когда вы интерполируете этот массив в строку, печатается один элемент (ссылка на массив), и строковая форма ссылки на массив выглядит как строка, которую вы видели.Вместо этого сохраняйте ссылку на массив в скалярной переменной, где бы вы ее ни извлекали, которая может быть передана другим подпрограммам как есть.

use strict;
use warnings;

my $aref = sub_returning_aref();
other_sub($aref);

sub sub_returning_aref {
  my @stuff;
  return \@stuff;
}

sub other_sub {
  my ($aref) = @_;
  print "@$aref\n";
}

Ключ, который нужно помнить, заключается в том, что \@array возвращает ссылку, которая являетсяскалярное значение, которое затем можно использовать как любой другой скаляр, но для получения содержимого массива его необходимо разыменовать.

Data :: Dumper является хорошим основным инструментом для определения того, что именно выиметь в переменной при отладке.

use Data::Dumper;
print Dumper \@array;
...