const debacle

Davidson Corry davidsoncorry at comcasst.net
Wed Mar 26 11:19:50 PDT 2008


Janice Caron wrote:
> On 26/03/2008, Davidson Corry <davidsoncorry at comcasst.net> wrote:
>>  idem(x) foo(const T x, const U y);      // first promise
>>  idem(y) bar(T x const, U y const);      // second promise
>>
>>  Does this make any sense? Or have I said something silly, or resurrected
>>  an old and discarded idea, or otherwise taken a pratfall on my maiden sally?
> 
> It makes sense, and you're spot on. I think the problem is well
> understood now. All we're lacking a good syntax to recommend. And it
> seems to me that no one's come up with anything better than Walter's
> 
>     U bar(const(T) x, return const(U) y)
> 
> although actually I still think it should be
> 
>     const(U) bar(const(T) x, return const(U) y)
> 
> because inside the function body, every return statement is going to
> be returning a const(U), not a U.
> 
> Your "bar" example doesn't make complete sense to me. If the function
> can only return a U (as indicated by your idem(y) - which incidently
> is similar to my earlier sliceof(y) suggestion), then why does x also
> have the "returnable" parameter declaration syntax? Was that a typo or
> am I missing something?
> 
> Walter's syntax is not as expressive as we might like, but it does
> have the benefit of being simple. By contrast, making a distinction
> between const-on-the-left and const-on-the-right is potentially
> confusing - and also, no more expressive that Walter's idea, so
> there's nothing to be gained by it.

Thank you. I was trying to suggest a few more things without burdening 
the message with too much extra explanation; in doing so I was unclear. 
I apologise.

There are two things going on here. First, I wanted to show that you 
could choose ANY of the function parameters as the basis for the 
returned type. You're not constrained to use the first parameter, nor 
the "first parameter that has one of these tricky annotations". <grin>

Second, these annotations are not necessarily tied to returns. They can 
be applied to any parameter(s) in the function, and each one makes a 
separate "promise".

The "promise" is actually two parts:
"I promise not to mutate the data underlying the X that you passed me, 
whether you think it's mutable or not. And IF I RETURN SOMETHING TO YOU 
BASED ON THOSE DATA, I won't constrain you to treat it as const even 
though I did. (If the return data are not referenced through X, the 
second part of the promise is irrelevant.)"

Imagine a signature like
	void foo(T t const, U u invariant, const V v)

Since the "return" is void, obviously NONE of the input parameters are 
participating in it. Nevertheless, we might have good reason to make the 
promises "I will treat your t as if it were const, your u as if it were 
invariant, and if you try to pass me a non-const v, I will cast it to 
const". In THIS example, there's not much difference between
"const V v" and "V v const" for the third parameter -- but if the return 
type were derived from v, the compiler would reject an attempt to return 
a NON-const reference to it. (Whereas the compiler would ALLOW non-const 
return types based on t or u.)

That is, the annotations participate in matching signatures for 
overloaded function names. As a secondary issue, they MAY also support 
automatic inference of a return type as well, but that's not part of 
signature matching. (In C++, you can't overload on return type. Correct 
me if I'm wrong, but I believe that this is true in D as well.)

Since what I'm talking about does not (necessarily) affect return, the 
"return (type) x" syntax is inappropriate, IMHO. Particularly since you 
could only mark ONE parameter as "return (Type) x", whereas here you 
could mark any or all parameters as "as-if-const".

I agree with you that 
const-on-the-left-const-on-the-right-stand-up-sit-down-fight-fight-fight 
<grin> is potentially confusing. I just haven't thought of a better way 
to express the notion "I will treat this parameter as if it were const, 
but I won't require that YOU promise to treat it the same way".

I think of "const on the left" as being part of the type: (const T)
whereas "const on the right" is an additional assurance from the 
function, part of its contract if you will: (plain T, possibly mutable, 
but I will not change it).

Does that make things clearer?

-- Dai




More information about the Digitalmars-d mailing list