On Sat, 17 Jul 2010 10:34:28 -0400, Andrei Alexandrescu <seewebsiteforem...@erdani.org> wrote:

Robert Jacques wrote:
Before reading TDPL I'd had agreed with you 100%. Now, I find that TDPL is either ambiguous or anticipatory in a small number of cases. For example, Functions-as-Methods get more exposure than @property, but no limitations are mentioned nor are there any generalized examples presented. So is the feature limited to arrays (current DMD) or available to all types (Slide-ware from the D conference)? Clear and the removal of delete got a solid paragraph of explanation and rational, but recent discussions have highlighted issues. And while I believe these issues to be solvable, as the devil is always in the details, this might not always be the case where TDPL anticipates DMD. By contrast, @property literally gets 1 line of text, 2 off-hand code uses and Methods-as-Properties is never mentioned. So was Methods-as-Properties not mentioned because it was dropped from the spec or because TDPL is downright laconic with regard to properties in general?

It's quite reasonable to not want to give very much detail about features that are not yet fully implemented - that was the only motivation.

What Walter and I had in mind was to remove methods-as-properties in favor of @property. He mentioned that that would break quite a bit of code in Phobos so it needs to be introduced with care. The current plan is to initially enable it as a compiler switch.

Functions-as-methods is, I think, a good feature. I've encountered one issue with them: it's difficult to define a function if there's no method with the same name. Consider we want to define foo(T) if T does not have a method foo():

void foo(T) if (!is(T.init.foo())) { ... }

This works today. However, with the new rule things are dicey. The foo(T) free function is introduced before evaluating the constraint. So T.init.foo() does find it. What happens currently (if T is an array type) is infinite recursion during compilation.

I think the problem is solvable - I just introduced hasMember(T, string) in std.traits that looks up straight in T's symbol table. So the rewritten condition would be:

void foo(T) if (!hasMember!(T, "foo") || !is(T.init.foo())) { ... }

Assuming short-circuit evaluation, it all works but it's rather subtle.

Since recently, however, Walter became very adverse to introducing breaking changes of any kind. He understandably wants to promote stability of the language. The only question is whether stability refers to the compiler's status quo or TDPL.

Finally, I should mention that we decided relatively early within the book that TDPL won't be a reference manual including every single detail of the language; it would have inflated with a lot of boring details. Not even K&R is a complete reference to C, even as it was back when the book was written.


Andrei

Thank you for that excellence explanation/clarification.

I'm also hopeful for Functions-as-methods, although you may be borrowing trouble with your example. It appears that templates are not included in T.init's scope as the following compiles:

struct Bar {
    void foo(T)() if (!is(bar.foo!int)) { writeln("recursive"); }
}

void foo( T)(T x) if (!is(T.init.foo())) { writeln("recursive"); }
void foo2(T)(T x) if (!is(T.init.foo())) { writeln("recursive"); }

void main(string[] args) {
    Bar b;
    b.foo!int;

    int[] bar;
    bar.foo;
    bar.foo2;

    return;
}

As for @properties and Methods-as-properties, I know I dropped out of the properties debate when the removal of Methods-as-properties was taken out of the proposal. The more I use @property and see it used, the more I feel that it's solving its motivating problems by exclusion: i.e. it's fixing a problematic corner case by virally applying itself to everything else. So perhaps like throw and nothrow, noproperty would be a superior alternative to property. But in either case, no/property is a preemptive / retrospective patch to the problem of opCall hijacking. And although I appreciate the value of having the tools to fix an opCall hijack once detected, I'd much rather have a generic solution that detects them at compile-time.

Reply via email to