<div dir="ltr">2013/2/3 Andrei Alexandrescu <span dir="ltr"><<a href="mailto:SeeWebsiteForEmail@erdani.org" target="_blank">SeeWebsiteForEmail@erdani.org</a>></span><br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Walter and I have had a discussion on how to finalize properties.<br>

<br>
<a href="http://wiki.dlang.org/DIP23" target="_blank">http://wiki.dlang.org/DIP23</a></blockquote><div><br></div><div style>Awesome!!</div><div style><br></div><div style>After reading it, I thought that there is some consistent rules.</div>
<div style><br></div><div style><div>1. When a function is annotated with @property, it cannot be called with parenthesis syntax.</div><div>2. 0-arg functions which not annotated with @property can be called without parentheses.</div>
<div>3. Ref return getter can make "auxiliary setter", if formal getter is missing.</div><div>4. `typeof(exp)` never returns "function type". In other words, the actual type of `exp` and `typeof(exp)` should be same.</div>
<div>5. Both `&prop` and `&func` should return function pointer / delegate object</div><div>6. UFCS CAN NOT call global setter by getter syntax.</div><div><br></div><div style>I think that 4 to 6 are important points of this DIP. Based on the rules, I could write an exhaustive test case.</div>
<div style><br></div><div style><div>alias Type = int;</div><div><br></div><div>unittest</div><div>{</div><div>    struct S</div><div>    {</div><div>        @property Type foo();       // formal getter</div><div>        @property void bar(Type);   // formal setter</div>
<div>        @property ref Type baz();   // ref return getter == auxiliary setter</div><div>    }</div><div>    S s;</div><div>    static assert( __traits(compiles, { s.foo;     }));</div><div>    static assert(!__traits(compiles, { s.foo();   }));</div>
<div>    static assert(is(typeof(s.foo) == Type));</div><div>    static assert(is(typeof(&s.foo) == Type delegate()));</div><div><br></div><div>    static assert( __traits(compiles, { s.bar = 1; }));</div><div>    static assert(!__traits(compiles, { s.bar(1);  }));</div>
<div>    static assert(is(typeof(s.bar)) == false);</div><div>    static assert(is(typeof(&s.bar) == void delegate(Type)));</div><div><br></div><div>    static assert( __traits(compiles, { s.baz;     }));</div><div>    static assert(!__traits(compiles, { s.baz();   }));</div>
<div>    static assert( __traits(compiles, { s.baz = 1; }));</div><div>    static assert(is(typeof(s.baz) == Type));</div><div>    static assert(is(typeof(&s.foo) == ref Type delegate()));</div><div>}</div><div>unittest</div>
<div>{</div><div>    struct S</div><div>    {</div><div>        Type foo();         // 0-arg function</div><div>        void bar(Type n);   // 1-arg function</div><div>        ref Type baz();     // 0-arg ref return function</div>
<div>    }</div><div>    S s;</div><div>    static assert( __traits(compiles, { s.foo;     }));</div><div>    static assert( __traits(compiles, { s.foo();   }));</div><div>    static assert(is(typeof(s.foo) == Type));</div>
<div>    static assert(is(typeof(&s.foo) == Type delegate()));</div><div><br></div><div>    static assert(!__traits(compiles, { s.bar = 1; }));</div><div>    static assert( __traits(compiles, { s.bar(1);  }));</div><div>
    static assert(is(typeof(s.bar)) == false);</div><div>    static assert(is(typeof(&s.bar) == void delegate(Type)));</div><div><br></div><div>    static assert( __traits(compiles, { s.baz;     }));</div><div>    static assert( __traits(compiles, { s.baz = 1; }));</div>
<div>    static assert( __traits(compiles, { s.baz();   }));</div><div>    static assert(is(typeof(s.baz) == Type));</div><div>    static assert(is(typeof(&s.baz) == ref Type delegate()));</div><div>}</div><div><br></div>
<div>@property Type foo();</div><div>@property void bar(Type);</div><div>@property ref Type baz();</div><div><br></div><div>unittest</div><div>{</div><div>    static assert( __traits(compiles, { foo;     }));</div><div>    static assert(!__traits(compiles, { foo();   }));</div>
<div>    static assert(is(typeof(foo) == Type));</div><div>    static assert(is(typeof(&foo) == Type function()));</div><div><br></div><div>    static assert( __traits(compiles, { bar = 1; }));</div><div>    static assert(!__traits(compiles, { bar(1);  }));</div>
<div>    static assert(is(typeof(bar)) == false);</div><div>    static assert(is(typeof(&bar) == Type function()));</div><div><br></div><div>    static assert( __traits(compiles, { baz;       }));</div><div>    static assert(!__traits(compiles, { baz();     }));</div>
<div>    static assert( __traits(compiles, { baz = 1;   }));</div><div>    static assert(!__traits(compiles, { baz() = 1; }));</div><div>    static assert(is(typeof(baz) == Type));</div><div>    static assert(is(typeof(&baz) == ref Type function()));</div>
<div>}</div><div><br></div><div>@property Type foh(Type);</div><div>@property void bah(Type n, Type m);</div><div>@property ref Type bas(Type);</div><div><br></div><div>Type hoo(Type);</div><div>void var(Type, Type);</div>
<div>ref Type vaz(Type);</div><div><br></div><div>unittest</div><div>{</div><div>    static assert( __traits(compiles, { foh = 1; })     && !__traits(compiles, { hoo = 1; }));</div><div>    static assert(!__traits(compiles, { foh(1);  })     &&  __traits(compiles, { hoo(1);  }));</div>
<div>    static assert(!__traits(compiles, { 1.foh;   })     &&  __traits(compiles, { 1.hoo;   }));</div><div>    static assert(!__traits(compiles, { 1.foh(); })     &&  __traits(compiles, { 1.hoo(); }));</div>
<div><br></div><div>    static assert(!__traits(compiles, { bah(1, 2); })   &&  __traits(compiles, { var(1, 2); }));</div><div>    static assert( __traits(compiles, { 1.bah = 2; })   && !__traits(compiles, { 1.var = 2; }));</div>
<div>    static assert(!__traits(compiles, { 1.bah(2);  })   &&  __traits(compiles, { 1.var(2);  }));</div><div><br></div><div>    static assert( __traits(compiles, { bas = 1;     }) && !__traits(compiles, { vaz = 1;     }));</div>
<div>    static assert(!__traits(compiles, { bas(1);      }) &&  __traits(compiles, { vaz(1);      }));</div><div>    static assert(!__traits(compiles, { bas(1) = 2;  }) &&  __traits(compiles, { vaz(1) = 2;  }));</div>
<div>    static assert(!__traits(compiles, { 1.bas;       }) &&  __traits(compiles, { 1.vaz;       }));</div><div>    static assert(!__traits(compiles, { 1.bas = 2;   }) &&  __traits(compiles, { 1.vaz = 2;   }));</div>
<div>    static assert(!__traits(compiles, { 1.bas();     }) &&  __traits(compiles, { 1.vaz();     }));</div><div>    static assert(!__traits(compiles, { 1.bas() = 2; }) &&  __traits(compiles, { 1.vaz() = 2; }));</div>
<div>}</div><div><br></div><div style>Is this correct?</div><div style><br></div><div style>Kenji Hara</div></div></div></div></div></div>