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/

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)()

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

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...

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

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.

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.

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