On Sunday, February 25, 2018 01:49:05 Seb via Digitalmars-d-learn wrote: > On Tuesday, 20 February 2018 at 08:44:37 UTC, aberba wrote: > > On Sunday, 18 February 2018 at 15:23:14 UTC, Cym13 wrote: > >> On Sunday, 18 February 2018 at 14:48:59 UTC, Cym13 wrote: > >>> [...] > >> > >> Just thought of a much better/simpler solution for that last > >> case that also doesn't force you to read all data (which might > >> > >> be impossible when dealing with infinite ranges): > >> import std.range; > >> import std.algorithm; > >> > >> a[] > >> > >> .enumerate // get tuples (index, > >> > >> value) > >> > >> .filter!(t => t[1] == "Test2") // keep only if value == > >> > >> "Test2" > >> > >> .map!(t => t[0]) // keep only the index > >> > >> part > >> > >> .writeln; > >> > >> Completely lazy. > > > > How does one detect an operation as lazy or not? Is the some > > compile-time or runtime check for that? > > > > My guess is by referring to the docs function signature. > > While it's not a replacement for checking the code manually, > @nogc helps a lot:
That doesn't actually tell you whether the range is lazy. It just tells you whether any allocations may occur. If any exceptions could be thrown, then a lazy solution can't be @nogc (something that's often the case with strings thanks to auto-decoding and UTFExceptions), and a solution could be eager without allocating if the result doesn't require any allocation. Also, you could have a lazy range that involves a lambda that allocates a closure. So, yeah, a lot of the time, @nogc means that the range is lazy, but it doesn't guarantee it, and not being able to be @nogc doesn't mean that it's eager. So, I'd argue that while @nogc gives you a clue, it's ultimately a pretty poor way to try and figure out whether a range is lazy or not. All it really tells you is whether it's guaranteed that no allocations will occur on the GC heap. - Jonathan M Davis