auto ref

Bill Baxter wbaxter at gmail.com
Fri Dec 18 12:42:19 PST 2009


On Thu, Dec 17, 2009 at 11:41 AM, bearophile <bearophileHUGS at lycos.com> wrote:
> dsimcha:
>
>>The only solution I see would be to completely get rid of separate compilation.<
>
> "All problems in computer science can be solved by another level of indirection;"
> -- David Wheeler
> But that also slows code down a little :-)
>
> --------------------
>
> Bill Baxter:
>
> Static interfaces are an easy idea, it was discussed some weeks ago, and probably it's not too much hard to implement in the language. I like them enough, but they don't add that much to the template constraints already present, so it's mostly a duplication of syntax and semantics. So I am not sure they are a good idea.

My reason for bringing them up was to say that perhaps they could be
carried beyond that simple idea.


>>static interface VConst(T) {
>   constnessOf(T) is in [const, immutable, !const];
> }
> VConst!(Bar) doSomething(VConst!(Bar) b, int y) {...}
>
> static interface MaybeRef(T) {
>   refnessOf(T) is in [ref, !ref];
> }
> MaybeRef!(Bar) doSomethingElse(MaybeRef!(Bar) b, int y) { ... }<
>
> Walter has just added traits to perform this, so I think this is already doable, with __trait/meta. and template constraints.
> The opIn_r defined for arrays is something that D2 must eventually have, there's no doubt about this.
>
> But "is in", followed by an array of those modifiers is currently impossible (you may create a tuple of templates, where each template tests for constness, etc). Maybe in future you can create an array of annotations:
> [@const, @immutable, @notConst]

Yeh, I know what I wrote is impossible now.  Just putting the idea out
there because it seems like we're heading for a place where we solve
the problem of generating multiple versions of a function in three
completely different ways (auto ref, vconst and of course templates)
[four if you count generating them with string mixins].  I don't know
what the proper generalization is, but I think if you try to keep
templates the way they are while generalizing them to handle these
cases you will end up with an unworkable notation nightmare.  I like
the way Go static interfaces refactor template specifications to
simplify the overall syntax.

In WalterAndrei.pdf from the D conference there was talk of static
parameters and of unifying regular functions and templates.  The Go
approach basically accomplishes that by associating a symbol with all
the template specification baggage.  Then just by using that symbol in
the parameter list of an ordinary-looking function, the compiler can
tell not only 'hey we've got a template' but also what types of
constraints apply.

In a sense, current templates are analogous to structures that require
you to spell out the members of the struct every time you use one.
For structs we can do:
   struct Complex { float re; float im; };
   Complex addComplex(Complex a, Complex b);

But imagine if you had to write that always as
    template isComplex(T) {
          enum isComplex =
                   __traits(hasMember,T,"re") &&
                   __traits(hasMember,T,"im") &&
                    typeof(T.init.im == float) && typeof(T.init.re == float);
    }
    T addComplex(T)(T a, T b) if (IsComplex!(T)) { ... }

The current system forces you to do that the instant your constraint
becomes more complex than "a struct that has these members of these
types in this particular order".    Instead, Go encodes the complexity
in a reusable symbol that acts like a type name, but it contains
richer, more generic information than a regular type.

A big thing lacking is that Go doesn't give you a way to express
constraints between types.  Like with:
      T index(T,S)(T[S] x, S y) { ... }

But I think you could devise a way to encompass such cases.  Maybe
something like:

      static interface Indexable  {
            Indexed := Indexable[Index];
      }
      Indexable.Indexed index(Indexable x, Indexable.Index y) { ... }

(Note this is more general than the above T[S] template which only
matches built-in AA's)

This is clearly too much for D2 to swallow at this point.  But I think
it's worth thinking about whether there may be a significantly better
way to specify parametrized types and constraints on them than what
C++ and D use.

--bb



More information about the Digitalmars-d mailing list