Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re^2: [Perl6] Seq iterator already consumed

by Athanasius (Archbishop)
on Jun 17, 2019 at 12:24 UTC ( [id://11101460]=note: print w/replies, xml ) Need Help??


in reply to Re: [Perl6] Seq iterator already consumed
in thread [Perl6] Seq iterator already consumed

Thanks, choroba. I didn’t know about .^name — that’s useful. I found this explanation under https://docs.perl6.org/language/classtut#Introspection:

The syntax of calling a method with .^ instead of a single dot means that it is actually a method call on its meta class, ...

I’ll have to look into that.

But

say @dirs.^name;

returns Array, so it should be OK.

Actually, at this point @dirs contains two Seq objects. I think the subsequent call to split iterates each Seq (which is ok, since a Seq is a one-shot iterable); the later call to map attempts to iterate them again, causing the error.

This explanation would be fine if it weren’t for line C. Since join iterates over the Seq, it should be line C that produces the error. But it isn’t — and, as I stated in the OP, removing line C removes the error at line D too. So, still confused. :-(

But I did find another fix: change line A to this:

my @dirs.push: $_.split('/').cache for @paths; # A'

At least this looks less like a kludge than line B.

Cheers,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^3: [Perl6] Seq iterator already consumed
by duelafn (Parson) on Jun 17, 2019 at 13:36 UTC

    @dirs contains nothing until you call the split. Split doesn't iterate the Seq, it creates them. Then the join iterates them the first time and map tries to iterate them again.

    my @paths = data(); my @dirs.push: $_.split('/') for @paths; # A : @dirs == [(...).Seq, + (...).Seq] say $_.join('/') for @dirs; # C : @dirs == [Seq.new-co +nsumed(), Seq.new-consumed()] my $depth = @dirs.map(*.elems).min; # D : oops, consumed!

    Personally, I think the nicest looking way to fix this is to consume the Seq into an Array (update: though upon consideration, using .cache may be more efficient since it is lazy)

    my @dirs.push: [ $_.split('/') ] for @paths;

    Calling .perl "fixes" the error because the .perl method automatically calls .cache for you. Else attempting to debug via .perl would consume the Seq which would generally break code. The documentation for Seq mentions this:

    Caching is a volatile state exposed to the developer as an optimization. The Seq may become cached by many operations, including calling perl on the Seq (if called prior to a non-cached iteration).

    Good Day,
        Dean

      Hello Dean,

      Thanks for this explanation! I apologise for not replying sooner, but I wanted to look at the whole question with a fresh pair of eyes first. You are absolutely right:

      my @dirs.push: $_.split('/') for @paths; say @dirs.perl;

      shows:

      [("", "aardvark", "bison", "camel", "dromedary").Seq, ("", "aardvark", + "bison", "camel", "dromedary", "elephant").Seq]

      (i.e., 2 unconsumed Seq objects), but with .cache added to the split they are Lists:

      [("", "aardvark", "bison", "camel", "dromedary"), ("", "aardvark", "bi +son", "camel", "dromedary", "elephant")]

      — and therefore can be iterated as often as needed.

      Update:

      upon consideration, using .cache may be more efficient since it is lazy

      Where is this documented?

      Thanks again,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        Again, the documentation for Seq:

        A Seq represents anything that can lazily produce a sequence of values. A Seq is born in a state where iterating it will consume the values. However, calling .cache on a Seq will return a List that is still lazy, but stores the generated values for later access.

        Good Day,
            Dean

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11101460]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (8)
As of 2024-04-18 11:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found