lazy thoughts
Jason House
jason.james.house at gmail.com
Mon Jan 12 17:01:20 PST 2009
It sounds good. I have one question:
How do we avoid surprising the user?
That can be...
lazy output when expecting non-lazy
non-lazy output when expecting lazy
later input changes altering output
When returning lazy should be be safe:
immutable input data
consumable ranges
the output range can be of the same type as the input ranges
Confusing / easy to misuse cases:
Arrays of mutable data
Slices of static arrays (or any other scope data)
Changing the default behavior depending on the function
Some candidate ideas:
Create std.algorithm and std.lazyalgorithm
* Allows user to pick what they want (when importing only one)
* Overload sets can help with ambiguous cases
Slight name mangling of lazy and non-lazy versions (map vs. xmap)
Andrei Alexandrescu wrote:
> (I originally emailed this to Walter and a couple others, but I thought
> it might be better to gather insights from the community.)
>
> I'm gearing up for changing std.algorithm, and I am thinking of making
> the major change of favoring lazy evaluation throughout. For example,
> consider the map function. Right now map allocates and returns a new
> vector, for example:
>
> int[] arr = [ 1, 2, 3, 4 ];
> auto squares = map!("a * a")(arr);
> assert(squares == [ 1, 4, 9, 16 ]);
>
> What happens is unfortunate because (1) all evaluation is done upfront
> even if it is only partially needed, (2) allocation is done every call,
> (3) the whole scheme won't work with unbounded inputs, e.g. generators
> or even large files.
>
> So now that we have nice range support in the language, I'm thinking
> very seriously of switching full-bore to lazy semantics. In that case
> map returns a range - a little struct that saves the input and trickles
> out results one at a time.
>
> One nice thing about lazy is that lazy includes eager. If you actually
> want to "eagerize" map, you just call eager against the returned range:
>
> int[] arr = [ 1, 2, 3, 4 ];
> auto squares = eager(map!("a * a")(arr));
> assert(squares == [ 1, 4, 9, 16 ]);
>
> The real advantage comes when you actually exploit the laziness, e.g.:
>
> int[] arr = [ 1, 2, 3, 4 ];
> auto squares = map!("a * a")(arr);
> foreach (x; squares) {
> writeln(x);
> }
>
> Look ma, no allocation!
>
> I just wanted to gauge your opinion on this. It is a major departure
> from the STL, and I think in the right direction. It is a departure
> nonetheless and some STL users might feel uncomfortable.
>
> Also, lazy evaluation has the risk of getting confusing as there's a lot
> of escaping. Consider:
>
> int[] arr = [ 1, 2, 3, 4 ];
> auto squares = map!("a * a")(arr);
> arr[] = [ 5, 6, 7, 8 ];
>
> Now iterating squares will see different numbers than the original ones.
>
> Please let me know what you think!
>
>
> Andrei
More information about the Digitalmars-d
mailing list