Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I iterate after an assignment in Raku?

Tags:

raku

Given the following code, it seems that I cannot iterate over a Buf if it had been assigned to a variable, unless I cast it to a list, even though it's not a lazy sequence. What gives?

    my $file = open $path, bin => True;
    $_.chr.say for $file.read: 8; # works well

    my $test = $file.read: 8;
    $_.chr.say for $test; # fails with "No such method 'chr' for invocant of type 'Buf[uint8]'"
    $_.chr.say for $test.list; # works well
    $test.is-lazy.say; # False
like image 583
marwy Avatar asked Dec 21 '21 16:12

marwy


People also ask

How to pull out individual elements from a list using Raku?

Individual elements can be pulled out of a list using a subscript. The first element of a list is at index number zero: Variables in Raku whose names bear the @ sigil are expected to contain some sort of list-like object. Of course, other variables may also contain these objects, but @ -sigiled variables always do, and are expected to act the part.

What is itemization in raku list handling?

This is actually one of the trickiest parts of Raku list handling to get a firm understanding of. First, be aware that because itemization in Arrays is assumed, it essentially means that $ (…) s are being put around everything that you assign to an array, if you do not put them there yourself.

Can We have infinite lists in raku?

These are called sequences, which are of type Seq. As it so happens, loops return Seq s. So, it is fine to have infinite lists in Raku, just so long as you never ask them for all their elements.

What are @-sigiled variables in raku?

Variables in Raku whose names bear the @ sigil are expected to contain some sort of list-like object. Of course, other variables may also contain these objects, but @ -sigiled variables always do, and are expected to act the part. By default, when you assign a List to an @ -sigiled variable, you create an Array.


1 Answers

The reason it fails, is that:

my $test = $file.read: 8;

puts the Buf that is returned by $file.read into a Scalar variable, aka inside a container. And containerized is interpreted by for as itemized, to be considered a single item. So with:

.chr.say for $test;

you're calling the .chr method on the whole Buf, rather than on the individual elements.

There are a number of solutions to this:

  1. make sure there's no container:
my $test := $file.read: 8;

This makes sure there is no container by binding the Buf.

  1. make it look like an array
my @test := $file.read: 8;

Same as 1 basically, make the @test be an alias for the Buf. Note that this should also use binding, otherwise you'll get the same effect as you saw.

  1. make it work like an Iterable
.chr.say for @$test;

By prefixing the @ you're telling to iterate over it. This is basically syntactic sugar for the $test.list workaround you already found.

Re the $test.is-lazy.say, that is False for just about anything, e.g. 42.is-lazy.say; # False, so that doesn't tell you very much :-)

like image 120
Elizabeth Mattijsen Avatar answered Oct 21 '22 10:10

Elizabeth Mattijsen