Как объявить функцию, которая принимает типизированный параметр массива

#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 является an Array[Any] и @a.grep(*.Str) является a Seq , ни один из них не будет проходить для a Array[Str] .