Значения аргументов по умолчанию в подпрограммах

Я не знаю, как устанавливать аргументы по умолчанию для подпрограмм. Вот что я подумал:

sub hello {
  print @_ || "Hello world";
}

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

Я собирался сделать это:

sub hello {
  my $say = $_[0] || "Hello";
  my $to  = $_[1] || "World!";
  print "$say $to";
}

Но это много работы ... Должен быть способ попроще; возможно, лучший метод?

13
задан alex 24 May 2018 в 13:43
поделиться

8 ответов

Я делаю это с такими именованными аргументами:

sub hello {
    my (%arg) = (
        'foo' => 'default_foo',
        'bar' => 'default_bar',
        @_
    );

}

Я считаю, что Params :: Validate поддерживает значения по умолчанию, но это больше проблем, чем мне хотелось бы.

14
ответ дан 1 December 2019 в 17:58
поделиться

Обычно я делаю что-то вроде:

sub hello {
    my ($say,$to) = @_;
    $say ||= "Hello";
    $to ||= "World!";
    print "$say $to\n";
}

Обратите внимание, что, начиная с perl 5.10, вы можете использовать оператор « // = », чтобы проверить, определена ли переменная, а не просто ненулевое значение. (Представьте себе звонок hello ("0", "friend") , который при использовании вышеуказанного даст "Hello friend" , что может быть не тем, что вы хотели. Использование ] // = оператор вернет «0 друг» ).

12
ответ дан 1 December 2019 в 17:58
поделиться

Если вы посмотрите документацию Perl Best Practices : Значения аргументов по умолчанию от Damian Conway , то вы найдете несколько важных указывает, например:

  • Разрешить любые значения аргумента по умолчанию , как только @_ будет распакован.
  • Предполагается, что если у вас есть много значений по умолчанию, которые нужно настроить, самым чистым способом было бы вынести значения по умолчанию в таблицы, то есть хэш , а затем выполнить предварительную инициализацию хэша аргумента с этой таблицей.

Пример:

#!/usr/bin/perl
  use strict;
  use warning;
  my %myhash = (say => "Hello", to => "Stack Overflow");
  sub hello {
   my ($say, $to) = @_;
   $say =  $say ? $say : $myhash{say};
   $to =  $to ? $to : $myhash{to};
   print "$say $to\n";
  }
  hello('Perl');      # output :Perl Stack Overflow
  hello('','SO');     # output :Hello SO
  hello('Perl','SO'); # output :Perl SO
  hello();            # output :Hello Stack Overflow

Более подробный и полный пример см. В Perl Best Practices .

3
ответ дан 1 December 2019 в 17:58
поделиться

Attribute :: Default модуль на CPAN. Вероятно, чище, чем это, и позволяет избежать некоторых сложностей (например, что, если вы хотите передать false своей подпрограмме?).

Я также видел, как люди использовали my $ var = exists @_ [0]? shift: "Default_Value"; , но в документации Perl отмечается, что вызов существует в массивах устарел , поэтому я бы не рекомендовал его.

Фрагмент Attribute :: Default со страницы документа:

  sub vitals : Default({age => 14, sex => 'male'}) {
     my %vitals = @_;
     print "I'm $vitals{'sex'}, $vitals{'age'} years old, and am from $vitals{'location'}\n";
  }

   # Prints "I'm male, 14 years old, and am from Schenectady"
   vitals(location => 'Schenectady');
2
ответ дан 1 December 2019 в 17:58
поделиться

Для получения дополнительной информации см. Также Method :: Signatures :

func add($this = 23, $that = 42) {
    return $this + $that;
}
0
ответ дан 1 December 2019 в 17:58
поделиться

Поскольку Perl-механизм передачи аргументов подпрограммам представляет собой единый список, аргументы позиционны. Это затрудняет предоставление значений по умолчанию. Некоторые встроенные модули (например, substr ) обрабатывают это, упорядочивая аргументы в соответствии с вероятностью их использования - менее часто используемые аргументы появляются в конце и имеют полезные значения по умолчанию.

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

use 5.010;  # for //

sub hello {
    my %arg = @_;
    my $say = delete $arg{say} // 'Hello';
    my $to  = delete $arg{to}  // 'World!';
    print "$say $to\n";
}

hello(say => 'Hi', to => 'everyone');  # Hi everyone
hello(say => 'Hi');                    # Hi world!
hello(to  => 'neighbor Bob');          # Hello neighbor Bob
hello();                               # Hello world!

Примечание: оператор defined-or // был добавлен в Perl v5.10. Это более надежно, чем использование логического ИЛИ ( || ), поскольку оно не будет по умолчанию для логически ложных значений '' и 0 .

4
ответ дан 1 December 2019 в 17:58
поделиться

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

 sub hello {
печать @_ || "Привет мир";
}

И это отлично работает, если вам нужен только один аргумент.

Вы действительно пробовали этот код? Он напечатает количество аргументов или, если они не указаны, Hello World !
Причина этого в том, что || -оператор имеет приоритет и заставляет левую часть в скалярном контексте, таким образом уменьшая @_ до количества аргументов, которые вы предоставляете, а НЕ самих аргументов!
посмотрите perlop для получения дополнительной информации об операторах в Perl.

HTH,
Пол

1
ответ дан 1 December 2019 в 17:58
поделиться

Также взгляните на Метод::Подписи. Здесь используется Devel::Declare для предоставления дополнительного (необходимого!) сахара с ключевыми словами method и func.

Ниже приведен пример использования новой функции:

use Method::Signatures;

func hello ($say='Hello', $to='World!') {
    say "$say $to";
}

hello( 'Hello', 'you!' );    # => "Hello you!"
hello( 'Yo' );               # => "Yo World!"
hello();                     # => "Hello World!"

/I3az/

7
ответ дан 1 December 2019 в 17:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: