V2 string

Bruno Medeiros brunodomedeiros+spam at com.gmail
Thu Jul 5 04:37:08 PDT 2007


Regan Heath wrote:
> Walter Bright Wrote:
>> Derek Parnell wrote:
>>> However, if I might need to update it ...
>>>
>>>    char[] fullpath;
>>>
>>>    fullpath = CanonicalPath(shortname).dup;
>>>    version(Windows)
>>>    {
>>>       setLowerCase(fullpath);
>>>    }
>>>
>>> The point is that the 'CanonicalPath' function hasn't got a clue what the
>>> calling function is intending to do with the result so it is trying to be
>>> responsible by guarding it against mistakes by the caller.
>> If you write it like this:
>>
>> string fullpath;
>>
>> fullpath = CanonicalPath(shortname);
>> version(Windows)
>> {
>>        fullpath = std.string.tolower(fullpath);
>> }
>>
>> you won't need to do the .dup .
> 
> Because tolower does it for you, but it still returns string and if for example you need to add something to the end of the path, like a filename you will end up doing yet another dup somewhere.
> 
> I think the solution may be to template all functions which return the input string, or part of the input string, eg.
> 
> T tolower(T)(T input)
> {
> }
> 
> That way if you call it with char[] you get a char[] back, if you call it with string you get a string back.
> 
> However...
> 
> tolower is an interesting case.  As a caller I expect it to modify the string, or perhaps give a modified copy back (both options are valid and should perhaps be supported?).
> 
> So, the 'string tolower(string)' version has 2 cases, the first case where it doesn't need to modify the input and can simply return it, no problem.  
> 
> But case 2, where it does modify it should dup and return char[].  My reasoning being that after it has completed and returned the copy, the caller now 'owns' the string (as it's the only copy in existance and no-one else has a reference to it).
> 

Indeed, I think this illustrates that some standard library functions 
may not have the correct signature, and I tolower is likely one of them.
The most general case for tolower is:
   char[] tolower(const(char)[] s);
Since tolower creates a new array, but does not keep it, it can give 
away it's ownership of the the array (ie, return a mutable).

The second case, more specific, is simply syntactic sugar for making 
that array invariant:

   invariant(char)[] tolowerinv(const(char)[] str) {
     return cast(invariant) tolower(str);
   }

The current signature:
   const(char)[] tolower(const(char)[] str)
is kinda incorrect, because it returns a const reference for an array 
that has no mutable references, and that is the same as an invariant 
reference, so tolower might as well return invariant(char)[].


> To achieve that we'd need to overload on return type, or something clever...  but then, how do we call it?
> 
> auto s = tolower(input);
> 
> tolower cannot be selected at compile time, and the type of s cannot be known either, so that's an impossible situation, yes?
> 
> Regan

The 'something clever' to distinguish both cases is simply naming two 
different functions, like tolower or tolowerinv (if the second function 
is needed at all).


-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D



More information about the Digitalmars-d mailing list