Can the end list be lazy in Perl 6?

Suppose I have a sequence where I know the start and end points, and the generator is straightforward. Can I make it lazy?

my @b = 0 ... 3; say 'Is @b lazy? ' ~ @b.is-lazy; # Not lazy 

I would like to combine this famous list with myself an unknown number of times, but not immediately create the entire list. I want @cross be lazy:

 my @cross = [X] @b xx $n; 

I know I can do this with other simple questions or programming (and my Perl 5 Set :: CrossProduct does just that), but I'm curious if there is some simple and straightforward way that I am missing. Some way that does not imply that I am counting on my own.

As a side question, what feature of the sequence makes it lazy? Is this just the end point? Is there a sequence with a known endpoint that can still be lazy if the generator can create infinite values ​​between? I wondered how much information I need to delete and tried something like this:

 my $m = @*ARGS[0]; my @b = 0, * + $m ... ^ * > 3; say 'Is @b lazy? ' ~ @b.is-lazy; say '@b: ' ~ @b; 

However, this is not lazy.

+8
lazy-evaluation perl6
source share
4 answers

The lazy method, in my opinion, is really wrong. The only thing he says, as cuonglm noted, is that he simply goes over to the point that the main iterator claims to be lazy. But it still doesn’t mean anything. An iterator can technically produce values ​​on demand, but still claim that he is not lazy. And vice versa.

The "is-lazy" check is used to prevent cases where the number of elements must be known in advance (for example, .roll or .pick): if Seq / iterator claims to be lazy, it won’t actually try, but don’t work or throw it instead.

The only thing that .lazy does is wrap the Seq iterator in another iterator, which claims to be lazy (if that iterator claims it is not lazy, of course). And make sure that it does not pull any values ​​if it is really necessary. So, adding .lazy says nothing about when the values ​​will be produced, only when they are delivered. And it helps test the iterator-based logic to see how they will work with an iterator that claims to be lazy.

So, back to the question: if you want to be sure that something is lazy, you have to write an iterator yourself. Having said that, in recent months I have spent a lot of effort on making things as lazy as possible in the kernel. Remarkably, xx N is still not lazy, although it currently produces Seq. Forcing him to lazily break some speculations at some deep level, I still could not understand. Looking ahead, I think you can be sure that everything will be as lazy as it makes sense at all, perhaps it may indicate the benefit of memory over the processor. But you will never have full control over the built-in: if you want to get full control, you will have to write it yourself.

+5
source share

Yes, you can using the lazy method :

 > my @b = (0 ... 3).lazy; [...] > say 'Is @b lazy? ' ~ @b.is-lazy; Is @b lazy? True 

There is nothing special about Seq that makes it lazy, only its basic Iterator does.

+5
source share

As already stated, is-lazy means nothing.

But I just wanted to mention that there is a page on the rakudo wiki that gives a couple of tips on what you can expect from is-lazy .

+1
source share

You can do:

 my @b = 0 ... 3; 

lazy by simply adding the lazy keyword to the desired location, for example:

 my @b = lazy 0 ... 3; 

Or, as cuonglm pointed out , you can call the range method, for example:

 my @b = (0 ... 3).lazy; 
+1
source share

All Articles