On Wednesday, 15 January 2014 at 20:05:32 UTC, TheFlyingFiddle wrote:
This is why i was confused really since the normal foreach is char it's weird that string.front is not a char. But if foreach being a char is only the way it is for legacy reasons it all makes sense.

Unfortunately, it's not that simple. D arrays/slices have two distinct interfaces - the slice interface and the range interface. The latter is a library convention built on top of the former - thus the existence of the slice interface is necessary.

A generic algorithm can choose to work on arrays (array algorithm) or ranges (range algorithm) among other kinds of type federations:

auto algo(E)(E[] t); // array algorithm
auto algo(R)(R r) if (isInputRange!R); // range algorithm

The array algorithm can assume that:

foreach(e; t)
    static assert(is(typeof(e) == E));

While the range algorithm *cannot* assume that:

foreach(e; r)
    static assert(is(typeof(e) == ElementType!R));

Because this fails when R is a narrow string (slice of UTF-8 or UTF-16 code units). Thus, the correct way to use foreach over a range in a generic range algorithm is:

foreach(ElementType!R e; r) {}

Swapping the default just swaps which kind of algorithm can make the assumption. The added cost of breaking existing algorithms is a big deal, but as demonstrated, it's not a panacea.

Reply via email to