#raku
#raku
Вопрос:
Допустим, я хочу объявить функцию, параметром которой является массив строк:
sub process-string-array(Str[] stringArray) # invalid
{
...
}
Как бы я это сделал?
Ответ №1:
Это зависит от сигила, который вы хотите использовать:
sub process-string-array(Str @array) { ... } # @-sigil
sub process-string-array(Array[Str] $array) { ... } # $-sigil
Обратите внимание, что для этого нужно быть осторожным при передаче объявленного массива Str, что означает, что adhoc-массивы должны будут передаваться с типизированным объявлением:
my Str @typed-array = <a b c>;
process-string-array <a b c>; # errors
process-string-array @typed-array; # typed array in
process-string-array Array[Str].new: <a b c>; # adhoc typed array
Если вы не хотите иметь дело с такими типизированными массивами, вы можете использовать предложение для принятия любого типизированного массива, который содержит только элементы (что часто проще в использовании IME) where
Any
Str
:
sub process-string-array(@array where .all ~~ Str) { ... }
Однако для этого (как напоминает jnthn в комментариях) требуется проверка типа каждого элемента (так что O (n) perf по сравнению с O (1)), поэтому в зависимости от того, насколько чувствительны к производительности вещи, это может стоить дополнительного шума кода. По предложению Брэда, вы могли multi
бы это сделать, чтобы ускорить процесс при вводе массива и вернуться к более медленному методу, когда нет.
multi sub process-string-array(Int @array) {
... # actual processing here
}
multi sub process-string-array(@array where .all ~~ Str) {
process-string-array Array[Int].new: @array
}
Комментарии:
1. Я попробовал первый вариант
sub name(Str @array)
, но у меня были ошибки, потому что я передавал нетипизированный массив, как и написано в вашем предупреждении! Что касаетсяwhere
предложения, я предполагал, что что-то вроде вашего примера будет работать, но не пробовал, потому что я хотел «фактические» объявления типизированных массивов. Спасибо.2. Обратите внимание, что проверка типизированного массива
O(1)
зависит от размера массива, ноwhere
подход заключается вO(n)
том, что вы действительно не хотите делать это везде, где важна производительность.3. @JonathanWorthington Спасибо за напоминание: обычно я пытаюсь упомянуть компромиссы, но в данном случае совершенно забыл (я обычно использую where в неряшливых конструкциях, где типизированный массив невозможен. (Хотя я еще не проверял, позволит ли новая система принуждения vrurg
:( Int() @foo)
4.Вы могли бы использовать несколько подмен.
multi process-string-array(@array where .all ~~ Str) { samewith( Array[Str].new: @array )}
multi process-string-array(Str @array) { ... }
5. @jubilatious1:
grep
выберет элементы, которые естьInt
, и через другие (where
не изменяет массив, если он найдет не-Int
, это предотвратит вызов метода). В вашем примере@a
является anArray[Any]
и@a.grep(*.Str)
является aSeq
, ни один из них не будет проходить для aArray[Str]
.