Рассмотрим эти подпрограммы, которые принимают один именованный параметр. Именованные параметры должны быть необязательными, и я не видел ничего сказать, что есть исключения.
Без ограничений типа нет проблем; именованный параметр не требуется. С типом ограничения, которое может принять объект типа (без аннотации, :U
и :_
), нет проблем.
Parameter '$quux' of routine 'quux' must be an object instance of type 'Int',
not a type object of type 'Int'. Did you forget a '.new'?
in sub quux at /Users/brian/Desktop/type.p6 line 16
in block <unit> at /Users/brian/Desktop/type.p6 line 37
При ограничении типа, которое требует определенного значения (аннотируется с помощью :D
), именованный параметр больше не является необязательным. То есть, с любым из других определений мне не нужно давать значение. При значении :D
я должен указать значение. Я бы предпочел не оставлять :D
, потому что значение, которое я хочу, должно быть определено.
Из Signatures docs:
Обычно ограничение типа проверяет, имеет ли значение принятое значение.
Но я не передаю никакой ценности. Я полагал, что эти ограничения будут иметь значение только для задания. Поскольку я не предоставляю явное значение для назначения, я ожидал, что не будет никакого назначения и не будет проблем. Это не так с Rakudo 2017.10. Это заставляет меня обходить это различными неприятными способами. Это связано с моим вопросом Является ли этот один аргумент или нет для блока Perl 6?, где я пытаюсь отличить нуль от одного аргумента.
Я мог бы обойти это, назначив значение по умолчанию, но в некоторых случаях значения по умолчанию не имеют смысла. А Bool
легко, например, но какой определенный Int
будет соответствовать? Как бы то ни было, это было бы волшебным значением, которое усложняло бы и отвлекало бы код. Я сделал это с помощью Имеет ли Perl 6 Infinite Int, но мне это не удается, потому что Inf
работает как допустимое значение в этом случае.
sub foo ( :$foo ) {
put $foo.defined ?? 'foo defined' !! 'foo not defined';
}
sub bar ( Int :$bar ) {
put $bar.defined ?? 'bar defined' !! 'bar not defined';
}
sub baz ( Int:U :$baz ) {
put $baz.defined ?? 'baz defined' !! 'baz not defined';
}
sub quux ( Int:D :$quux ) {
put $quux.defined ?? 'quux defined' !! 'quux not defined';
}
sub quack ( Int:_ :$quack ) {
put $quack.defined ?? 'quack defined' !! 'quack not defined';
}
foo();
foo( foo => 2 );
bar();
bar( bar => 2 );
baz();
baz( baz => Int );
quack();
quack( quack => 2 );
quux( quux => 2 );
quux();