Array as an argument, ambiguous behaviour.

Steven Schveighoffer schveiguy at yahoo.com
Thu Jan 30 11:50:41 PST 2014


On Thu, 30 Jan 2014 13:58:55 -0500, Cooler <kulkin at hotbox.ru> wrote:

>>>>> The D principle - "The program compile and runs as expected, or not  
>>>>> compile at all".
>>>>
>>>> This is a fantasy. The compiler cannot know what you expect.
>>> The language is needed to express your intentions to the compiler.
>>
>> Anything that the compiler cannot enforce is just documentation. Does  
>> it matter whether the documentation is in a comment or part of the  
>> signature?
> Why we need "const" keyword, while we can just put "I promise do not  
> change it" in the documentation?

const is only useful in cases where references are involved. In this case,  
you want to make the *copied* data constant, in hopes that you then can't  
accidentally stop referencing the original.

In another example, there is little to be gained from a signature such as:

void foo(const int x);

What does this say about foo? Nothing. I can pass in a mutable, const, or  
immutable int, because a copy is made. It doesn't provide any more  
guarantees to the caller than:

void foo(int x);

Likewise, your proposed "int[] const" would not guarantee anything extra  
to the caller beyond "int[]", because both are copies put onto the stack.  
The function has no access to the original values.

Arrays in D are hard to understand. They don't behave like arrays in most  
other languages. But they foster a different mindset I think, that results  
in some of the fastest code on the planet. But one has to understand the  
semantics of syntax if they want to properly use the language. For  
functions which append/extend and then write data to the prior piece (the  
only non-deterministic case), special care has to be taken to explain this  
to the caller. I would think a mechanism to attempt detecting this and  
flagging it would be a worthy lint tool feature. But not a language or  
compiler feature. There is just simply no way to say "that is always bad"  
or that you know what the intentions of the author are.

The other case you specified, when the author re-assigns a slice and  
expects it to be a memcpy or to re-bind the calling parameter, the result  
is deterministically the wrong result, and the coder will notice it right  
away (and hopefully correct their understanding). I don't think we need a  
language feature for that, just documentation (which I think we have).

Let me also suggest you use scope statements to verify at runtime that the  
case you intend to prevent doesn't actually happen:

void foo(int[] x)
{
    const origx = x;
    scope(exit) assert(origx.ptr == x.ptr);
    ...
}

While not perfect, and not static, it should at least avoid subtle bugs  
(and can be turned off in release mode).

-Steve


More information about the Digitalmars-d-learn mailing list