Is all this Invarient **** er... stuff, premature optimisation?

p9e883002 at sneakemail.com p9e883002 at sneakemail.com
Sun Apr 27 16:43:43 PDT 2008


Hi all,

'scuse me for not being familiar with previous or ongoing discussion on this 
subject, but I'm just coming back to D after a couple of years away.

I have some strings read in from external source that I need to convert to 
uppercase. A quick look at Phobos and I find std.string has a toupper method.

import std.stdio;
import std.string;

int main( char[][] args ) {
    char[] a = args[ 0 ].toupper();
    writefln( a );
    return 0;
}

c:\dmd\test>dmd junk.d
junk.d(5): function std.string.toupper (invariant(char)[]) does not match 
parameter types (char[])
junk.d(5): Error: cannot implicitly convert expression (args[0u]) of type char[] 
to invariant(char)[]
junk.d(5): Error: cannot implicitly convert expression (toupper(cast(invariant
(char)[])(args[0u]))) of type invariant(char)[] to char[]

Hm. Okey dokey.

import std.stdio;
import std.string;

int main( char[][] args ) {
    char[] a = ( cast(invariant(char)[]) args[ 0 ] ).toupper();
    writefln( a );
    return 0;
}

junk.d(5): Error: cannot implicitly convert expression (toupper(cast(invariant
(char)[])(args[0u]))) of type invariant(char)[] to char[]

Shoulda known :(

import std.stdio;
import std.string;

int main( char[][] args ) {
    string a = ( cast(invariant(char)[]) args[ 0 ] ).toupper();
    writefln( a );
    return 0;
}

c:\dmd\test>dmd junk.d

c:\dmd\test>junk
C:\DMD\TEST\JUNK.EXE

Great! Now I need to replace the bit in the middle:

import std.stdio;
import std.string;

int main( char[][] args ) {
    string a = ( cast(invariant(char)[]) args[ 0 ] ).toupper();
    a[ 2 .. 4 ] = "XXX";
    writefln( a );
    return 0;
}

c:\dmd\test>dmd junk.d
junk.d(6): Error: slice a[cast(uint)2..cast(uint)4] is not mutable

Wha..? What's the point in having slices if I can't use them?

import std.stdio;
import std.string;

int main( char[][] args ) {
    char[] a = cast(char[]) ( cast(invariant(char)[]) args[ 0 ] ).toupper();
    a[ 2 .. 4 ] = "XXX";
    writefln( a );
    return 0;
}

Finally, it works. But can you see what's going on in line 5 amongst all that 
casting? Cos I sure can't.

So, I read that all this invarient stuff is about efficiency. For whom?
Must be the compiler because it sure ain't about programmer efficiency.

Ah. Maybe I meant to ignore the beauty of slices and use strings  and method 
calls for everything?

import std.stdio;
import std.string;

int main( string[] args ) {
    string a = args[ 0 ].toupper();
    a.replace(  a[ 2 .. 4 ], "XXX" );
    writefln( a );
    return 0;
}

Compiles clean and runs:

c:\dmd\test>dmd junk.d

c:\dmd\test>junk
C:\DMD\TEST\JUNK.EXE

But does nothing! 

import std.stdio;
import std.string;

int main( string[] args ) {
    string a = args[ 0 ].toupper();
    a = a.replace(  a[ 2 .. 4 ], "XXX" );
    writefln( a );
    return 0;
}

c:\dmd\test>dmd junk.d

c:\dmd\test>junk
C:XXXMD\TEST\JUNK.EXE

Finally, it runs. But at what cost? The 'immutable' a has ended up being mutated. 
I still had to specify the slice, but I had to call another method call to actually 
do the deed. 

Of course, a wasn't really mutated. Instead, args[0] was copied and then 
mutated and labelled a. Then a was copied and mutated and reassigned the 
mutated copy. 

So, that's two copies of the string, plus a slice, plus an extra method call to 
achieve what used to be achievable in place on the original string. Which is now 
immutable, but I'll never need it again. 

Of course, on these short 1-off strings it doesn't matter a hoot. But when the 
strings are 200 to 500 characters a pop and there are 20,000,000 of them. It 
matters.

Did I suggest this was an optimisation?

Whatever immutability-purity cool aid you've been drinking, please go back to 
coke. And give us usable libraries and sensible implicit conversions. Cos this sucks 
bigtime.

b.





More information about the Digitalmars-d mailing list