2010-01-14 2 views
2

Эй. В Python я могу это сделать:Как вернуть список в качестве ссылки на массив в Perl?

def fnuh(): 
    a = "foo" 
    b = "bar" 
    return a,b 

Могу ли я вернуть список в такой же элегантный способ в Perl, особенно когда тип возврата подпрограммы должна быть ссылка на массив?

Я знаю, что могу сделать

sub fnuh { 
    my $a = "foo"; 
    my $b = "bar"; 
    my $return = []; 
    push (@{$return}, $a); 
    push (@{$return}, $b); 
    return $return; 
} 

Но я держу пари, что есть лучший способ сделать это в Perl. Ты знаешь это?

+2

Будьте осторожны, о различии между списками и массивами. Это область, которая вызывает много путаницы. Понимание различий важно для понимания того, как работает контекст. См. Http://perldoc.perl.org/perlfaq4.html#What-is-the-difference-between-a-list-and-an-array%3f и http://www.perlmonks.org/?node_id= 130861 и http://www.perlmonks.org/?node_id=719099 для обсуждения. – daotoad

+2

Спасибо, я думал, что это должно было включать списки, но на самом деле решение, которое мне больше всего нравится, - return [$ a, $ b] - не связано с ним. Если вы знаете, как лучше сформулировать намерение вопроса, дайте мне знать. – 0x89

+0

Ваш вопрос в порядке. В большинстве языков нет реального различия между списком и массивом. Perl делает различие. Список - упорядоченная группа значений.Массив - это переменный тип данных, который содержит упорядоченный набор значений, доступных по индексу. Ваш предпочтительный ответ делает * точно * то, что вы просили. Я просто пытался подчеркнуть различие между массивами и списками. Это тонкая вещь, но получение ее действительно помогает понять, как контекст работает в Perl. – daotoad

ответ

7

Несомненно, просто пощечины \ перед списком, чтобы вернуть ссылку.

Или создайте новый массив с [ list elements ].

В вашем примере,

sub f1 { 
    my $a = "foo"; 
    my $b = "bar"; 
    return [ $a, $b ]; 
} 

sub f2 { 
    my $a = "foo"; 
    my $b = "bar"; 
    push @return, $a, $b; 
    return \@return; 
} 

Пожалуйста, см perldoc perlreftut и perldoc perlref для больше о ссылках. Существует также кулинарная книга данных по perldoc perldsc.

Вы также можете прочитать этот вопрос в perlfaq (спасибо Брайно): "What's the difference between a list and an array?"

+6

Второй способ, которым вы определенно хотите объявить '@ return' с' my', иначе он станет глобальным, что не так хорошо. – Dan

+2

"# последнее выражение возвращается автоматически, не нужно быть явным" - в связи с этим мне нравится python лучше. Из «zen of python» второй оператор: Явный лучше, чем неявный. Так что я бы предпочел: return [$ a, $ b]; – 0x89

+2

Я предпочитаю всегда делать явные возвращения. Нет ничего плохого в добавлении немного ясности. Особенно в Perl. :) – friedo

6

Python автоматически упаковывает и распаковывает кортежи вокруг присвоения имитирующих списков. В Perl вы можете написать его таким же образом, возвращая список.

sub fnuh { 
    my $a = 'foo'; 
    my $b = 'bar'; 
    $a, $b 
} 

затем использовать результат:

my ($x, $y) = fnuh; 

или если вам нужна ссылка:

my $ref = [ fnuh ]; 
+0

Мне нравится простота этого ответа. Кроме того, 'wantarray'. –

+0

еще несколько педантизм: Perl Best Practices, глава 2: макет кода, точка с запятой: «Поместите точку с запятой после каждого утверждения». Глава 4: Ценности и выражения, списки: «Parenthesize every raw list». Минималистский во мне любит краткий синтаксис. – 0x89

+0

Perl Best Practices - это не Святая Библия. Это то, что любит Дамиан. Это не значит, что вам нужно это делать. См. Мое интервью с ним: http://www.theperlreview.com/Interviews/damian-bpp-20050622.html –

-1

Вы можете получить ту же функцию, Python, явно испытывая хочет ли контекст a массив с функцией wantarray.

sub fnuh { 
    my $a = 'foo'; 
    my $b = 'bar'; 
    return wantarray ? ($a, $b), [ $a, $b ]; 
} 

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

sub pack_list { 
    my $want = wantarray; 
    return unless defined $want; # void context 
    return $want ? @_ : \@_; 
} 

Затем вызовите его следующим образом:

return pack_list($a, $b); 
+1

Работа с контекстами в Perl - лучший способ стрелять в ногу. –

+0

@ Hynek -Pichi- Vychodil: Я не уверен, почему ты так говоришь. * Контекст * - одна из вещей, которые мне больше всего нравятся в Perl.Когда я работаю на Java, мне часто жаль, что я не могу сделать то же самое без дополнительной передачи параметров и перегрузки. * Если * вы не знакомы с контекстом, это может сбить с толку. – Axeman

Смежные вопросы