Eigenpoll : D wish list : similar templt/function syntax 

Short version:
Let's combine template and function syntax to make templates and other parts of D easier to use.

Long version:
I have an idea for a completely new template syntax that is easier to use and implement. I'll explain it in therms of a hypothetical language called Dscript. Let's start by imagining that Dscript works identically to D 2.0, but it is interpreted and dynamically typed, with eval's (this is not intended to be implemented, and not the main point of this post). Obviously there isn't much of a point to creating two languages with the same syntax, especially since Dscript would be useless for systems programming, contradicting one of the design goals of D. However, there are some things that you can't do if you have static type enforcement. For example, in D this is impossible:

template foo(string Type) {
invariant foo = eval(Type ~ ".init");

but it would be legal in Dscript. The point of templates in D is compile-time evaluation of functions and compile-time creation of types, but if Dscript is going to be interpreted, templates will obviously not get instantiated until they are used since I could write:

string type = readLine();

If they are not going to be evaluated until run-time, they become identical to functions. For syntactic clarity, Dscript could remove templates altogether and replace them with functions:

eval(Type) foo(string Type) {
return eval(Type ~ ".init");

If you don't like the idea of the return type being an eval, remember that Dscript is dynamically typed and is not supposed to be implemented. I'm just writing the type to make the next step easier: bringing this back to D. First, we have to eliminate eval. Well, I have only been using it to convert strings into types, so what if we made a type type?

type myint = int; //we don't need alias anymore
type myOtherInt : int; //or typedef, note the colon
type[3] threeIntegers = [short, int, long]; //and tuples are now built-ins

// ! syntax is obsolete too, because templates are functions
to(myint, 13.7);

//and is-expressions are simpler
if(int <= float) {
writeln("int is cast-able or identical to float.");

if(myint == int) {
writeln("myint and int are the same type.");

import std.socket;

if(UdpSocket <: Socket) {
writeln("UdpSocket extends Socket.");

Everything is so much simpler!

This is easier for both programmers and compilers, but we still have one problem: dynamic typing. This isn't too hard to eliminate, though; we just have to make sure that whenever we use a type, it's known at compile time. This checking is already in place, for example integer template parameters are known at compile-time. If necessary, it can also be easily accomplished by making types immutable. What about templates with non-type parameters, such int's? Simple:

int bar(string str, static int abc, type T)

abc must be known at compile-time, since it is static. T can be regarded as implicitly static, just as str, being declared string instead of char[], is implicitly invariant in D 2.0. A template is instantiated for each unique set of static parameters, giving either a function (pointer), a new type (struct/class), or whatever else could be templated. Now we have our static typing back.

The last use of templates is compile-time function evaluation. There is already a better way to do this in D. instead of writing a function twice, once normally, and once confusingly using recursive templates, just say:

static int a = baz('a', 5, "asdf");

The static keyword tells it to evaluate at compile time, similar to my proposed use of static. This is recommended, instead of the template approach, at http://www.digitalmars.com/d/2.0/templates-revisited.html, just before the section on SFINAE.

We've created a language just like D, except it simplifies alias's, typedef's, tuples, is expressions, and especially templates, all the confusing and hard-to-learn aspects. Instead, we have the much more elegant syntax of types.


Report this item for cleanup