www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Configurable syntax

reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 1. Allow inner name promotion even if the template defines other
 members, as long as they are all private:

 now:

 template WidgetImpl(A, B) {
      ...
      alias ... Result;
 }

 template Widget(A, B) {
      alias WidgetImpl!(A, B) Widget;
 }

 proposed:

 template Widget(A, B) {
 private:
      ...
      alias ... Result;
 public:
      alias Widget Result;
 }

 It's needed very frequently, puts sand in the eye, and almost sure to
 throw off the casual reader.

The D1 documentation says:
Implicit Template Properties: If a template has exactly one member in it, and
the name of that member is the same as the template name, that member is
assumed to be referred to in a template instantiation:<

Two possible ideas: 1) If it contains a member with the name of the template (and other names), it can be referred anyway with the name of the template: template Foo(T) { T Foo; T[] Bar; } void test() { Foo!(int) = 6; // equal to Foo!(int).Foo anyway } This may lead to troubles I am not seeing yet. ---------------- 2) Having private and public members as in your example solves the problem, but it may be overkill, because in many situations you have only one public name, plus some private ones. So a 'return' may be used: template WidgetImpl(A, B) { T[] Bar; T Foo; return Foo; } template WidgetImpl(A, B) { ... return Result; } This doesn't allow you to hide names from the outside, but helps you avoid having a second template. Having a return also helps to see templates as closer to compile-time functions (changing few things there may be ways to merge the syntax of templates with the syntax of compile time functions, reducing the complexity of D). Bye, bearophile
May 22 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
bearophile:
 Having a return also helps to see templates as closer to compile-time
functions (changing few things there may be ways to merge the syntax of
templates with the syntax of compile time functions, reducing the complexity of
D).<

To write some templates as compile-time functions you may need to add a new type to D, named "type": type foo(type T) { return T[]; } That is the same as: template Foo(T) { alias T[] Foo; } Bye, bearophile
May 22 2009
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
bearophile:
To write some templates as compile-time functions you may need to add a new
type to D, named "type":<

To see if the idea of compile-time functions that process compile-time variables of type "type" isn't fully crazy I have translated some of the D1 templates of my dlibs into such compile-time functions. The following code shows a template and its possible translation. The code is of course untested and there can be many mistakes of mine. // ------------------------------- private template AA_impl(KeyType, ValueType) { ValueType[KeyType] result; const ValueType[KeyType] res = result; } template AA(KeyType, ValueType) { const ValueType[KeyType] AA = AA_impl!(KeyType, ValueType).res; } TyVal[TyKey] newaa(type TyKey, type TyVal) { TyVal[TyKey] aa; return aa; } // ------------------------------- template AAKeyType(T) { alias typeof(T.keys[0]) AAKeyType; } template AAValType(T) { alias typeof(T.values[0]) AAValType; } type aaKeyType(TV, TK)(TV[TK] aa) { return TK; } type aaValType(TV, TK)(TV[TK] aa) { return TV; } type aaKeyType(TV, TK)(type TV[TK]) { return TK; } type aaValType(TV, TK)(type TV[TK]) { return TV; } // ------------------------------- template ALL(alias Predicate, Types...) { static if (Types.length == 0) const bool ALL = true; else const bool ALL = Predicate!(Types[0]) && ALL!(Predicate, Types[1 .. $]); } bool All(alias pred, type[] types...) { static foreach (T; types) static if (!pred(T)) return false; return true; } ANY/Any are similar. // ------------------------------- template BaseTypedef(T) { static if( is( T BaseType1 == typedef ) ) alias BaseTypedef!(BaseType1) BaseTypedef; else alias T BaseTypedef; } type baseTypedef(type T) { // the syntax of is() may be improved in many ways static while ( is( T BaseType1 == typedef ) ) T = BaseType1; return T; } A problem of the "static foreach" (that Walter will face) is that templates are functional, so their values are immutable. And Scheme shows that in a language with no mutability it's not much useful to have for/foreach loops. In that "static while" loop the variable T of type type, is a mutable. // ------------------------------- template CastableTypes(Types...) { static if (Types.length <= 1) const CastableTypes = true; else const CastableTypes = is(typeof(Types[0] == Types[1])) && CastableTypes!(Types[1 .. $]); } bool areCastableTypes(type[] Types)(type... types) { static foreach (T; types[1 .. $]) static if (!is(typeof(Types[0] == Types[1]))) return false; return true; } // ------------------------------- template DeconstArrayType(T) { static if (IsStaticArray!(T)) alias typeof(T[0])[] DeconstArrayType; else alias T DeconstArrayType; } (DeconstArrayType works if T isn't a static array, this is very useful in my code) type deconstArrayType(type T) { static if (isStaticArray!(T)) return typeof(T[0])[]; //return (T[0]).typeof[]; else return T; } // ------------------------------- template IsType(T, Types...) { // Original idea by Burton Radons, modified static if (Types.length == 0) const bool IsType = false; else const bool IsType = is(T == Types[0]) || IsType!(T, Types[1 .. $]); } bool isType(T, type[] types...) { static foreach (TX; types) // now == works among run-time variables of type "type". static if (T == TX) return true; return false; } Or even simpler, if the compiler understands that isType is a compile-time-function-only: bool isType(T, type[] types...) { foreach (TX; types) if (T == TX) return true; return false; } With Any() and a compile-time lambda you can write: bool isType(T, type[] types...) { return Any((type TX){ return T == TX; }, types); } :-) // ------------------------------- Bye, bearophile
May 22 2009
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:gv6e4p$1m3f$1 digitalmars.com...
 bearophile:
 Having a return also helps to see templates as closer to compile-time 
 functions (changing few things there may be ways to merge the syntax of 
 templates with the syntax of compile time functions, reducing the 
 complexity of D).<

To write some templates as compile-time functions you may need to add a new type to D, named "type": type foo(type T) { return T[]; }

Yea, that's one thing I kind of miss from the VM languages like C#/Java. I been really wanting to see that in D.
May 22 2009
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
bearophile Wrote:

 bearophile:
 Having a return also helps to see templates as closer to compile-time
functions (changing few things there may be ways to merge the syntax of
templates with the syntax of compile time functions, reducing the complexity of
D).<

To write some templates as compile-time functions you may need to add a new type to D, named "type": type foo(type T) { return T[]; } That is the same as: template Foo(T) { alias T[] Foo; }

I'd love to see compile-time functions returning types. IMHO, it's far superior to the template-based approach. There are several reasons for this: 1. The template scheme violates the DRY principle. It's like type constructors in C++, Java, etc... D was designed to better than that! 2. Function calls make it far clearer what the intent is. Once templates are allowed to have more members, the true purpose will be obfuscated. 3. It opens up possibilities for better (compile-time) reflection. That being said, it's possible for templates to define an instance with unknown type and value. A non-templated function returning either a type or value can't do that.
May 22 2009
parent bearophile <bearophileHUGS lycos.com> writes:
Jason House:
 I'd love to see compile-time functions returning types.<

Glad to see my post appreciated :-)
IMHO, it's far superior to the template-based approach.<

Even if such compile-time functions can't fully replace templates (so templates can't be removed from the language) such functions may be a significant improvement anyway. I have shown some examples in another post. But for some of those functions you may enjoy having a "static while" too :-) Probably you can even write things like: auto foo(type T) { static if (T == int) return 1; else return T[]; }
it's possible for templates to define an instance with unknown type and value.
A non-templated function returning either a type or value can't do that.<

Can you explain better or show an example? Bye, bearophile
May 22 2009