Raku中数学序列打印优化:移除首元素及idiomatic代码改造问询
嘿,咱们来搞定这两个Raku的小问题:
问题1:移除输出中的第一个元素(a0 = 0)
有几种超简便的方法,选哪种看你需求:
直接跳过第一个元素的循环
在遍历的时候用skip(1)直接丢掉第一个键值对,原判断逻辑完全不用改,非常直观:my @seq = my $a=0, {++$a} ... *; for @seq[^10].pairs.skip(1) { state $f=0; ($_.key < 4 or $_.key > 7) ?? say "a{_.key} = " ~ $_.value !! (say "..." if $f ne 1; $f=1) }在循环内直接跳过第一个索引
加一行next if $^k == 0,遇到第一个元素直接跳过,代码改动极小:my @seq = my $a=0, {++$a} ... *; for @seq[^10].kv { next if $^k == 0; # 跳过a0 state $f=0; ($^k < 4 or $^k > 7) ?? say "a$^k = " ~ $^v !! (say "..." if $f ne 1; $f=1) }调整序列切片范围
直接从索引1开始取序列,循环只处理@seq[1..9],不过注意这里的kv索引会变成0-8,要对应调整判断条件(比如把$^k <4改成$^k <3),适合不需要保留原索引的场景:my @seq = my $a=0, {++$a} ... *; for @seq[1..9].kv { state $f=0; ($^k < 3 or $^k > 6) ?? say "a{+$^k+1} = " ~ $^v !! (say "..." if $f ne 1; $f=1) }
问题2:改写成更符合Raku惯用风格的代码
原代码的逻辑没问题,但可以更简洁可读,更贴合Raku的“表达性优先”理念:
首先简化序列生成
Raku的整数序列可以直接写0 ... *,不用手动声明$a和递闭包,完全等价:
my @seq = 0 ... *;
然后重构输出逻辑
原代码用state变量控制省略号的打印,我们可以把输出拆成三个明确的部分,逻辑更清晰,也不用状态变量:
my @seq = 0 ... *; my @display = @seq[^10]; # 打印前3个元素 say "a$_ = @display[$_]" for 0..2; # 打印省略号(如果中间有元素的话) say "..." if @display[3..7].elems > 0; # 打印最后2个元素 say "a$_ = @display[$_]" for 8..9;
如果喜欢更紧凑的写法,用gather/take收集输出内容也是很Raku的风格:
my @seq = 0 ... *; my @output = gather { take "a$_ = @seq[$_]" for 0..2; take "..." if @seq[3..7].elems > 0; take "a$_ = @seq[$_]" for 8..9; }; .say for @output;
要是想保留循环的写法,也可以用更语义化的变量名和集合操作符∉(表示“不在范围内”),可读性拉满:
my @seq = 0 ... *; for @seq[^10].kv { state $ellipsis-shown = False; if $^k ∉ 4..7 { say "a$^k = $^v"; } elsif not $ellipsis-shown { say "..."; $ellipsis-shown = True; } }
内容的提问来源于stack exchange,提问作者Lars Malmsteen
相关产品推荐
相关产品推荐

