2016-05-27 3 views
4

Я работаю с Moose пакетами в Perl, которые используют MooseX::Params::Validate для определения интерфейса. Эти интерфейсы, как правило, довольно гибкие и позволяют использовать несколько необязательных параметров. К сожалению, это Perl, поэтому типы возвращаемых данных будут меняться в зависимости от дополнительных параметров, и есть преимущество для передачи необязательных параметров в большинстве случаев, когда они определены в вызывающем. Различные методы, экспортируемые из MooseX::Params::Validate, используются в этой кодовой базе, поэтому из-за различных способов обработки пакета undef параметры, которые я не могу передать, будут в любом случае изящными. Я, как правило, использую следующий метод, но в обзорах это очень много, и я хотел бы спросить, есть ли другой способ достичь этой гибкости.Условный параметр, передаваемый с MooseX :: Params :: Validate

use strict; 
use warnings; 

my $bar; 

Foo->foo({ 
    foo => 'I, Foo need a VERY flexible interface. ', 
    $bar ? (bar => $bar) :() 
}); 

$bar = "Very flexible..."; 

Foo->foo({ 
    foo => 'I, Foo need a VERY flexible interface. ', 
    $bar ? (bar => $bar) :() 
}); 

package Foo; 

use Moose; 
use MooseX::Params::Validate; 

sub foo { 
    my $self = shift; 
    my ($foo, $bar) = validated_list(
     \@_, 
     foo => { isa => 'Str' }, 
     bar => { isa => 'Str', optional => 1 }, 
    ); 

    print $foo . $bar . "\n"; 
} 

1; 

Тройная оператор, чтобы проверить переменные defined состояния является то, что всегда оставляет меня, желая вариант пАРАМЕТР // типа, но я не могу увидеть где-нибудь этот тип операции поддерживается.

Ответы для caller предпочтительнее, так как я не хочу (не будет) изменять интерфейс различных пакетов, но я открыт для ответов, показывающих методы обработки undef значений параметров, передаваемых также.

+0

Для абонентов, ваш "идиома" кажется laborous [и, что более важно, к ошибкам]. Как насчет замены тройной с более простой вспомогательной функцией, например: 'sub defme {my (@arr); push (@arr, $ _ [0], $ _ [1]), если ($ _ [1]); @arr; } '? Затем у вас есть 'defme (" bar ", $ bar)' вместо тройной. Или, в конструкторе, делайте '//' или '// =' при необходимости _before_ вызывая 'validated_list', так как первый arg всегда указывает на temp? –

+0

@CraigEstey вы можете объяснить, насколько более склонны к ошибкам и кропотливости (я был в основном обеспокоен читабельностью) и как работает ваше решение, потому что я не вижу, как это применимо? – MattSizzle

+0

Моя функция AFAICT делает то, что делает trernary - создает массив, который либо заполняется символом '($ sym, $ val)', либо пустым. И, IMO, 'defme (« bar », $ bar)' более читабельна, чем [более длинная] '$ bar? (bar => $ bar):() '. Вызов fnc короче и проще троичного синтаксиса. И, при необходимости, вы можете добавить debug printfs в fnc. Но, вероятно, лучше всего, чтобы все вызывающие абоненты просто делали '(bar => $ var)' и позволяли 'foo' справляться с этим, а не возлагать ответственность на вызывающих. Даже если вы все еще хотите тройной, 'foo' все равно нуждается в защите, так или иначе. Итак, если проверить, почему бы и не исправить? –

ответ

0

Как сказал Craig Estey в своем комментарии, я считаю, что имеет смысл просто перейти к вариантам вашей функции и не заботиться о том, являются ли они неопределенными или нет. Вместо этого разделите неопределенные хеш-ключи как шаг предварительной обработки перед вызовом MooseX::Params::Validate::validated_list(). Например:

use strict; 
use warnings; 

my $bar; 

Foo->foo({ 
    foo => 'I, Foo need a VERY flexible interface. ', 
    bar => $bar 
}); 

package Foo; 

use Moose; 
use MooseX::Params::Validate(); 

sub foo { 
    my $self = shift; 

    my ($foo, $bar) = validated_list(
     \@_, 
     foo => { isa => 'Str' }, 
     bar => { isa => 'Str', optional => 1 }, 
    ); 

    $bar //= 'undef'; # Just to avoid printing warning: Use of uninitialized value 
    print $foo . $bar . "\n"; 
} 

sub validated_list { 
    for (keys %{ $_[0]->[0] }) { 
     delete $_[0]->[0]{$_} if !defined $_[0]->[0]{$_}; 
    } 
    return MooseX::Params::Validate::validated_list(@_); 
} 
1; 
+0

Пакеты Moose - это черный ящик для моего вопроса – MattSizzle

+0

@MattSizzle Я не уверен, что вы подразумеваете под« черным ящиком ». Для меня «черный ящик» означает, что вы ничего не можете изменить внутри. Вы можете общаться только через API. Не могли бы вы объяснить, что вы имеете в виду? –

0

Тип Maybe может быть то, что вы ищете. Обычно MooseX :: Params :: Validate делает не разрешает передачу undef для вещей, которые нравятся Str, заставляя вас использовать тернар, чтобы условно передать или не передать его. Необязательная переменная будет undef в любом случае в подпрограмме, но, возможно, это облегчит для вызывающего пользователя просто пройти через переменные, которые у них есть (которые могут быть или не определены).

sub foo { 
    my $self = shift; 
    my ($foo, $bar) = validated_list(
     \@_, 
     foo => { isa => 'Str' }, 
     bar => { isa => 'Maybe[Str]', optional => 1 } 
    ); 

    print $foo . $bar . "\n"; 
} 

Используя Возможно [Str], он теперь принимает значение UNDEF и вы можете справиться с этим UNDEF, как вы считаете нужным в вашей подпрограмме.

Maybe[`a] accepts either `a or undef. 

http://search.cpan.org/dist/Moose-2.0604/lib/Moose/Manual/Types.pod