www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Templates and Generic Programming

reply Sha Chancellor <schancel pacific.net> writes:
#import std.c.stdio;

#class Foo(T) {
#  alias T baseType;
#  /* ... */
#}

#int main( char[][] args )
#{
#  Foo!(int) f = new Foo!(int); //Redundant
#
#  f.baseType s = 10;  //Why Doesn't this work?!
#  //This allows you to declare variables that are related to f
#  // without somehow already knowing F's template types.
#
#  Foo!(int).baseType t = 10; //Why does only this work???
#  // This works fine if you know F is has a template type of int.
#  // Unfortunately I don't know of a way to find s's
#  // template types at runtime if you don't already know it.
#
#
#
#  // The compiler it seems should know what T is,
#  // why can't it make the previous declaration work?
#  
#  return 0;
#}


For generic programming, as Matthew mentioned earlier.  There should be 
a way to deduce base types.  There's no good generic way to do this 
besides aliases.  What should we do:

Foo!(int,char,float) f = new Foo!(int,char,float) (BTW, wtf do we need 
to specify this stuff twice? Should be implicit if you leave it off...)

template_type( f, 0 ) = int?
template_type( f, 1 ) = char?
template_type( f, 2 ) = float?

This seems klunky.   Rather specifying aliases in the classes for the 
ones you'd need seems like a better solution... If only it worked.
Jul 29 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Sha Chancellor" <schancel pacific.net> wrote in message
news:schancel-0DEA5D.10244529072004 digitalmars.com...
 #import std.c.stdio;

 #class Foo(T) {
 #  alias T baseType;
 #  /* ... */
 #}

 #int main( char[][] args )
 #{
 #  Foo!(int) f = new Foo!(int); //Redundant
 #
 #  f.baseType s = 10;  //Why Doesn't this work?!
 #  //This allows you to declare variables that are related to f
 #  // without somehow already knowing F's template types.
 #
 #  Foo!(int).baseType t = 10; //Why does only this work???
 #  // This works fine if you know F is has a template type of int.
 #  // Unfortunately I don't know of a way to find s's
 #  // template types at runtime if you don't already know it.
 #
 #
 #
 #  // The compiler it seems should know what T is,
 #  // why can't it make the previous declaration work?
 #
 #  return 0;
 #}


 For generic programming, as Matthew mentioned earlier.  There should be
 a way to deduce base types.  There's no good generic way to do this
 besides aliases.  What should we do:

 Foo!(int,char,float) f = new Foo!(int,char,float) (BTW, wtf do we need
 to specify this stuff twice? Should be implicit if you leave it off...)

 template_type( f, 0 ) = int?
 template_type( f, 1 ) = char?
 template_type( f, 2 ) = float?

 This seems klunky.   Rather specifying aliases in the classes for the
 ones you'd need seems like a better solution... If only it worked.

As we've begged for for a long time, we need an autotype (or similar keyword), e.g. autotype f = new Foo!(int,char,float); rather than Foo!(int,char,float) f = new Foo!(int,char,float) I can't see that this would be terribly hard to do, since the compiler already knows the type returned, so this could be a moderate step with minimum effort. Much easier than implicit instantiation, eh Walter?
Jul 29 2004
next sibling parent reply James Widman <james jwidman.com> writes:
In article <cec1ml$1tlt$2 digitaldaemon.com>,
 "Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote:

 As we've begged for for a long time, we need an autotype (or similar 
 keyword), e.g.
 
     autotype f = new Foo!(int,char,float);
 
 rather than
 
     Foo!(int,char,float) f = new Foo!(int,char,float)

How about: Foo!(int,char,float) f = new(); Foo!(int,char,float)[] f = new[5]; ...with the assumption that if 'new' is followed immediately by '(', '[', or ';', then it's just as if we saw: Foo!(int,char,float) f = new typeof(f)(/* args to this() */); Would that throw a big monkey wrench in the parser?
Jul 29 2004
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"James Widman" <james jwidman.com> wrote in message
news:james-B2BBCF.20133029072004 digitalmars.com...
 In article <cec1ml$1tlt$2 digitaldaemon.com>,
  "Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote:

 As we've begged for for a long time, we need an autotype (or similar
 keyword), e.g.

     autotype f = new Foo!(int,char,float);

 rather than

     Foo!(int,char,float) f = new Foo!(int,char,float)

How about: Foo!(int,char,float) f = new(); Foo!(int,char,float)[] f = new[5]; ...with the assumption that if 'new' is followed immediately by '(', '[', or ';', then it's just as if we saw: Foo!(int,char,float) f = new typeof(f)(/* args to this() */); Would that throw a big monkey wrench in the parser?

It'd throw a huge wrench in DTL. You'd be writing very, very, very long types.
Jul 29 2004
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 30 Jul 2004 09:29:47 +1000, Matthew wrote:

 "Sha Chancellor" <schancel pacific.net> wrote in message
news:schancel-0DEA5D.10244529072004 digitalmars.com...
 #import std.c.stdio;

 #class Foo(T) {
 #  alias T baseType;
 #  /* ... */
 #}

 #int main( char[][] args )
 #{
 #  Foo!(int) f = new Foo!(int); //Redundant
 #
 #  f.baseType s = 10;  //Why Doesn't this work?!
 #  //This allows you to declare variables that are related to f
 #  // without somehow already knowing F's template types.
 #
 #  Foo!(int).baseType t = 10; //Why does only this work???
 #  // This works fine if you know F is has a template type of int.
 #  // Unfortunately I don't know of a way to find s's
 #  // template types at runtime if you don't already know it.
 #
 #
 #
 #  // The compiler it seems should know what T is,
 #  // why can't it make the previous declaration work?
 #
 #  return 0;
 #}


 For generic programming, as Matthew mentioned earlier.  There should be
 a way to deduce base types.  There's no good generic way to do this
 besides aliases.  What should we do:

 Foo!(int,char,float) f = new Foo!(int,char,float) (BTW, wtf do we need
 to specify this stuff twice? Should be implicit if you leave it off...)

 template_type( f, 0 ) = int?
 template_type( f, 1 ) = char?
 template_type( f, 2 ) = float?

 This seems klunky.   Rather specifying aliases in the classes for the
 ones you'd need seems like a better solution... If only it worked.

As we've begged for for a long time, we need an autotype (or similar keyword), e.g. autotype f = new Foo!(int,char,float); rather than Foo!(int,char,float) f = new Foo!(int,char,float) I can't see that this would be terribly hard to do, since the compiler already knows the type returned, so this could be a moderate step with minimum effort. Much easier than implicit instantiation, eh Walter?

How about something like ... new Foo!(int,char,float) f; as a complete statement. class Bar{} new Bar b; new int i; seems easy to understand and write. The 'new' creates a newly initialized instance of the 'type'. Classes are created on the heap and everything else on the stack. Thus it would be redundant for intrinsic types and structs but shouldn't be a issue if used. -- Derek Melbourne, Australia 30/Jul/04 10:34:39 AM
Jul 29 2004
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Derek Parnell" <derek psych.ward> wrote in message
news:cec5bd$1v91$1 digitaldaemon.com...
 On Fri, 30 Jul 2004 09:29:47 +1000, Matthew wrote:

 "Sha Chancellor" <schancel pacific.net> wrote in message
news:schancel-0DEA5D.10244529072004 digitalmars.com...
 #import std.c.stdio;

 #class Foo(T) {
 #  alias T baseType;
 #  /* ... */
 #}

 #int main( char[][] args )
 #{
 #  Foo!(int) f = new Foo!(int); //Redundant
 #
 #  f.baseType s = 10;  //Why Doesn't this work?!
 #  //This allows you to declare variables that are related to f
 #  // without somehow already knowing F's template types.
 #
 #  Foo!(int).baseType t = 10; //Why does only this work???
 #  // This works fine if you know F is has a template type of int.
 #  // Unfortunately I don't know of a way to find s's
 #  // template types at runtime if you don't already know it.
 #
 #
 #
 #  // The compiler it seems should know what T is,
 #  // why can't it make the previous declaration work?
 #
 #  return 0;
 #}


 For generic programming, as Matthew mentioned earlier.  There should be
 a way to deduce base types.  There's no good generic way to do this
 besides aliases.  What should we do:

 Foo!(int,char,float) f = new Foo!(int,char,float) (BTW, wtf do we need
 to specify this stuff twice? Should be implicit if you leave it off...)

 template_type( f, 0 ) = int?
 template_type( f, 1 ) = char?
 template_type( f, 2 ) = float?

 This seems klunky.   Rather specifying aliases in the classes for the
 ones you'd need seems like a better solution... If only it worked.

As we've begged for for a long time, we need an autotype (or similar keyword), e.g. autotype f = new Foo!(int,char,float); rather than Foo!(int,char,float) f = new Foo!(int,char,float) I can't see that this would be terribly hard to do, since the compiler already knows the type returned, so this


 a moderate step with minimum effort. Much easier than implicit instantiation,
eh Walter?

How about something like ... new Foo!(int,char,float) f; as a complete statement. class Bar{} new Bar b; new int i; seems easy to understand and write. The 'new' creates a newly initialized instance of the 'type'. Classes are created on the heap and everything else on the stack. Thus it would be redundant for intrinsic types and structs but shouldn't be a issue if used.

But that's missing the point. The ideal is to not have to worry about the specific type of a function return, and simply to write your code in accordance to that type's expected operations. It's kind of a typeless programming, with compile-time type checking. (Cake & eating it, if you will.) A good example of this would be where one might apply a transformation operation to a selected element from a container, ie. template someFunc(X) { void someFunc(. . . { autotype x = cont.select(IsOdd).collect!(X).max(); If cont contains ints, but the X functor transforms to some other type, we can still manipulate the instance x of that "other type", without knowing its precise type. All we know is that it will fulfil the intended operations we subject it to, and because the compiler knows the return type from "cont.select(IsOdd).collect!(X).max();" it can ensure that it will.
Jul 29 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Fri, 30 Jul 2004 12:02:14 +1000, Matthew wrote:

 "Derek Parnell" <derek psych.ward> wrote in message
news:cec5bd$1v91$1 digitaldaemon.com...
 On Fri, 30 Jul 2004 09:29:47 +1000, Matthew wrote:

 "Sha Chancellor" <schancel pacific.net> wrote in message
news:schancel-0DEA5D.10244529072004 digitalmars.com...
 #import std.c.stdio;

 #class Foo(T) {
 #  alias T baseType;
 #  /* ... */
 #}

 #int main( char[][] args )
 #{
 #  Foo!(int) f = new Foo!(int); //Redundant
 #
 #  f.baseType s = 10;  //Why Doesn't this work?!
 #  //This allows you to declare variables that are related to f
 #  // without somehow already knowing F's template types.
 #
 #  Foo!(int).baseType t = 10; //Why does only this work???
 #  // This works fine if you know F is has a template type of int.
 #  // Unfortunately I don't know of a way to find s's
 #  // template types at runtime if you don't already know it.
 #
 #
 #
 #  // The compiler it seems should know what T is,
 #  // why can't it make the previous declaration work?
 #
 #  return 0;
 #}


 For generic programming, as Matthew mentioned earlier.  There should be
 a way to deduce base types.  There's no good generic way to do this
 besides aliases.  What should we do:

 Foo!(int,char,float) f = new Foo!(int,char,float) (BTW, wtf do we need
 to specify this stuff twice? Should be implicit if you leave it off...)

 template_type( f, 0 ) = int?
 template_type( f, 1 ) = char?
 template_type( f, 2 ) = float?

 This seems klunky.   Rather specifying aliases in the classes for the
 ones you'd need seems like a better solution... If only it worked.

As we've begged for for a long time, we need an autotype (or similar keyword), e.g. autotype f = new Foo!(int,char,float); rather than Foo!(int,char,float) f = new Foo!(int,char,float) I can't see that this would be terribly hard to do, since the compiler already knows the type returned, so this


 a moderate step with minimum effort. Much easier than implicit instantiation,
eh Walter?

How about something like ... new Foo!(int,char,float) f; as a complete statement. class Bar{} new Bar b; new int i; seems easy to understand and write. The 'new' creates a newly initialized instance of the 'type'. Classes are created on the heap and everything else on the stack. Thus it would be redundant for intrinsic types and structs but shouldn't be a issue if used.

But that's missing the point.

That maybe true. However, I was replying to the point raised above, and I requote .. " As we've begged for for a long time, we need an autotype (or similar keyword), e.g. autotype f = new Foo!(int,char,float); rather than Foo!(int,char,float) f = new Foo!(int,char,float) " This seemed to be dealing with the declaration of variables and not function execution. My mistake.
 The ideal is to not have to worry about the specific type of a function
return, and simply
 to write your code in accordance to that type's expected operations. It's kind
of a typeless programming, with
 compile-time type checking. (Cake & eating it, if you will.)

So in general, are you saying ... The generic *syntax* form of variable declaration is <datatype> <identifier> ['=' <initialization>] ';' and if the <datatype> is "autotype" then the compiler will use the datatype of the <initialization> expression? This is a useful idea. I'm not saying otherwise. Yep, sounds okay to me. It could mean a serious rethink of how the current compiler is written, as it may now have to defer decisions until the <initialization> datatype is known (ie, the function might be forward-referenced). -- Derek Melbourne, Australia 30/Jul/04 12:05:20 PM
Jul 29 2004
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Derek Parnell" <derek psych.ward> wrote in message
news:cecbjb$21ho$1 digitaldaemon.com...
 On Fri, 30 Jul 2004 12:02:14 +1000, Matthew wrote:

 "Derek Parnell" <derek psych.ward> wrote in message
news:cec5bd$1v91$1 digitaldaemon.com...
 On Fri, 30 Jul 2004 09:29:47 +1000, Matthew wrote:

 "Sha Chancellor" <schancel pacific.net> wrote in message
news:schancel-0DEA5D.10244529072004 digitalmars.com...
 #import std.c.stdio;

 #class Foo(T) {
 #  alias T baseType;
 #  /* ... */
 #}

 #int main( char[][] args )
 #{
 #  Foo!(int) f = new Foo!(int); //Redundant
 #
 #  f.baseType s = 10;  //Why Doesn't this work?!
 #  //This allows you to declare variables that are related to f
 #  // without somehow already knowing F's template types.
 #
 #  Foo!(int).baseType t = 10; //Why does only this work???
 #  // This works fine if you know F is has a template type of int.
 #  // Unfortunately I don't know of a way to find s's
 #  // template types at runtime if you don't already know it.
 #
 #
 #
 #  // The compiler it seems should know what T is,
 #  // why can't it make the previous declaration work?
 #
 #  return 0;
 #}


 For generic programming, as Matthew mentioned earlier.  There should be
 a way to deduce base types.  There's no good generic way to do this
 besides aliases.  What should we do:

 Foo!(int,char,float) f = new Foo!(int,char,float) (BTW, wtf do we need
 to specify this stuff twice? Should be implicit if you leave it off...)

 template_type( f, 0 ) = int?
 template_type( f, 1 ) = char?
 template_type( f, 2 ) = float?

 This seems klunky.   Rather specifying aliases in the classes for the
 ones you'd need seems like a better solution... If only it worked.

As we've begged for for a long time, we need an autotype (or similar keyword), e.g. autotype f = new Foo!(int,char,float); rather than Foo!(int,char,float) f = new Foo!(int,char,float) I can't see that this would be terribly hard to do, since the compiler already knows the type returned, so this


 a moderate step with minimum effort. Much easier than implicit instantiation,
eh Walter?

How about something like ... new Foo!(int,char,float) f; as a complete statement. class Bar{} new Bar b; new int i; seems easy to understand and write. The 'new' creates a newly initialized instance of the 'type'. Classes are created on the heap and everything else on the stack. Thus it would be redundant for intrinsic types and structs but shouldn't be a issue if used.

But that's missing the point.

That maybe true. However, I was replying to the point raised above, and I requote .. " As we've begged for for a long time, we need an autotype (or similar keyword), e.g. autotype f = new Foo!(int,char,float); rather than Foo!(int,char,float) f = new Foo!(int,char,float) " This seemed to be dealing with the declaration of variables and not function execution. My mistake.

No, it was mine for not being clear enough.
 The ideal is to not have to worry about the specific type of a function
return, and simply
 to write your code in accordance to that type's expected operations. It's kind
of a typeless programming, with
 compile-time type checking. (Cake & eating it, if you will.)

So in general, are you saying ... The generic *syntax* form of variable declaration is <datatype> <identifier> ['=' <initialization>] ';' and if the <datatype> is "autotype" then the compiler will use the datatype of the <initialization> expression? This is a useful idea. I'm not saying otherwise. Yep, sounds okay to me. It could mean a serious rethink of how the current compiler is written, as it may now have to defer decisions until the <initialization> datatype is known (ie, the function might be forward-referenced).

Not sure. I wouldn't think it'd be that serious, since the type of <initialisation> *is* already known at that time. Dunno, really. That's Walter's area.
Jul 29 2004