2013-11-29 4 views
2

Это обычная практика, чтобы использовать самостоятельно, ссылающиеся на анонимные функции переменной области видимости и т.д. в JavaScript:Является ли хорошей практикой использовать самоназывающую анонимную функцию в Perl?

;(function() { 
    ... 
})(); 

Это хорошая практика, чтобы использовать такие функции в Perl?

(sub { 
    ... 
})->(); 

Или лучше по какой-либо причине использовать основную подпрограмму?

sub main { 
    ... 
} 

main(); 

ответ

6

Perl имеет лексические механизмы обзорного JS испытывает недостаток. Вы лучше просто заключая код, который вы хотите как-то в области видимости блока, например .:

{ 
    my $localvar; 
    . . . 
} 

В этом случае $localvar будет полностью невидимым вне этих скобок; то есть также и тот же механизм можно использовать для локализации встроенных переменных, таких как $/:

{ 
    local $/ = undef; 
    #reading from a file handle now consumes the entire file 
} 
#But not out here 

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

В perl наилучшей практикой является помещение вещей в субтитры, когда это имеет смысл; когда это не имеет смысла или излишне усложняет код, лексические блоки обеспечивают обзор; если вам нужны анонимные подпрограммы (как правило, для обратных вызовов или аналогичных), то вы можете сделать my $subref = sub { . . . }; или даже просто приклеить к югу заявления непосредственно в качестве аргумента функции: do_something(callback => sub { . . . });

Примечание: смотри также ysth's answer для ресурсов, связанных с преимущества в самоназывающие анонимные субтитры.

3

Это не неслыханно, но не является общим. Чтобы ограничить переменный объем временно, это гораздо чаще использовать блок с my объявлением переменным:

... 
{ 
    my $local_variable; 
    ... 
} 
4

Поскольку perl предоставляет лексически измененные переменные (и, начиная с 5.18, лексически названные подмножества), для этого нет никакой причины.

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

$ perl -MDevel::Peek -wle'sub { my $x; Dump $x; $x = 42 }->() for 1..2' 
SV = NULL(0x0) at 0x944a88 
    REFCNT = 1 
    FLAGS = (PADMY) 
SV = IV(0x944a78) at 0x944a88 
    REFCNT = 1 
    FLAGS = (PADMY) 
    IV = 42 
$ perl -MDevel::Peek -wle'my $y; sub { $y if 0; my $x; Dump $x; $x = 42 }->() for 1..2' 
SV = NULL(0x0) at 0x259d238 
    REFCNT = 1 
    FLAGS = (PADMY) 
SV = NULL(0x0) at 0x259d220 
    REFCNT = 1 
    FLAGS = (PADMY) 

Хотя, если вы не обеспокоенный памятью, это было бы недостатком.

2

В Javascript, самоосуществляющиеся функции имеют два применения:

  1. видимость переменная. Объявления var поднимаются в область первой закрывающей функции или в глобальную область.Поэтому

    function() { 
        if (true) { 
        var foo = 42 
        } 
    } 
    

    такого же, как

    function() { 
        var foo 
        if (true) { 
        foo = 42 
        } 
    } 
    

    - часто нежелательный эффект.

  2. Заявления об уровне выражения. Иногда вам нужно несколько операторов для вычисления чего-то, но вы хотите сделать это внутри выражения.

    largeObject = { 
        ..., 
        // sum from 1 to 42 
        sum: (function(n){ 
        var sum = 0; 
        for(var i = 1; i <= n; i++) 
         sum += i; 
        return sum; 
        })(42), 
        ..., 
    }; 
    

Perl, нет необходимости для самостоятельного вызова функций в качестве механизма обзорного, поскольку новая область вводятся с помощью любой фигурной скобки. Голый блок всегда разрешен на уровне оператора:

... 
my $foo = 10; 
{ 
    my $foo = 42; 
} 
$foo == 10 or die; # lives 

Perl уменьшило необходимость самоосуществляющихся функций для представления отчетности в выражение из-за do BLOCK встроенной команды:

%large_hash = (
    ..., 
    sum => do { 
    my $sum = 0; 
    $sum += $_ for 1 .. 42; 
    $sum; 
    }, 
    ..., 
); 

Однако вы иногда хотят короткого замыкания в таком блоке. Поскольку return выходит из окружающей подпрограммы (а не блока), он может быть весьма полезен здесь. Например, в памятной функции:

# moronic cached division by two 
my %cache; 
sub lookup { 
    my $key = shift; 
    return $cache{$key} //= sub { 
    for (1 .. 100) { 
     return $_ if $_ * 2 == $key 
    } 
    return; 
    }->(); 
} 
Смежные вопросы