A Capture
имеет два слота, содержащих массив уровня VM (позиционные аргументы) и хэш (именованные аргументы). Он довольно дешево сконструирован и - поскольку аргументы стиля |c
довольно часто встречаются в различных элементах внутреннего интерфейса - был хорошо оптимизирован. Поскольку параметр захвата нарушает как позиционные, так и именованные аргументы, любые именованные аргументы будут игнорироваться. Это, вероятно, не является большой проблемой для методов, где необязательные именованные аргументы будут все равно тихо помещены в %_
, но это может быть соображением, если использовать эту конструкцию для sub
, поскольку это не чистая оптимизация: она меняет поведение.
Случай **@c
выделяет Array
, а затем выделяет контейнер Scalar
для каждого из переданных значений, помещая их в контейнеры Scalar
и эти контейнеры Scalar
в Array
. Это разумное количество дополнительной работы.
Есть еще один случай, который здесь не рассматривается, а именно:
sub test3(**@c is raw){
1;
}
Это помещает List
в @c
и устанавливает его элементы для прямой ссылки на то, что было передано. Это немного дешевле, чем в случае без is raw
. Теоретически, он мог бы работать так же хорошо, если не лучше, как параметр захвата, такой как |c
; возможно, просто нужен кто-то, работающий над компилятором, чтобы понять, почему он этого еще не делает.
Таким образом, если не заботиться о принудительной детализации и / или иметь изменяемые Array
входящих аргументов, то добавление is raw
, вероятно, является лучшим выбором для оптимизации, чем выбор параметра захвата: семантика обработки аргументов ближе, это уже немного быстрее, позволит создавать более естественный код и в будущем может стать таким же быстрым, как если бы не быстрее, чем |c
.