Raku中匿名状态变量$与主题变量$_的行为差异解析
匿名状态变量
$与主题变量$_在Raku级数生成中的行为差异 问题场景
2020年1月编写的Raku代码,用匿名状态变量$生成数学级数时结果正确,但替换为主题变量$_后输出异常。
原代码(正确)
my @a = ( 1, { ([+] 1 .. ++$ ) / [×] 1 .. ++$ } ... Inf)[^7]; say @a.join(' + ') ~ "=" ~ [+] @a;
正确输出
1 + 1 + 1.5 + 1 + 0.416667 + 0.125 + 0.029167=5.070833
替换后代码(异常)
my @a = ( 1, { ([+] 1 .. ++$_ ) / [×] 1 .. ++$_ } ... Inf)[^7]; say @a.join(' + ') ~ "=" ~ [+] @a;
异常输出
1 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5 + 0.5=4
差异原因
匿名状态变量
$的行为
Raku中单独使用的$是匿名状态变量,它的状态会在每次调用所在代码块时保留,不会被重置。在序列生成场景中,每次调用生成块时,++$会让这个变量持续自增,从而生成递增的数值范围,计算出符合预期的级数项。主题变量
$_的行为
在Raku的序列生成器代码块中,$_默认绑定的是序列的前一个元素。当你将$替换为$_后,++$_实际上是直接修改序列的前项值:- 第一次调用生成块时,
$_绑定第一个元素1,两次++$_会将其修改为3,计算得到(1+2)/(1×2×3) = 3/6 = 0.5,这就是第二个元素的来源。 - 后续每次调用生成块时,
$_绑定的是前一个元素0.5,++$_将其修改为1.5,但1 .. 1.5的整数范围仅包含1,求和与乘积结果都是1,因此每次生成的项都是1/1 = 0.5,最终导致后续输出全部为0.5。
- 第一次调用生成块时,
总结
二者的核心差异在于:$是独立的持久化状态变量,用于跟踪级数的项数;而$_是序列前项的绑定变量,修改它会破坏序列的原有逻辑,导致生成的项不符合预期。
内容的提问来源于stack exchange,提问作者Lars Malmsteen
相关产品推荐
相关产品推荐

