Ссылки лучше возвращают значения в функциях Perl? - PullRequest
10 голосов
/ 15 марта 2011

Каковы плюсы и минусы возврата массива или хеша по сравнению с возвратом ссылки на него?

Есть ли влияние на память или время выполнения?

Каковы функциональные различия между ними?

sub i_return_an_array
{
    my @a = ();
    # push things in @a;
    return @a;
}

sub i_return_a_ref
{
    my @a = ();
    # push things in @a;
    return \@a;
}

my @v = i_return_an_array();
my $v = i_return_a_ref();

Ответы [ 5 ]

9 голосов
/ 15 марта 2011

Влияние на производительность больше заметно , когда массив становится больше , но только на 50% для perl 5.10.

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

#! /usr/bin/perl
use Benchmark;

sub i_return_an_array
{
    my @a = (1 .. shift);
    # push things in @a;
    return @a;
}

sub i_return_a_ref
{
    my @a = (1 .. shift);
    # push things in @a;
    return \@a;
}

for my $nb (1, 10, 100, 1000, 10000) {
        Benchmark::cmpthese(0, {
                "array_$nb" => sub { my @v = i_return_an_array($nb); },
                "ref_$nb" => sub { my $v = i_return_a_ref($nb); },
        });
}

возвращает:

            Rate   ref_1 array_1
ref_1   702345/s      --     -3%
array_1 722083/s      3%      --
             Rate array_10   ref_10
array_10 230397/s       --     -29%
ref_10   324620/s      41%       --
             Rate array_100   ref_100
array_100 27574/s        --      -47%
ref_100   52130/s       89%        --
             Rate array_1000   ref_1000
array_1000 2891/s         --       -51%
ref_1000   5855/s       103%         --
             Rate array_10000   ref_10000
array_10000 299/s          --        -48%
ref_10000   578/s         93%          --

В других версиях Perl цифры могут отличаться.

9 голосов
/ 15 марта 2011

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

Функциональное различие между ними заключается просто в том, работаете ли вы с результатом как массив / хэш или как массивref / hashref.Некоторые люди считают ссылки гораздо более громоздкими для работы;лично я не считаю это существенным отличием.

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

Возвращаясь к вопросу о названии, я считаю, что наиболее важным фактором при возвращении списков и ссылок является то, что вы должны быть последовательными, чтобы вам не приходилось тратить свое время на запоминание того, какие функции возвращают массивы / хэши, а какие - ссылки.Учитывая, что ссылки в некоторых ситуациях лучше, и, по крайней мере для меня, ссылки никогда не оказываются значительно хуже, я предпочитаю стандартизировать всегда возвращать массивы / хэши в виде ссылок, а не списков.

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

5 голосов
/ 15 марта 2011

Что касается интерфейса, возвращение массива позволяет вам проще обрабатывать его с помощью таких карт, как карта и grep, не прибегая к @{bletchorousness}.

Но с хешами часто полезнее возвращатьссылка, потому что тогда вы можете делать умные вещи, такие как my $val = function->{key} без необходимости присваивать промежуточную переменную.

2 голосов
/ 15 марта 2011

Краткий ответ: это зависит от размера того, что вы возвращаете. Если он маленький, вы можете вернуть весь массив.

Подробнее см. Вопрос переполнения стека Неэффективен ли возврат целого массива из подпрограммы Perl? .

1 голос
/ 15 марта 2011

Обратите внимание, что на самом деле невозможно вернуть массив или хеш из функции. Единственное, что может вернуть функция - это список скаляров. Когда вы говорите return @a, вы возвращаете содержимое массива.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...