October 06, 2008
On 2008-10-05 22:23:16 -0400, Michel Fortin <michel.fortin@michelf.com> said:

> Well, not so sure about that: I'm pretty sure it's needed for disambiguation too. Let's say you have:
> 
> 	void foo(int x)();
> 	void foo(T)(T x);
> 
> 	foo(5);
> 
> Is foo(5) a the same as foo!(5), or does it call foo!(int).foo(5) ? Under the current rules, it's the second (you can write foo!(5) to call the first). If you allow templates to be instanciated without the "!", then I guess both will match and you'll have ambiguity.
> 
> If you could avoid having sets of parameters, one for the function and one for the template, then you could get rid of the "!" in a snap...

Or... we could just disallow having both at the same time, just like you can't have two functions with the same arguments. A call to foo(5) would be ambigous in the above situation, plain and simple. Is this reasonable?

We could still disambiguate using:

	foo!(5);

and:

	foo(int)(5);

In this context, the ! becomes the "force this to be template arguments" operator, or the "do not deduce template arguments, I'll provide them" operator.

Or we could just forget ! completely and leave the first one impossible to disambiguate.

Which makes me think that it's sad we can't write the second as:

	foo(int, 5);

I'd be much nicer to the eye.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

October 06, 2008
Sun, 05 Oct 2008 09:44:39 -0500,
Andrei Alexandrescu wrote:
> Adam D. Ruppe wrote:
> > On Sun, Oct 05, 2008 at 09:29:37AM -0500, Andrei Alexandrescu wrote:
> >> Heh. So this change should come together with abolishing goto :o).
> > 
> > Noooooooooooooooooooooooooo!
> 
> No worries. Goto to Walter is what money is to Swiss banks. :o)
> 
> Andrei
> 
> P.S. I have one goto in my code too.

Maybe not gotos, but labelled breaks and continues might come in very handy sometimes.
October 06, 2008
On Mon, 06 Oct 2008 14:56:43 +0400, Michel Fortin <michel.fortin@michelf.com> wrote:

> On 2008-10-05 22:23:16 -0400, Michel Fortin <michel.fortin@michelf.com> said:
>
>> Well, not so sure about that: I'm pretty sure it's needed for disambiguation too. Let's say you have:
>>  	void foo(int x)();
>> 	void foo(T)(T x);
>>  	foo(5);
>>  Is foo(5) a the same as foo!(5), or does it call foo!(int).foo(5) ? Under the current rules, it's the second (you can write foo!(5) to call the first). If you allow templates to be instanciated without the "!", then I guess both will match and you'll have ambiguity.
>>  If you could avoid having sets of parameters, one for the function and one for the template, then you could get rid of the "!" in a snap...
>
> Or... we could just disallow having both at the same time, just like you can't have two functions with the same arguments. A call to foo(5) would be ambigous in the above situation, plain and simple. Is this reasonable?
>
> We could still disambiguate using:
>
> 	foo!(5);
>
> and:
>
> 	foo(int)(5);
>
> In this context, the ! becomes the "force this to be template arguments" operator, or the "do not deduce template arguments, I'll provide them" operator.
>
> Or we could just forget ! completely and leave the first one impossible to disambiguate.
>
> Which makes me think that it's sad we can't write the second as:
>
> 	foo(int, 5);
>
> I'd be much nicer to the eye.
>

If we don't omit parenthesises, the ambiguity goes away:

foo()(5)
foo(5)()
October 06, 2008
Andrei Alexandrescu wrote:
> I'd want to give it a try. How do others feel about Template{arguments}?


At first glance, I like it better than !(), especially since it saves a character, making nested templates much nicer:

   auto map = new Map{T[], List{MyType}}();     // not too bad
   auto map = new Map!(T[], List!(MyType))();   // not too good
   auto map = new Map<T[], List<MyType>>();     // still my favorite

It's too bad the shift operators can't be changed. Personally, I think the angle brackets are more valuable as a matched pair of enclosures.

We could redefine the shift operators to be:

   -->  RIGHT SHIFT
   <--  LEFT SHIFT
   -->> SIGNED RIGHT SHIFT

And then the angle brackets could be coopted for templates.

Of course, like I said before, I think it'd be especially cool if templates, as such, didn't exist. Instead, what if an ordinary function could return a Type, which could be used in a Type Constructor? Templates would vanish! It'd be CTFE, but for types instead of just for values.

--benji
October 06, 2008
Michel Fortin wrote:
> On 2008-10-05 12:10:36 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:
> 
>> I wish the dot wasn't even needed. One day I want to go over with Walter about the ambiguities incurred by simply using parens.
> 
> Replacing !( with .( doesn't make things better to my eye. Having only parenthesis would be great though, it it could be disambiguated.
> 
> - - -
> 
> I did a quick search and replace in the D/Objective-C bridge, which is pretty heavy in templates, to get an idea of what it would be like using ".(". In many places, the result seems fine:
> 
>     const char[] encode = "{"
>         ~ typename.(T) ~ "="
>         ~ encode.(size_t) ~ encode.(ArrayType.(T)*) ~ "}";
> 
>     const char[] encode = "{"
>         ~ typename!(T) ~ "="
>         ~ encode!(size_t) ~ encode!(ArrayType!(T)*) ~ "}";
> 
> I'd be tempted to see the first version, using the .( syntax, as easier to read. But note that here I'm not using a dot for anything else. If I take these other real examples from various lines in the bridge code:
> 
>     mixin objc.bridge.ObjcSubclass.(this.stringof);
> 
>     ObjcSubclassDefs.(T).objcMethodLists ~= ObjcSubclassDefs.(SUPER).objcMethodLists;
> 
>     alias objc.msg.sendSuper.(objc.type.ObjcType.(R), objc.type.ObjcTypeTuple.(A)) msgSendSuper;
> 
>     objc.subclassinit.ObjcSubclassDefs.(typeof(this)).objcClassInit.(typeof(super))(); 
> 
> 
> Here
> the dot is used to get to symbols in various modules an template members and in conjunction with an opening parenthesis to instanciate templates. This results in the strange "Template.(param).member" syntax. Am I the only one to find that syntax strange... if not misleading?
> 
> I think all these examples are much better with the current syntax, because defining parameters and accessing members is done with a totally non-overlapping syntax:
> 
>     mixin objc.bridge.ObjcSubclass!(this.stringof);
> 
>     ObjcSubclassDefs!(T).objcMethodLists ~= ObjcSubclassDefs!(SUPER).objcMethodLists;
> 
>     alias objc.msg.sendSuper!(objc.type.ObjcType!(R), objc.type.ObjcTypeTuple!(A)) msgSendSuper;
> 
>     objc.subclassinit.ObjcSubclassDefs!(typeof(this)).objcClassInit!(typeof(super))(); 
> 
> 
> Basically,
> I believe the syntax we choose needs to convey that we're defining parameters, not accessing a member. I don't really care if we ditch "!(", but I think ".(" is a worse alternative.
> 

After seeing these examples I actually think that the dot-syntax kinda works for me. Its like seeing the template as an aggregate of all its possible instantiations and the params in brackets is the "member" that you are after. I never really liked the pling-syntax (when I am coding, pling means NOT) so to keep my code cleaner looking I had a lot of aliases for my templated types, even if they were only used once. I think I could live with the dot.

A...
October 06, 2008
Tom S wrote:
> The "!" may be very common in modules such as std.algorithm, but you won't see as many in the usual stuff, like, most of Tango.

Unfortunately, any code that uses strings (and wants to correctly handle all three character types) is required to use templates. So there's a lot more template code out there than there ought to be.

--benji
October 06, 2008
On Mon, Oct 6, 2008 at 6:59 AM, Denis Koroskin <2korden@gmail.com> wrote:

> If we don't omit parenthesises, the ambiguity goes away:
>
> foo()(5)
> foo(5)()
>

No it doesn't.

Stdout("foo")("bar!").newline;
October 06, 2008
Benji Smith wrote:
> Jarrett Billingsley wrote:
>> On Sun, Oct 5, 2008 at 8:57 PM, Chris R. Miller
>> <lordsauronthegreat@gmail.com> wrote:
>>> The !() syntax seems to serve only as a heads up that it's a template.
>>> Otherwise (as far as I can tell) a simple foo(int)(bar, baaz) would work
>>> just as well as foo!(int)(bar, baaz).
>>>
>>
>> Unambiguous grammar, you fail it.
>>
>> foo(bar)(baz); // template instantiation or a chained call?
>>
>> This _can_ be _made_ to work, but it would mean that the parse tree
>> would be dependent upon semantic analysis, and that just makes things
>> slow and awful.  I.e. C++.
> 
> I'd be happy to get rid of OpCall, which I've always found confusing and pointless.
> 
> --benji

That's going to break a lot of struct constructors using static opCalls.
October 06, 2008
Benji Smith wrote:
> Andrei Alexandrescu wrote:
>> I'd want to give it a try. How do others feel about Template{arguments}?
> 
> 
> At first glance, I like it better than !(), especially since it saves a character, making nested templates much nicer:
> 
>    auto map = new Map{T[], List{MyType}}();     // not too bad
>    auto map = new Map!(T[], List!(MyType))();   // not too good
>    auto map = new Map<T[], List<MyType>>();     // still my favorite
> 
> It's too bad the shift operators can't be changed. Personally, I think the angle brackets are more valuable as a matched pair of enclosures.
> 
> We could redefine the shift operators to be:
> 
>    -->  RIGHT SHIFT
>    <--  LEFT SHIFT
>    -->> SIGNED RIGHT SHIFT
> 
> And then the angle brackets could be coopted for templates.
> 
> Of course, like I said before, I think it'd be especially cool if templates, as such, didn't exist. Instead, what if an ordinary function could return a Type, which could be used in a Type Constructor? Templates would vanish! It'd be CTFE, but for types instead of just for values.
> 
> --benji

Another problem with < is that, if you're not confident that Map is really a template identifier, you'll have the ambiguity whether < is an open bracket or a less than sign.

int x, y, w, z;

writefln(x<y,w>(z)); // currently compiles.
October 06, 2008
On Sun, Oct 5, 2008 at 1:06 PM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> The problem I see with "!" as a template instantiation is not technical. I write a fair amount of templated code and over years the "!" did not grow on me at all. I was time and again consoled by Walter than one day that will happen, but it never did. I also realized that Walter didn't see a problem with it because he writes only little template code.

I'm joining this discussion late, but I just wanted to say the !()
doesn't bother me so much.
What Walter said to you was pretty much how it went for me.  Seemed
weird for a while, but I got used to it.

I had to do several double-takes reading this thread thinking people were suggesting to use plain "()" because the little dot is just so easy to miss.

I find !() to at least be easier on the eyes than greater-than
less-than everywhere in C++.

I wouldn't be adamantly opposed to a different syntax, but it would have to be better by leaps and bounds for me to think it was worth the headache.  And .() doesn't seem leaps and bounds better to me.

I suggest, though, that if you think it looks a lot better you should at least post some example code showing "before" and "after" to try to convince us.  Seems like not many here see a lot of point in making the change, so rather than pleading with everyone to try it out on their own, why not just save us the effort and show us how it improves the code you're looking at?

--bb