Okay, what happened to my literal strings?

Regan Heath regan at netmail.co.nz
Mon Sep 10 01:45:23 PDT 2007


Bill Baxter wrote:
> Burton Radons wrote:
>>
>> "Walter Bright" <newshound1 at digitalmars.com> wrote in message 
>> news:fbq3d5$1j0j$1 at digitalmars.com...
>>> 1) It opens the door to functional programming. This means that 
>>> function calls can be automatically parallelized, which is going to 
>>> become an increasingly big deal as people try to figure out how to 
>>> use their multicore processors.
>>>
>>> Note that C++ const CANNOT do FP, and Java CANNOT do const. This will 
>>> open up a huge advantage for D.
>>
>> But you can't do any serious optimisations (like SIMD) unless if you 
>> have the function body, in which case proving it's procedural (or 
>> where the output is defined based on hermetic input) is relatively 
>> simple and completely foolproof.
>>
>> C-type languages have too much of a fetish for becoming undefined. If 
>> my function is declared const or invariant, but it's not (which the 
>> language rules allow), it's undefined and the worst kind of undefined 
>> - the kind which works initially, and might even work with -O. But 
>> then one day it doesn't because of new optimisations or because the 
>> file is compiled in a different environment or even because the 
>> operating system has been upgraded or the same code is executed on a 
>> different processor or the code is moved into a different context or 
>> it or a dependency has been slightly modified. This can cause major 
>> damage to older code and forces dozens of discrete optimisation flags 
>> to try to get it to compile properly with a little more speed.
>>
>> If the language could not be put into an undefined state (but could be 
>> put into an erroneous state which could be detected in debug 
>> compilations) then you'd be free to implement any compliant 
>> optimisation without worrying about how much code it breaks. 
>> "Aggressive optimisation" wouldn't be a bad thing in that context.
>>
>>> 2) People who work on large projects with several teams modifying the 
>>> code tell me unequivocably that they need some sort of const to 
>>> enforce modularity.
>>
>> I don't think you believe it's adequate to do that. I'd expect that to 
>> be a good situation for programmers using const incorrectly, because 
>> they might need to cast const off code which they're not in control 
>> of, particularly when the internal rule is "you should const anything 
>> you don't modify" (which is an easy trap) instead of "you should const 
>> anything you /shouldn't/ modify".
>>
>>> 3) Const improves the self-documentation of interfaces.
>>
>> In this context, const is being used to describe a contract with the 
>> user. But contracts of this sort are impossible to reduce to a 
>> combination of keywords and unenforcable in all contexts by the 
>> compiler; there are too many subtleties. This belongs in the 
>> documentation itself.
>>
>> A good example is "char* strchr (const char*, char)" from C. That 
>> implies that the return value is not a pointer to an index of the 
>> first argument, but it is, it's just not declared that way because the 
>> argument itself may not be const. So the signature misses the subtlety 
>> of the true contract. If the user uses this signature as 
>> self-documentation then they could easily make an error. If it were 
>> instead "const char* strchr (const char*, char)" then the contract 
>> goes beyond what is strictly required because it's so blunt, and 
>> interpreted as self-documentation requires the user to make a copy 
>> before any modifications of the return value (and makes it impossible 
>> to do certain operations). If we decide that we don't want to lie then 
>> we can declare it as "char* strchr (char*, char)", which implies that 
>> the function modifies the string (because of the absence of const), 
>> when it never does; interpreted as self-documentation you'd always 
>> call it with mutable data. There's no happy medium: in any case the 
>> self-documentation is wrong and harms the user.
>>
>> This could be "fixed" through a complex set of attributes, in this 
>> case something like "argument (a) strchr (const char*a, char)", so the 
>> compiler could assume that if it calls it with a non-const argument 
>> then it gets a non-const argument in return and vice versa, and the 
>> function can be implemented without casting off const. But even 
>> keeping these literate contracts to const there are many variations 
>> that would require the user to learn a new language to interpret them 
>> when simple human-interpreted language more than suffices.
>>
> 
> I think the actual "fix" in C++ would be just to define a version of 
> strchr overloaded on const.  So you have both:
> 
>    const char* strchr(const char*, char);
> and
>    char* strchr(char*, char);
> 
> If you pass it a char* that can be modified, it'll give you back one 
> that can be modified. Otherwise it won't.

And in D we can use a template as the body of the function is the same 
for const or non-const data, eg.

S[] strchr(S : S[], C)(S[], C);

Two types S and C are required because sometimes you want to pass a 
char[] for the first and invariant(char) for the 2nd.

Regan



More information about the Digitalmars-d mailing list