Extended Type Design.
Reiner Pope
reiner at none.com
Fri Mar 16 23:44:29 PDT 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Reiner Pope wrote:
>> Andrei Alexandrescu (See Website For Email) Wrote:
>>
>>> We have talked about a design. In short, the intent is to define
>>> three flavors of immutability:
>>>
>>> a) final - a simple storage class controlling the immutability of the
>>> bits allocated for the symbol per se;
>>>
>>> b) const - type qualifier meaning an immutable view of an otherwise
>>> modifiable data. const does not control the bits of the object, only
>>> the storage addressed indirectly by it (transitively);
>>>
>>> c) "superconst" - denoted as "const!" or "super const": type
>>> qualifier meaning that the data is genuinely unmodifiable.
>>>
>> Is there anything in your discussion about compile-time constants (the
>> sort that you need for 'static if', etc) ? You spoke a while ago about
>> improving compile-time evaluation syntax so that there would be no
>> difference at the call site between runtime and compile-time
>> evaluation (like for regexps).
>
> I understand this is high on Walter's list.
Good to hear that.
The syntax discussed is:
>
> // dispatched when the pattern is known at compile time
> RegExpMatch match(const char[] p)(const char[] p, char[] text) {...}
> // dispatched when the pattern is a runtime string
> RegExpMatch match()(const char[] p, char[] text) {...}
That seems fine, but I can't help wondering, "why the double-declaration
of p in the first instance?" and also, "why does the second instance of
match even need to be a template?".
>
>> It seems like you could get this quite easily by adding just one more
>> parameter modifier (is this a storage class? I'm not sure) to denote,
>> "any time this function is called, this parameter must be known at
>> compile-time". Effectively, it would just be a conversion from this:
>>
>> RegExpMatch match(static const char[] pattern, char[] text) {...}
>> ...
>> main()
>> {
>> match("gr[ae]y", din.read());
>> }
>>
>> to this:
>>
>> RegExpMatch match(char[] pattern)(char[] text) {...}
>> ...
>> main()
>> {
>> match!("gr[ae]y")(din.read());
>> }
>>
>> Any plans this way?
>
> The above forces only compile-time constant regexps. What we need is to
> dispatch depending on compile-time constant vs. run-time string.
Well, I kind of took it for granted that the above suggestion would
allow for overloading by compile-time-constness (with a preference to
the compile-time version when there's a choice). So that you could write:
RegExpMatch match(static const char[] pattern, char[] text){...}
RegExpMatch match(char[] pattern, char[] text) {...}
>
> Combined with macros, this will essentially allow a call to writefln to
> morph, depending on its arguments, into putch(), fputs(), write(),
> fprintf() - or execute today's dynamically-checked writefln.
True. I was also interested in another use of this, though: allowing a
library-time implementation of tuples (since what kind of feature is one
that can't be implemented in the library?). There are basically two
reasons that this can't be done at the moment:
alias Tuple!(int, double) myTuple;
myTuple[0] = 5; // First reason
foreach (val; myTuple) // Second reason
{
writef(val);
}
I would imagine that you could implement the first feature as:
struct MyTupleImpl(TypeList...)
{
...
TypeList[i] opIndex(static const int i) {...}
// We grab the return type based on the parameter, so we must know it at
compile time. It makes no sense to have a runtime version of this.
}
and at a stretch, you could imagine the second feature as working in a
similar way: your compile-time representation of the foreach delegate is
either a char[] to be mixed in, or an expression alias, when we get that:
struct MyTupleImpl(TypeList...)
{
int opApply(static const char[] code)
{
// iterate through tuple; this iteration would actually have to
be generated with CTFE, but you get the idea
{
TypeList[i] __special_foreach_key = whatever;
mixin(code);
}
}
}
Cheers,
Reiner
More information about the Digitalmars-d
mailing list