Proposal for scoped const contracts

Steven Schveighoffer schveiguy at yahoo.com
Tue Mar 25 08:06:59 PDT 2008


"Janice Caron" wrote
> The more I think about this, the more I find I have to agree with
> Stephen completely. I think I might be able to come up with a better
> syntax though.
>
> Instead of
>
>    out(T) min(T)(in(T) x, in(T) y)
>    {
>        return x < y ? x : y;
>    }
>
> which is what Stephen suggested, I think this works better:
>
>    inout(U=T) U min(T)(U x, U y)
>    {
>        return x < y ? x : y;
>    }
>
> It's a pretty straightforward enhancement really. Just preceed a
> function definition with the attribute inout(U=T), and then within the
> function definition, all U's are in/out types. Here's the same idea
> used with strstr
>
>    inout(U=char) U[] strstr(U[]s, const(char)[] pattern)
>    {
>        int n = s.find(pattern);
>        return n == -1 ? null : s[n..$];
>    }
>
> The reason I like this better is that it means we only have to define
> the "in/out" type once, instead of multiple times. Also - it means we
> don't have to ditch the existing uses of "in" and "out".
>
> We can also use it for member functions, except with a slightly modified 
> syntax
>
>    class String
>    {
>        inout(this) strstr(const(String) pattern)
>        {
>            /*...*/
>        }
>    }
>
> I like the idea of only having to express the inout type only once per
> function declaration, and I like the idea of not having to completely
> change the existing meanings of "in" and "out" in a way which would
> break old code.
>
> Another advantage of my syntax is that you could use inout(U=T) as an
> attribute to bracket multiple functions. e.g.
>
>    inout(U=char)
>    {
>        U[] strchr(U[]s, char c);
>        U[] strstr(U[]s, const(char)[] pattern);
>    }
>
> Stephen, what do you think? Have I missed anything?

First, I'll say that I'm not a huge fan of my out() syntax.  However, I do 
like being able to tag exactly what is variably const on the arguments, and 
I think it is necessary to tag the output, otherwise you lose expressiveness 
and limit the syntax to certain types of functions.

So I'm glad that you are trying to find a better syntax, but I don't think 
this is it.  First, you are only allowing one type to be considered 'in' and 
'out', where it must be different for properties (in that the return type 
should be variably const based on the constancy of the 'this' pointer, but 
the return type usually is not the same type as the 'this' pointer). 
Second, I'd much rather have the 'char' in the argument declaration rather 
than aliasing it to some other symbol ('U') at the beginning.  I actually 
think it's less clear the way you have it.  Third, there is no way to 
declare another variable of the same constancy as the input but of a 
different type.  In my scheme, in(x), means the type x that is somehow 
derived from the input.  So at any time you can declare any type and tag it 
with 'in', which means it is based on the input (and therefore, should carry 
the same constancy).

I have found there are more issues that my solution doesn't solve exactly, 
so these need to be figured out.

For example, a linked list of mutable classes might be a template defined 
as:

LinkList(T)
{
   void append(T t) {...}
}

for the append function, the t argument is not modified during the function, 
but the link list node added should be not const.  So if a LinkList node is 
Node(T), then how do you write the signature and body of this function?  Is 
it important to declare t as an 'in' parameter?  I'm almost thinking that 
there is no real way to have the compiler be able to prove that an argument 
is not modified for all types of functions.

In addition, going back to the same example, append should only accept a 
mutable object for t, otherwise, it cannot construct a proper node to add to 
the list.  So how is this information communicated to the compiler?  If we 
use:

void append(in(T) t);

Then a const or invariant t could be passed to the function, which would be 
no good.

Is this even a concern that we should worry about?

-Steve 





More information about the Digitalmars-d mailing list