> On Mar 4, 2024, at 15:55, ToddAndMargo via perl6-users <perl6-us...@perl.org> 
> wrote:


--snip--

> $ raku -e '.say for <bk10 bk34 bk2 bk1>.sort(*.split(/\d+/, :kv).map({ (try 
> .Numeric) // $_}).List)'
> bk1
> bk2
> bk10
> bk34
> 
> Yippee!
> 
> 
> tony@rn6:/home/linuxutil1$ raku -e '.say for <bk10 bk34 bk2 bk1>.sort: { 
> .comb(/ \d+ | \D+ /) .map({ .Int // .self })};'
> bk1
> bk10
> bk2
> bk34
> 
> Rats!  Thank for trying anyway!
> 
> -- 
> love, todd


Wow! Very subtle trap with Seq!

The short answer is: Just add `.cache`:
raku -e '.say for <bk10 bk34 bk2 bk1>.sort: { .comb(/ \d+ | \D+ /).map({ .Int 
// .self }).cache };' 
bk1
bk2
bk10
bk34

When the elements that `.sort` is sorting are of type List or Array, the 
sorting happens one slot at a time; the sort happens on element [0] of each 
List, and ties are settled by [1] (or [2] if [1] are also a tie, etc). This 
enables `.sort` to behave very intuitively (after the shock wears off).

I did not detect the problem by eye, but when I broke it down on the 
commandline I see that Seq objects are being created by `.comb` and `.map`.
Objects of Seq type can only be read *once*, so the multiple reads that `.sort` 
needs would not play well with Seq. It does not matter whether you convert the 
numbers to a Numeric type (which you did correctly in the `.map`), they are 
still part of a Seq.

The .cache method turns the Seq into a List, and the sort behaves as you 
intended.
https://docs.raku.org/routine/cache


-- 
Hope this helps,
Bruce Gray (Util of PerlMonks)

Reply via email to