Perl: есть ли что-то лучше, чем $ var = $ _ ;? - PullRequest
3 голосов
/ 18 ноября 2011

Это не важный вопрос, и я его знаю, buuut $var = $_; выглядит просто отстойно, есть ли лучший (более короткий) способ выполнить это назначение?

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

Ответы [ 9 ]

8 голосов
/ 18 ноября 2011

В новой лексической области вы можете локализовать $ _, что предотвратит любые изменения в этой области, влияющие на ее значение вне этой области.

Для пояснения необходим пример:

$_ = 1;
say;
{ # open a new scope
    local $_ = 3;
    $_++;
    say;
} # close the scope
say;

Это должно вывести

1
4
1

Я считаю, что это бесценно для написания функций, которые широко используют $ _ внутри, потому что мне не нравится, когда они затирают $ _ в окружающей их области.Однако вы также можете использовать его, чтобы «отложить» переменную и некоторое время поработать с новой версией.

6 голосов
/ 18 ноября 2011

Во многих случаях это не нужно.Например:

foreach my $var (@array) {
  dostuff($var);
}

или

my $var;
while ($var = <>) {
  chomp($var);
  dostuff($var);
}

или

while (<>) {
  chomp;
  dostuff($_);
}
4 голосов
/ 19 ноября 2011

По запросу ОП я публикую свой комментарий в качестве ответа.

Похоже, что вы спрашиваете, есть ли лучший или короткий способ написать $var = $_ (или получить эту функциональность). Для меня это довольно странная просьба, потому что:

  • $var = $_ уже настолько короток, насколько это возможно, а
  • нет лучшего способа сделать это назначение, чем использование равных знак.
4 голосов
/ 18 ноября 2011

Почему вы хотите $var = $_? Просто используйте $_ или передайте его в качестве параметра функции, в функции вызовите его $var.

3 голосов
/ 18 ноября 2011

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

apply {CODE} LIST

apply a function that modifies $_ to a shallow copy of LIST and returns the copy

    print join ", " => apply {s/$/ one/} "this", "and that";
    > this one, and that one

Вот реализация одного из моих модулей:

http://search.cpan.org/perldoc?List::Gen#apply

3 голосов
/ 18 ноября 2011

Использование local:

$_ = 1;
{
    local $_ = 2;
    say;           # prints 2
}
say;               # prints 1
3 голосов
/ 18 ноября 2011

Все хорошие ответы. Я хотел бы поделиться еще одним примером, связанным с «просто используйте $_», как сказал @awm.

10 минут назад я просто написал эти строки:

sub composite
{
   foreach my $element (@_)
   {
     # do something ...
   }
}

sub simple
{
  &composite( $_[ int rand @_ ] );
}

, который является Perl Golf ( cit. ), не рекомендуется использовать вообще.

Если вам нужно сохранить $_ в другом месте и через некоторое время использовать его первоначальное значение, вам следует выполнить присвоение.

2 голосов
/ 18 ноября 2011

Вы можете использовать map для создания нового массива путем преобразования существующего массива:

my @squares = map { $_**2 } 1..10 ;         # 1,4,9,16,25,36,49,64,81,100

my @after   = map { process($_) } @before ; # @before unchanged, @after created
1 голос
/ 18 ноября 2011

Похоже, вы хотели бы получить доступ к стеку pushdown локальных значений $_. Это может быть крутым. Тем не менее, вы можете сделать что-то , как это самостоятельно. Я могу показать вам основы.

our @A;           # declare a stack
*::A = *A{ARRAY}; # "Globalize" it if necessary.

sub pd (&;@) # <- block operator prototype indicating language sugar
{ 
    # I would have really preferred to do a push here.
    local @A = ( @A, $_ ); 
    # pull the block argument
    my $block = shift;
    # Ensure at least one execution
    @_ = $_ unless @_;
    # + Scalar behavior option #1
    # return $block->( local $_ = shift ) if not wantarray // 1; 
    # + Scalar behavior option #2
    # unless ( wantarray // 1 ) {
    #     my $result;
    #     while ( @_ ) { 
    #         local $_ = shift;
    #         return $result if defined( $result = $block->( $_ ));
    #     }
    #     return;
    # }
    # Standard filter logic
    return map { $block->( $_ ) } @_;
}

И вот простое понимание списка, основанное на этом:

my @comp 
    = map { pd { pd { join '', @A[-2,-1], $_ } qw<g h> } qw<d e f>; } qw<a b c>
    ;

Вот @comp:

@comp: [
         'adg',
         'adh',
         'aeg',
         'aeh',
         'afg',
         'afh',
         'bdg',
         'bdh',
         'beg',
         'beh',
         'bfg',
         'bfh',
         'cdg',
         'cdh',
         'ceg',
         'ceh',
         'cfg',
         'cfh'
       ]
...