Andrei's interface requests
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Fri Apr 3 14:13:09 PDT 2009
Christopher Wright wrote:
> Andrei has put up a few enhancement requests in the bugzilla:
> http://d.puremagic.com/issues/show_bug.cgi?id=2784
> http://d.puremagic.com/issues/show_bug.cgi?id=2785
> http://d.puremagic.com/issues/show_bug.cgi?id=2786
Yah, this too:
http://d.puremagic.com/issues/show_bug.cgi?id=2050
> These are intended to change interfaces from being solely a tool of
> polymorphism into a way of specifying type constraints. The additions
> recommended can only be used at compile time (constructors, static
> functions, and nested types).
Yah. Let me add that I haven't thought the changes through, but I posted
them to foster discussion, which is happening (thanks!).
> I grant that it would be quicker and clearer to write:
> interface Foo
> {
> static void stuff();
> this (int);
> }
> template Template(Arg : Foo) {}
>
> than to write:
> template Template(Arg) if (is (typeof (new Arg(0)) &&
> isStaticFunction!(Arg, "stuff")) {}
Yah. Let me add that after the OOP meteoric rise in the past years, many
of us can instantly figure how the former works, whereas the latter is
thoroughly obscure.
Let me also pull the definition of a couple of range types in std.range
(by the way, I should commit the new Phobos today):
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r; // can define a range object
if (r.empty) {} // can test for empty
r.next; // can invoke next
auto h = r.head; // can get the head of the range
}()));
}
I wrote it as clearly as I could, and it doesn't quite look that pretty.
I didn't even know the typeof({ ... }()) trick is possible; I saw it
somewhere on this group, and took to it. Otherwise the code would have
been even more convoluted (along the lines of what you wrote, just more
of it). Furthermore, if a type is not a range, there's no simple way to
output an error message telling exactly which test if failed. The only
test possible is e.g. isInputRange!MyType.
I think we can't quite be happy that this is D's offering with regard to
concepts. On the other hand, we'd like to avoid the aggravation of C++
concepts, which, in my humble opinion, have a very low power/complexity
ratio. So I wanted to look at how interfaces can be reasonably extended
into expressing concepts while still being strongly integrated with
their classic runtime polymorphic role.
> However, I'm not sure whether this would be used much at all, and it
> deserves some discussion.
>
> One detail of #2785 seems problematic:
> interface Foo
> {
> extern void bar(int, Foo, double);
> }
>
> meaning that a non-member function bar should exist that accepts an int,
> *the implementor of Foo*, and a double.
>
> This is a huge and silent divergence from the standard meaning of using
> the interface name; it would allow:
> class C : Foo
> {
> static void bar(int, C, double);
> }
>
> and disallow:
> class C : Foo
> {
> static void bar(int, Foo, double);
> }
>
> Thoughts? Any concerns that I have not raised? I don't do sufficient
> metaprogramming to find any of this useful, I admit.
I thought of that, too. One option is to parameterize Foo with its
subtype's name:
interface Foo(X)
{
extern void bar(int, X, double);
}
Then you'd require C : Foo!C and so on. I'm not sure how important this
detail is, but it is worth thinking of.
Another issue is that constructors in a struct are one thing, whereas in
a class they are quite a different thing (references of a class can be
copied!)
Andrei
More information about the Digitalmars-d
mailing list