Jump to page: 1 2
Thread overview
Implicit instantiation of parameterless templates
Oct 05, 2012
Piotr Szturmaj
Oct 05, 2012
Paulo Pinto
Oct 05, 2012
Piotr Szturmaj
Oct 05, 2012
David Piepgrass
Oct 05, 2012
F i L
Oct 05, 2012
Dmitry Olshansky
Oct 05, 2012
F i L
Oct 05, 2012
Piotr Szturmaj
Oct 05, 2012
Maxim Fomin
Oct 05, 2012
Paulo Pinto
Oct 06, 2012
Paulo Pinto
Oct 05, 2012
F i L
October 05, 2012
Java and C# with their generics can do the following:

class List { }
class List<T> { }

List list = new List();
List<int> intList = new List<int>();

In D similar code can't work because we can't have both a type and a template with the same name. So this code must be rewritten to:

class List(T = Variant) { }

List!() list = new List!();
List!int intList = new List!int;

When template name is used as a type and it can be instantiated with no parameters it could be automatically rewritten to List!() by the compiler. That code would then look like this:

List list = new List;
List!int intList = new List!int;

The question is... is it possible to change D's behaviour to avoid awkward !() template parameters _without_ breaking backward compatibility?
October 05, 2012
On Friday, 5 October 2012 at 12:01:30 UTC, Piotr Szturmaj wrote:
> Java and C# with their generics can do the following:
>
> class List { }
> class List<T> { }
>
> List list = new List();
> List<int> intList = new List<int>();
>
> In D similar code can't work because we can't have both a type and a template with the same name. So this code must be rewritten to:
>
> class List(T = Variant) { }
>
> List!() list = new List!();
> List!int intList = new List!int;
>
> When template name is used as a type and it can be instantiated with no parameters it could be automatically rewritten to List!() by the compiler. That code would then look like this:
>
> List list = new List;
> List!int intList = new List!int;
>
> The question is... is it possible to change D's behaviour to avoid awkward !() template parameters _without_ breaking backward compatibility?

Why to you need this?

Java and C# only allow this type of code due to backwards compatibility, because their first version did not allow for generics, and their creators did not want to force everyone to recode their code bases.

--
Paulo

October 05, 2012
Paulo Pinto wrote:
> On Friday, 5 October 2012 at 12:01:30 UTC, Piotr Szturmaj wrote:
>> Java and C# with their generics can do the following:
>>
>> class List { }
>> class List<T> { }
>>
>> List list = new List();
>> List<int> intList = new List<int>();
>>
>> In D similar code can't work because we can't have both a type and a
>> template with the same name. So this code must be rewritten to:
>>
>> class List(T = Variant) { }
>>
>> List!() list = new List!();
>> List!int intList = new List!int;
>>
>> When template name is used as a type and it can be instantiated with
>> no parameters it could be automatically rewritten to List!() by the
>> compiler. That code would then look like this:
>>
>> List list = new List;
>> List!int intList = new List!int;
>>
>> The question is... is it possible to change D's behaviour to avoid
>> awkward !() template parameters _without_ breaking backward
>> compatibility?
>
> Why to you need this?

For convenience. In the above example, List without parameters could handle any value (as Variant), but I can always specialize it for some type. List (which would be List!()) would then become a shortcut to List!Variant.

> Java and C# only allow this type of code due to backwards compatibility,
> because their first version did not allow for generics, and their
> creators did not want to force everyone to recode their code bases.

Yes, but it's more convenient to write List than List<Object>. And in D: List vs List!().
October 05, 2012
On Friday, 5 October 2012 at 12:24:12 UTC, Paulo Pinto wrote:
> On Friday, 5 October 2012 at 12:01:30 UTC, Piotr Szturmaj wrote:
>> Java and C# with their generics can do the following:
>>
>> class List { }
>> class List<T> { }
>>
>> List list = new List();
>> List<int> intList = new List<int>();
>>
>> In D similar code can't work because we can't have both a type and a template with the same name. So this code must be rewritten to:
...
>
> Why to you need this?
>
> Java and C# only allow this type of code due to backwards compatibility, because their first version did not allow for generics, and their creators did not want to force everyone to recode their code bases.

The Java and C# situations are very different. In Java, generics are "erased" at runtime so a List<int> is the same thing as a List. In C#/.NET, however, List<int> and List are 'unrelated' types, which is what Piotr was talking about.

.NET allows "overloading" types based on the number of generic parameters, so for example Tuple<X> is a different type than Tuple<X,Y> (the runtime names are Tuple`1 and Tuple`2). Since C# has no "default arguments" for generics or "tuple template parameters", it is trivial to allow different types that have the same name but a different number of generic parameters. In D, however, the situation is a bit more complicated.
October 05, 2012
On Friday, 5 October 2012 at 12:01:30 UTC, Piotr Szturmaj wrote:
> Java and C# with their generics can do the following:
>
> class List { }
> class List<T> { }
>
> List list = new List();
> List<int> intList = new List<int>();
>
> In D similar code can't work because we can't have both a type and a template with the same name. So this code must be rewritten to:
>
> class List(T = Variant) { }
>
> List!() list = new List!();
> List!int intList = new List!int;
>
> When template name is used as a type and it can be instantiated with no parameters it could be automatically rewritten to List!() by the compiler. That code would then look like this:
>
> List list = new List;
> List!int intList = new List!int;
>
> The question is... is it possible to change D's behaviour to avoid awkward !() template parameters _without_ breaking backward compatibility?

+1 This is natural.

Plus, this has other uses I've mentioned on here in the past, "sub-scoping":

    class Foo
    {
        int bar;

        template baz
        {
            int bar;
        }
    }

    void main()
    {
        auto f = new Foo();

        f.bar = 0;
        f.baz.bar = 1;
    }

Currently, this syntax is possible, but requires to some ugly work-arounds.
October 05, 2012
On 05-Oct-12 23:25, F i L wrote:
> On Friday, 5 October 2012 at 12:01:30 UTC, Piotr Szturmaj wrote:
>> Java and C# with their generics can do the following:
>>
>> class List { }
>> class List<T> { }
>>
>> List list = new List();
>> List<int> intList = new List<int>();
>>
>> In D similar code can't work because we can't have both a type and a
>> template with the same name. So this code must be rewritten to:
>>
>> class List(T = Variant) { }
>>
>> List!() list = new List!();
>> List!int intList = new List!int;
>>
>> When template name is used as a type and it can be instantiated with
>> no parameters it could be automatically rewritten to List!() by the
>> compiler. That code would then look like this:
>>
>> List list = new List;
>> List!int intList = new List!int;
>>
>> The question is... is it possible to change D's behaviour to avoid
>> awkward !() template parameters _without_ breaking backward
>> compatibility?
>
> +1 This is natural.
>
> Plus, this has other uses I've mentioned on here in the past,
> "sub-scoping":
>
>      class Foo
>      {
>          int bar;
>
>          template baz
>          {
>              int bar;
>          }
>      }
>
>      void main()
>      {
>          auto f = new Foo();
>
>          f.bar = 0;
>          f.baz.bar = 1;
>      }
>
> Currently, this syntax is possible, but requires to some ugly work-arounds.

Hm... If placed at the global scope it looks like a namespace.

-- 
Dmitry Olshansky
October 05, 2012
Dmitry Olshansky wrote:
> Hm... If placed at the global scope it looks like a namespace.

I don't see anything wrong with that. It's just another way (somewhat unique to D) you can categorize your code. Most people probably won't use this sort of thing all over the place, but it actually might be useful for "enforcing" naming classifications:

    // File system/io.d

    template Console
    {
        void write( ... )
        void read()
    }

    template File
    {
        void write( ... )
        void read()
    }


    // File something.d

    import system.io;

    void main()
    {
        // Prefix 'Console/File' required so to the
        // user, it looks somewhat like a static object

        Console.write( ... );
        File.write( ... );
    }
October 05, 2012
F i L wrote:
> Dmitry Olshansky wrote:
>> Hm... If placed at the global scope it looks like a namespace.
>
> I don't see anything wrong with that. It's just another way (somewhat
> unique to D) you can categorize your code. Most people probably won't
> use this sort of thing all over the place, but it actually might be
> useful for "enforcing" naming classifications:
>
>      // File system/io.d
>
>      template Console
>      {
>          void write( ... )
>          void read()
>      }

final abstract class Console
{
    static:
    void write() { }
    void read() { }
}

Console.write();

P.S. Yes, simultaneous final and abstract actually works :)
October 05, 2012
On Friday, 5 October 2012 at 20:19:26 UTC, Piotr Szturmaj wrote:
> F i L wrote:
>> Dmitry Olshansky wrote:
>>> Hm... If placed at the global scope it looks like a namespace.
>>
>> I don't see anything wrong with that. It's just another way (somewhat
>> unique to D) you can categorize your code. Most people probably won't
>> use this sort of thing all over the place, but it actually might be
>> useful for "enforcing" naming classifications:
>>
>>     // File system/io.d
>>
>>     template Console
>>     {
>>         void write( ... )
>>         void read()
>>     }
>
> final abstract class Console
> {
>     static:
>     void write() { }
>     void read() { }
> }
>
> Console.write();
>
> P.S. Yes, simultaneous final and abstract actually works :)

Thanks to how dmd parses code, many simultaneous things actually work, sometimes it is nonsense http://dpaste.dzfl.pl/04e6bf33
October 05, 2012
Piotr Szturmaj wrote:
> final abstract class Console
> {
>     static:
>     void write() { }
>     void read() { }
> }
>
> Console.write();
>
> P.S. Yes, simultaneous final and abstract actually works :)

Yes, I know there are other ways to do this, like you mentioned above. However, parameter-less templates would still be nice for scopes withing a Class (like my original example). Like I mentioned, it's possible today:

    class Foo
    {
        int bar;

        alias Baz!() baz;
        template Baz()
        {
            int bar;
        }
    }

    auto foo = new Foo();

    foo.bar = 10;
    foo.baz.bar = 10; // Same as..
    foo.Baz!().bar = 10; // ..writing this.

However, like OP is suggesting, it would be nice to have syntax-sugar to eliminate the need for extra typing at instantiation and at definition (my suggestion). The fact that these odd '!()' symbols are required will probably detour less-experienced people from using this feature today.
« First   ‹ Prev
1 2