Home > Raku > Only infinite elements

Only infinite elements

Flavio solved a puzzle with an implementation that puzzled me. The following code appears not as idiomatic as such a simple problem should require.

sub simulation-round () {
   return [+] gather {
      loop {
         my $value = roll-die();
         take $value;
         last if $value < 3;
      }
   }
}

We tend to do our dice rolls with a simpler construct.

sub simulation-round () {
    [+] (1..6).roll(*).map({ last .Int if .Int < 3; .Int });
}

# OUTPUT: Cannot .sum a lazy list onto a Seq
#           in sub simulation-round at ETOOBUSY-2.raku line 4
#           in block <unit> at ETOOBUSY-2.raku line 7

Rakudo assumes that a lazy list must be infinite. This would catch many bugs but is not what I want in this case. Sadly we don’t have a build-in to say .lazy-but-finite. Neither do we got roles we could mixin. This might be the reason why it took me 10 minutes of staring‑at‑the‑code to find a solution.

[+] (1..6).roll(*).map({ last if .Int < 3; .Int })[^∞]

So we are asking for up to infinite elements of this infinite list to defuse the laziness. This smells of bad design and may warrant a problem solving issue.

The rest of my version is quite different because I wanted to shoehorn a .hyper in.

use v6.*;

unit sub MAIN($rounds = 1_000_000);

sub term:<🎲>() { (1..6).roll(*) };

sub simulation-round () {
    [+] 🎲.map({ last .Int if .Int < 3; .Int })[^∞];
}

my $total = (0..^$rounds).hyper(:degree(12), :batch(10000)).map({ simulation-round }).sum;

put ‚average gain: ‘, $total / $rounds;

I believe there is a life‑lesson to be learned. Laziness can be problematic if the compiler is less then virtuos.

UPDATE:

As lizmat pointed out, last .Int requires v6.e.PREVIEW (v6.* will work too). Instead of [^∞] a simple .eager will do (but will break the title of the blog post). We can also use ^$rounds instead of (0..^$rounds) if we disambiguate with a space before the method call.

my $total = ^$rounds .hyper(:degree(12), :batch(10000)).map({ simulation-round }).sum;

Categories: Raku
  1. holliholzer
    August 3, 2021 at 21:57

    I can only wonder what the optimizer makes of this, but it works:

    [+] .head( .first: * <= 2, :k ) with cache (1..6).pick xx *

  1. August 2, 2021 at 20:32

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: