Никаких условий гонки или что-либо, что связано с тем, является ли @_ «определенным» или нет, просто вопрос порядка операций.
Индексы для среза списка оцениваются до того, как список будет разрезан.(Документация не гарантирует это так или иначе.) Таким образом, на первой итерации @_ пусто, и аргумент для rand равен 1 | 0 (= 0).Исторически rand (0) вела себя как rand (1), хотя теперь это задокументировано как подверженное изменениям.Таким образом, индекс на первой итерации равен> = 0 и <1, и неявный int индексации принимает его за 0. </p>
Выборка элемента массива ([@_=%hash]->[1|rand@_]
) не имеет аналогичной проблемы, посколькуон оценивает индекс после операнда массива.Срез массива (@{[@_=%hash]}[1|rand@_]
), с другой стороны, ведет себя так же, как срез списка.
Сравнение:
Срез списка:
$ perl -MO=Concise,-exec -e'(@_=%hash)[1|rand@_]'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark s
4 <$> const[IV 1] s
5 <#> gv[*_] s
6 <1> rv2av[t7] sK/1
7 <1> rand[t8] sK/1
8 <2> bit_or[t9] sK
9 <0> pushmark s
a <0> pushmark s
b <#> gv[*hash] s
c <1> rv2hv[t4] lK/1
d <0> pushmark s
e <#> gv[*_] s
f <1> rv2av[t2] lKRM*/1
g <2> aassign[t5] lKS/COMMON
h <2> lslice vK/2
i <@> leave[1 ref] vKP/REFC
-e syntax OK
Срез массива:
$ perl -MO=Concise,-exec -e'@{[@_=%hash]}[1|rand@_]'
1 <0> enter
2 <;> nextstate(main 2 -e:1) v:{
3 <0> pushmark s
4 <$> const[IV 1] s
5 <#> gv[*_] s
6 <1> rv2av[t8] sK/1
7 <1> rand[t9] sK/1
8 <2> bit_or[t10] sK
9 <0> pushmark s
a <0> pushmark s
b <#> gv[*hash] s
c <1> rv2hv[t4] lK/1
d <0> pushmark s
e <#> gv[*_] s
f <1> rv2av[t2] lKRM*/1
g <2> aassign[t5] lKS/COMMON
h <@> anonlist sK*/1
i <1> rv2av[t6] sKR/1
j <@> aslice vK
k <@> leave[1 ref] vKP/REFC
-e syntax OK
Элемент массива:
$ perl -MO=Concise,-exec -e'[@_=%hash]->[1|rand@_]'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark s
4 <0> pushmark s
5 <#> gv[*hash] s
6 <1> rv2hv[t4] lK/1
7 <0> pushmark s
8 <#> gv[*_] s
9 <1> rv2av[t2] lKRM*/1
a <2> aassign[t5] lKS/COMMON
b <@> anonlist sK*/1
c <1> rv2av[t10] sKR/1
d <$> const[IV 1] s
e <#> gv[*_] s
f <1> rv2av[t7] sK/1
g <1> rand[t8] sK/1
h <2> bit_or[t9] sK
i <2> aelem vK/2
j <@> leave[1 ref] vKP/REFC
-e syntax OK