DMD 0.177 release
Andrei Alexandrescu (See Website for Email)
SeeWebsiteForEmail at erdani.org
Wed Dec 20 02:04:15 PST 2006
Kevin Bealer wrote:
> == Quote from Andrei Alexandrescu (See Website For Email)
> ...
>> That remains to be seen, but I think the buck stops at functions. The
>> problem of duplicating templates for inout (lvalues) and rvalues
>> stays, but I have an idea about that, that I might tell about
>> tomorrow.
>>
>> Andrei
>
> Did you ever work out how to do this lvalue/rvalue idea?
I had to leave to Romania before having the time to post thoughts on the
lvalue/rvalue discussion I've had with Walter on Saturday. We both agree
that it's a serious problem with D's type system that needs fixing (and
that he needs to do all the work :o)). I've continued to think of the
issue, at least enough to figure that the solution we initially thought
of is not sound.
Walter is reluctant to offering the ability to overload on
lvalue/rvalue, while it turns out that that can't be avoided. Let's
return to my litmus test - the identity function ident(e), which can
snuggle any expression e and leave its semantics unchanged. My thesis is
that this function is an important test of a language's power. The
starting point would be:
template ident(T) {
T ident(T e) { return e; }
inout T ident(inout T e) { return e; }
}
The problem with this approach is that it doesn't scale. Right now
"inout" is about the only interesting storage class of a function
parameter, but "lazy" comes to mind (which I hope to get rid of soon via
a much better solution) and later on we'll have "const", and each of
these combinations will mean one more duplication of the ident body
(and, by extension, of any function that wants to just pass the storage
class outside). Walter had an idea along the line:
template ident(T) {
return T ident(return T e) { return e; }
}
which allows you to reuse the return keyword as a symbolic placeholder
for passing out the storage class. This solution is severely
shortsighted in that it fixes ident and only ident, whereas the purpose
of ident is to serve as a simplified case for functions with multiple
parameters. So this fell as well.
We then discussed another solution that I won't bore you with, as it's
so wrong it hurts. My current thoughts navigate around two possible
solutions. One is to make the storage part of the template parameters:
template ident(S T) {
S T ident(S T e) { return e; }
}
When two adjacent symbols appear in a template parameter list, they
unambiguously denote a storage class followed by a type. So "S" can bind
to things like "in", "inout" etc., while "T" can bind to types. In the
example above, the compiler will deduce both S and T from the argument
type. It already does that, so that's no extra difficulty. The key point
that makes this scale is that you can bind S and T multiple times in a
variadic template. Another interesting detail is that it clarifies that
you can't solve the problem without somehow compiling two versions of
the ident function. So in the end overloading on "inout" is a must.
Another solution that works is to commit to the idea of associating the
storage class with the parameter (and divorce it from the type
entirely). In that case, the following syntax describes what happens:
template ident(T) {
storageof(e) T ident(storageof(e) T e) { return e; }
}
The storageof(symbol) meta-operator yields the storage of that symbol.
The problem with this notation is that it uses a symbol without having
seen it. That's not too bad (it already happens due to the way symbols
at global scope are looked up) but in this case it does have a fishy
smell. Another thing that I don't like it that the code obscures what's
going on - namely that one ident will be generated for each storage
class, even though that's not reflected in the parameter type list.
Finally, one related but slightly different topic is the necessity of
deduced return types for functions, e.g. by using "auto" to denote the
return type. Automatic deduction of return types is very useful in that
it allows compact template function definition - no more need for a
template that defines a homonym function. With deduced argument types,
ident can be written as:
auto ident(S T)(S T e) {
return e;
}
which is, I think, the Platonic ideal of ident as far as expressing it
in D goes.
Andrei
More information about the Digitalmars-d-announce
mailing list