2013-05-28 2 views
6

У меня есть подпрограмма, которая возвращает хэш. Последние строки подпрограммы:Подпрограмма, которая возвращает хэш - разбивает ее на отдельные переменные

print Dumper(\%fileDetails); 
return %fileDetails; 

в этом случае самосвал печатает:

$VAR1 = { 
      'somthing' => 0, 
      'somthingelse' => 7.68016712043654, 
      'else' => 'burst' 
} 

Но когда я пытаюсь сбросить его вызов подпрограммы с этой линией:

print Dumper(\fileDetailsSub($files[$i])); 

Дампер отпечатков:

$VAR1 = \'somthing'; 
$VAR2 = \0; 
$VAR3 = \'somthingelse'; 
$VAR4 = \7.68016712043654; 
$VAR5 = \'else'; 
$VAR6 = \'burst'; 

Когда хэш сломан, я больше не могу его использовать. Почему это происходит? И как я могу сохранить правильную структуру при возврате подпрограммы?

Thanks, Mark.

+0

Ответ в '\\', который вы механически вставляете в свои вызовы Dumper() :-) –

ответ

9

В Perl нет такой вещи, как возвращение хэша.

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

Когда вы пишете

return %fileDetails; 

Это эквивалентно:

return ('something', 0, 'somethingelse', 7.68016712043654, 'else', 'burst'); 

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

my %result = fileDetailsSub(); 

Это работает, потому что хэш может быть инициализирован с списком пар ключ-значение. (Помните, что (foo => 42, bar => 43) это то же самое, как ('foo', 42, 'bar', 43).

Теперь, когда вы используете ссылочный обратный слэш оператор на хэш, как в \%fileDetails, вы получите хэш ссылку которая является скалярной точки на хэш.

Точно так же, если вы пишете \@array, вы получите ссылку на массив.

Но при использовании эталонного оператора на список, вы не получите ссылку на список (так как списки не являются переменными (они эфемерны), на них нельзя ссылаться.) Вместо этого, ссылка оператор распределяет над пунктами списка, так

\('foo', 'bar', 'baz'); 

делает новый список:

(\'foo', \'bar', \'baz'); 

(В этом случае мы получаем список полный скалярных ссылок.) И это то, что вы видите при попытке выполнить Dumper результаты вашей подпрограммы: ссылочный оператор, распределенный по списку элементов, возвращенных из вашего под.

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

return \%fileDetails; 

... 

my $details_ref = fileDetailsSub(); 
print Dumper($details_ref); 

# access it like this: 
my $elem = $details_ref->{something}; 
my %copy = %{ $details_ref }; 

Для большего удовольствия, см:

8

Почему бы не вернуть ссылку на хэш вместо этого?

return \%fileDetails; 

До тех пор, пока это лексическая переменная, это не будет усложнять работу с другими видами использования подпрограммы. Т.е .:

sub fileDetails { 
    my %fileDetails; 
    ... # assign stuff 
    return \%fileDetails; 
} 

Когда выполнение покидает подпрограмму, переменная выходит из области видимости, но данные, содержащиеся в памяти остается.

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

print Dumper \(qw(something 0 somethingelse 7.123 else burst)); 
0

В контексте списка Perl не различает хеш и список пар ключ/значение. То есть, если подпрограмма return с хешем, то, что она действительно возвращает, является списком (key1, value1, key2, value2...). К счастью, это работает в обоих направлениях; если взять такой список и назначить его хэш, вы получите точную копию оригинала:

my %fileDetailsCopy = subroutineName(); 

Но если он не будет нарушать другой код, то, вероятно, больше смысла иметь возвращение к югу ссылка на хэш вместо этого, как сказал TLP.

1

Вы не можете вернуть хеш напрямую, но perl может автоматически конвертировать между хэшами и списками по мере необходимости. Поэтому perl преобразует это в список, и вы захватываете его как список. то есть

Dumper(filedetail()) # list 
my %fd = filedetail(); Dumper(\%fd); #hash 
3

Функции Perl не могут возвращать хеши, только списки. Оператор return %foo сгладит %foo в список и возвращает сплющенный список.Чтобы получить возвращаемое значение, чтобы быть истолкована как хэш, вы можете присвоить его имя хэш

%new_hash = fileDetailsSub(...); 
print Dumper(\%new_hash); 

или cast it (не уверены, что это лучшее слово для него) с %{{...}} последовательности операций:

print Dumper(\%{ {fileDetailsSub(...)} }); 

Другой подход, как указывает TLP, заключается в возврате хеш-ссылки из вашей функции.