Traits

Traits are designed as a mechanism for extending existing types with functionality.

Both explicit and implicit traits exist; explicit traits (trait Foo) must be explicitly implemented for a given type. They implement nominal subtyping. Implicit traits (implicit trait Foo) apply to all types that match the “pattern” (structure) described within, thus implementing structural subtyping.

Note: The example specifies what seems like operator overloading. While the D approach seems fine, I don’t fully know yet how it will work. opAdd, __add__, and similar have the issue that the relationship between operators and names can be unclear. On the other hand, operator+ (keyword-based) create for messy syntax, are by themselves ambiguous (consider the C++ operator++(int) hack), and either cover too much (all of < <= > >= must be manually implemented, as opposed to a single opCmp), or leave the user guessing as to which operators are available for overloading in this manner and which aren’t.

struct SomeStruct
{
    string foo;
    int bar;

    // implemented as an anonymous trait; see below for equivalent [A]
    int getSomething() { return bar + 10; }
}

trait Addable
{
    // this_t is alias for the implementing type
    // TODO: unsure of `this_t` keyword name (I dislike the idea of a _t suffix *in a keyword*, though it does make sense)
    this_t opAdd(this_t b);
}
// TODO: Should we even *have* implicit traits? They can be very useful, though.
implicit trait Divisible
{
    this_t opDiv(this_t b);
}

// implement a trait for SomeStruct
extend SomeStruct: Addable
{
    // `this_t` when *extending* is just a direct alias for `SomeStruct`
    // it is allowed here to avoid repetition of `SomeStruct`, and for symmetry with the trait
    this_t opAdd(this_t b) { ... }
}

// [A] equivalent to SomeStruct.getSomething above
extend SomeStruct	// implemented as an anonymous trait that only SomeStruct implements
{
    int getSomething() { return bar + 10; }
}