std.algorithm.remove and principle of least astonishment

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sun Nov 21 20:56:17 PST 2010


On 11/21/10 22:09 CST, Rainer Deyke wrote:
> On 11/21/2010 17:31, Andrei Alexandrescu wrote:
> char[] and wchar[] fail to provide some of the guarantees of all other
> instances of T[].

What exactly are those guarantees?

>    - When writing code that uses T[], it is often natural to mix
> range-based access and index-based access, with the assumption that both
> provide direct access to the same underlying data.  However, with char[]
> this assumption is incorrect, as the underlying data is transformed when
> viewing the array as a range.  This means that generic code that uses
> T[] must take special consideration of char[] or it may unexpectedly
> produce incorrect results when T = char.

This is exactly where your point falls apart. I'm actually glad you 
wrote it down explicitly because this makes it simple to achieve the 
goal of putting you in the position to both understand where your point 
is wrong, and also the goal of putting you in the position for an "aha" 
moment or at least a "all right, grumble grumble" moment.

What you're saying is that you write generic code that requires T[], and 
then the code itself uses front, popFront, and other range-specific 
functions in conjunction with it.

But this is exactly the problem. If you want to use range primitives, 
you submit to the requirement of ranges. So you write the generic 
function to ask for ranges (with e.g. isForwardRange etc). Otherwise 
your code is incorrect.

If you want to work with arrays, use a[0] to access the front, a[$ - 1] 
to access the back, and a = a[1 .. $] to chop off the first element of 
the array. It is not AT ALL natural to mix those with a.front, a.back 
etc. It is not - why? because std.range defines them with specific 
meanings for arrays in general and for arrays of characters in 
particular. If you submit to use std.range's abstraction, you submit to 
using it the way it is defined.

So: if you want to use char[] as an array with the built-in array 
interface, no problem. If you want to use char[] as a range with the 
range interface as defined by std.range, again no problem. But asking 
for one and then surreptitiously using the other is simply incorrect 
code. You can't use std.range while at the same time complaining you 
can't be bothered to read its docs.

>    - char[] sets a precedent of Container!char providing a dchar range
> interface.  Other containers must choose to either follow this precedent
> or to avoid it.  Either choice may require extra work when implementing
> the container.  Either choice can lead to surprising behavior for the
> user of the container.

Encoded strings bring with them the necessity of encoding and decoding. 
That is an expected feature. It is up to your container whether it wants 
to do so or it needs to pass it to the client.

I challenge you to define an alternative built-in string that fares 
better than string & Comp. Before long you'll be overwhelmed by the 
various necessities imposed by your constraints.


Andrei


More information about the Digitalmars-d mailing list