On Wednesday, 24 June 2015 at 01:04:01 UTC, Adam D. Ruppe wrote:
We disagreed on this on irc, but I ask you to consider the
following which limits the code breakage a lot more than my
first proposal in chat:
---
import std.range;
struct ToLowered(R) if(isInputRange!R) {
R inputRange;
this(R r) {
static if(isForwardRange!R)
inputRange = r;
if(!empty)
front = cast(char) (inputRange.front | 0x20);
}
char front;
static if(isForwardRange!R)
typeof(this) save() { return this; }
bool empty() {
return inputRange.empty();
}
void popFront() {
inputRange.popFront();
if(!empty)
front = cast(char) (inputRange.front | 0x20);
}
private immutable(char)[] eagerCache;
deprecated("please call .array on this yourself or adjust your
algorithm to use the laziness (tip: changing string
declarations to auto may help)")
string eager() pure {
if(eagerCache is null) {
foreach(c; this)
eagerCache ~= c;
}
return eagerCache;
}
alias eager this;
}
ToLowered!R toLower(R)(R r) {
return ToLowered!R(r);
}
void main() {
import std.stdio;
string s = "Amazing Stuff".toLower; // alias this!
writeln(s);
string[string] lol;
lol["FOO"] = "FOO".toLower; // alias this!
writeln(lol);
}
---
The code breakage is minimal (especially if we don't actually
deprecate that eager method) - cases where a string is expected
is automatically handled by the alias this, and pipelines using
auto will just work. Copying this struct has the same semantics
as copying the string The change of type can break code - but
only code that was neither quite static nor quite generic.
Code that statically takes a string works, as will returning a
string, that's also covered by alias this. Code that
generically works on input/forward ranges works, as this is
still a by-value forward range. Only code that takes a template
argument and literally checks if(is(T == string)) or
if(is(isArray!T)) and those variants will break on this.
I confess, that is some code, but with alias this, we have a
migration path to change a lot of usages of the existing
functions to be lazy without dreaming up new names.
Moreover, with this, some old code will *automatically* be
upgraded to laziness without needing to change at all too. Tell
me that doesn't at least tempt you!
Yup, mind completely blown.
I almost want to put "alias eager this;" in all my ranges now...