June 24, 2015
On Wednesday, 24 June 2015 at 01:04:01 UTC, Adam D. Ruppe wrote:
> [...]
> 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!

+1
June 24, 2015
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...
June 24, 2015
On 24-Jun-2015 04:03, 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:
>
[snip]
> 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!

+1
Feels dangerously seductive.

-- 
Dmitry Olshansky
June 24, 2015
On Wednesday, 24 June 2015 at 01:04:01 UTC, Adam D. Ruppe wrote:
> The code breakage is minimal

Won't this break isSomeString? Phobos uses this everywhere.
June 24, 2015
On Wednesday, 24 June 2015 at 11:12:27 UTC, John Chapman wrote:
> On Wednesday, 24 June 2015 at 01:04:01 UTC, Adam D. Ruppe wrote:
>> The code breakage is minimal
>
> Won't this break isSomeString? Phobos uses this everywhere.

It won't break isSomeString. isSomeString will continue to work the same. What it will mean is that the result of toLower won't pass isSomeString anymore, and if you pass it to a range-based function which has an overload for strings, it won't match it and will be treated the same as a range like FilterResult and not get the string optimizations. If you want it to actually be a string, then you'll need to use to!string on it (even std.array.array wouldn't work, since that would convert it to dchar[], not string).

So, that could be a reason why this isn't a great idea, but it once again highlights why having autodecoding is a bad idea, and it shows that as we increase how much we're doing with functions which return lazy ranges, the cost of having autodecoding will only increase, because we'll being dealing with strings directly less and less.

- Jonathan M Davis
June 24, 2015
On 24/06/15 01:17, Meta wrote:

> I really hate this naming scheme for functions that take lazy
> parameters. I still don't see why we don't do the (IMO) simplest and
> most intuitive thing and name them lazyToLower / lazyToUpper (or
> toLowerLazy / toUpperLazy). There is precedent with C#'s handling of
> async functions; for example, AccessTheWebAsync or GetStringAsync[1].
> Your proposed naming scheme seems like it's trying to be too "clever"
> and really just ends up causing unnecessary confusion. This is not Ruby.
> [1]https://msdn.microsoft.com/en-us/library/hh191443.aspx

+1

-- 
/Jacob Carlborg
June 24, 2015
On Tuesday, 23 June 2015 at 23:58:07 UTC, Jeremy Powers wrote:
> I actually don't think having separate threads for each name is the best solution.  May be better to get them all listed in one place, and see if a consistent naming system can emerge.

I looked through std.range and std.algorithm and created this page:

http://wiki.dlang.org/Naming_conventions
June 24, 2015
On 24/06/15 03:05, Vladimir Panteleev wrote:

> Well, it's true, any chosen decision is going to be a compromise.
>
> Appending "Lazy" is only easy because the work to come up with suitable
> names has already been done for the eager variants. Finding suitable
> names for the lazy variants would entail doing similar work, perhaps
> with a bit more effort to communicate that this version is not eager.

It's hard enough to come up with one good name, it will be even harder to come up with a second name. Trying to come up with names indicating one is eager and one is lazy will be almost impossible.

> I'll collect some data tomorrow to see if it's possible to find a
> likeable convention for lazy function names. But even if this will fail
> and we'll have to settle for inconsistency, I think overall the
> situation will still be better than having "Lazy" sprinkled everywhere.
> It will also be consistent with the names so far (e.g. join/joiner) :)

join/joiner is almost as bad as setExtension/setExt.

-- 
/Jacob Carlborg
June 24, 2015
On 24/06/15 02:17, Mike wrote:

> Ok, I'm with you.  Allow me to offer another suggestion then.
>
> 1. Add functions `toUpperCaseEager` and `toLowerCaseEager`.
> 2. Have `toUpper` forward to `toUpperCaseEager` and `toLower` forward to
> `toLowerCaseEager` with a friendly comment.  You don't need to deprecate
> `toUpper` or `toLower` unless you want to.  It will happen naturally and
> gradually in time anyway.
> 3. Add functions `toUpperCase` and `toLowerCase` implementing the lazy
> versions.

How will that make things better? A user will see both toLower and toLowerCase can think: "What the h*ll is the difference between these to functions".

-- 
/Jacob Carlborg
June 24, 2015
On Wednesday, 24 June 2015 at 05:20:38 UTC, Jonathan M Davis wrote:
> If we want to be consistent with the likes of splitter, then they should be something more like lowerCaser and upperCaser (though caser isn't really word, and AFAIK, there is no noun for something which changes the case of a letter). When adding lazy versions in the past, for better or worse, we've generally gone for using nouns, whereas you're suggesting adjectives based coming from the past tense of a verb (though the verb "to case" has nothing with the case of letters).

I think splitter and joiner are the exception rather than the rule, actually:

http://wiki.dlang.org/Naming_conventions

Most of the hypothetical names in that column (verb-noun) are pretty ugly. I don't think this is a convention we should adopt.

The problem with toXCase is that there is neither a noun for an upper-case transform, nor a verb for such an operation, such as e.g. "capitalization" and "capitalize", so I think we should look at it separately.

I think someone suggested lowerCased and upperCased somewhere, I think there are fine too. There is some precedent (transposed and indexed).