<div dir="ltr">Thanks for the reply Dmitri - comments inline below:<div class="gmail_extra"><br clear="all"><div><div class="gmail_signature"> -- Howard.<br></div></div>
<br><div class="gmail_quote">On 9 February 2016 at 16:17, Dmitri Gribenko <span dir="ltr"><<a href="mailto:gribozavr@gmail.com" target="_blank">gribozavr@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Mon, Feb 8, 2016 at 8:56 PM, Howard Lovatt via swift-users<br>
<<a href="mailto:swift-users@swift.org">swift-users@swift.org</a>> wrote:<br>
> Hi,<br>
><br>
> I think I have found a couple of bugs in lazy collections; just checking<br>
> before filling. The following code is a filter map version of the Sieve of<br>
> Eratosthenes:<br>
><br>
> func lazyFilterMapForEachLoop(limit: Int = 9) -> [Int] {<br>
><br>
> var possibles = Array(count: limit + 1, repeatedValue: true)<br>
><br>
> return (2 ... limit).lazy.filter { i in // Has to be lazy and sequential<br>
> so that `possibles` is updated before it is used<br>
<br>
</span>Before looking at your questions below, I want to note that this is<br>
not a supported way of using the lazy subsystem. The issue is that<br>
you seem to be relying on the evaluation order. It is not guaranteed,<br>
even if you can reliably reproduce a certain evaluation order in the<br>
current version of the library.<br></blockquote><div><br></div><div>Not sure where it says that it won't be sequential - do you have a reference? </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><br>
> The filter closure is called twice per trial integer! First without<br>
> preceding to the map stage at all, i.e. all values are filtered out! Second<br>
> time through the numbers it does proceed to the map stage as you would<br>
> expect.<br>
<br>
</span>Again, remember that you are using the *lazy* subsystem. The<br>
evaluation order of the closures you are passing to the operations is<br>
not guaranteed. Closures can be evaluated once, more than once, or<br>
not at all, and in the order that the library choses. Closures are<br>
required to be pure, so you are not allowed to observe how many times<br>
and in which order they were actually evaluated.<br>
<br></blockquote><div>Not sure where it says it can be called more than one - the filter might be a very expensive operation like a database lookup!</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The reason why the closure is evaluated twice is because you end up<br>
calling an eager map(), which tries to reserve the array capacity<br>
suitable for the result. To do that, map() calls 'count' on the lazy<br>
filter collection, which triggers the computation the first time.<br>
<br></blockquote><div>map on a lazy collection results in another lazy collection, so I don't see this.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
It is an open question though, whether calling the closure twice is<br>
profitable here, and what can we do about it. The idea though is that<br>
those reallocations can sometimes be quite expensive when the closure<br>
is cheap to execute. OTOH, when the closure is expensive to evaluate,<br>
calling it twice is a loss.<br>
<span class=""><br>
> It produces an "Index out of range" error despite the fact that maximum<br>
> number processed is 9 which is an allowable index of `possibles`.<br>
<br>
</span>Are you sure you didn't mean to use ..< instead of ...?<br></blockquote><div><br></div><div>No I meant 2 ... limit, the array is of size limit + 1.</div><div><br></div><div>PS The equivalent code in Java works as expected. </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class="HOEnZb"><font color="#888888"><br>
Dmitri<br>
<br>
--<br>
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if<br>
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <<a href="mailto:gribozavr@gmail.com">gribozavr@gmail.com</a>>*/<br>
</font></span></blockquote></div><br></div></div>