View mode: basic / threaded / horizontal-split · Log in · Help
October 06, 2008
Re: shouting versus dotting
Andrei Alexandrescu wrote:
> Sean Kelly wrote:
>> Andrei Alexandrescu wrote:
>>> I believe the clear distinction is not only unnecessary, but 
>>> undesirable. We should actively fight against it.
>>
>> Why is it undesirable?  I like the idea of static parameters as 
>> described at the conference last year, but I don't think that has any 
>> bearing on this particular issue.
> 
> Time and again, both Walter and myself have met people who experience a 
> mental block whenever templates come within a mile. The fact that they 
> come with the sign Here! This! Is! A! Template! doesn't help any.

Are we discussing better template syntax of a magical injection that 
will cure the common fear of template code?  ;-)
October 06, 2008
Re: shouting versus dotting
Andrei Alexandrescu wrote:
> KennyTM~ wrote:
>> Andrei Alexandrescu wrote:
>>> Michel Fortin wrote:
>>>> On 2008-10-05 01:14:17 -0400, Andrei Alexandrescu 
>>>> <SeeWebsiteForEmail@erdani.org> said:
>>>>
>>>> -- snip --
>>>>
>>>> Or we could use special delimiter characters:
>>>>
>>>>     Positive<real>(joke);
>>>>     Positive“real”(joke);
>>>>     Positive«real»(joke);
>>>>     Positive#real@(joke);
>>>>
>>>> Each having its own problem though.
>>>>
>>>> My preference still goes to "!(".
>>>
>>> There was also Positive{real}(joke), with which I couldn't find an 
>>> ambiguity.
>>  >
>>
>> Ohhhh. Why isn't it considered then? (Suppose we already knew Positive 
>> is not a keyword and not preceded by the keywords struct, class, etc.)
> 
> I believe it should be considered. At some point there was discussion on 
> accepting a last parameter of delegate type outside the function parens. 
> The idea was to allow user-defined code to define constructs similar to 
> e.g. if and foreach.
> 
> But I think that has many other problems (one of which is that the 
> delegate can't reasonably specify parameters), so we can safely discount 
> that as a problem.
> 
> I'd want to give it a try. How do others feel about Template{arguments}?

I distrust it greatly.  Too similar to a code block.

I still have a lot of contact with kids still being educated in 
programming, and that'd probably just confuse the heck out of 'em.

No on {}!  Keep the code block sacred!  ;-)
October 06, 2008
Re: shouting versus dotting
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++.
October 06, 2008
Re: Positive
On Mon, 06 Oct 2008 00:55:33 +0100, Andrei Alexandrescu  
<SeeWebsiteForEmail@erdani.org> wrote:
>>>
>>> Andrei
>>  I disagree. I'm not saying its easy but it could be done. We would  
>> have to start
>> with something relatively simple and work our way up but it could be  
>> done.
>
> I, too, think it can be done in the same way supersonic mass
> transportation can be done, but having done research in the area I can
> tell you you are grossly underestimating the difficulties. It is a
> project of gargantuan size. Today the most advanced systems only managed
> to automatically prove facts that look rather trivial to the casual
> reader. There is absolutely no hope for D to embark on this.
>
I'm not asking for a generalised theorem prover. Something to handle even  
the
simple cases is a start.
I agree that D won't have this (any time soon) but mainly because there
are several hundred things higher up the priority list.

>> Compiler's already do all kinds of clever analyses behind the scenes  
>> but each one
>> is often hard coded. I suspect the main difficulty is giving users too  
>> much rope
>> by which to hang themselves, or rather hang the compiler trying to  
>> prove something
>> it doesn't realise it can't. Marrying declarative / constraint based  
>> programming
>> at compile time is creeping in via templates. I wish it was less well  
>> hidden.
>
> I discussed the problem this morning with Walter and he also started
> rather cocky: if you assert something early on, you can from then on
> assume the assertion is true (assuming no assignment took place, which
> is not hard if you have CFA in place). He got an arrow in a molar with
> the following example:
>
> double[] vec;
> foreach (e; vec) assert(e >= 0);
> // now we know vec is all nonnegatives
> normalize(vec);
>
> The definition of normalize is:
>
> void normalize(double[] vec)
> {
>      foreach (e; vec) assert(e >= 0);
>      auto sum = reduce@"a + b"(vec, 0);
>      assert(sum > 0);
>      foreach (ref e; vec) e /= sum;
> }
>
> If normalize takes udouble[] and you have one of those, there's no need  
> to recheck. Automated elimination of the checking loop above is really  
> hard.
>
>
> Andrei

Is it? I think your example needs to be expanded or we may be talking
at cross purposes.
Firstly I would rearrange things a little, though in principle it makes
no difference.

 pre
 {
    static assert(foreach (e; vec) assert(e >= 0));
 }
 void normalize(double[] vec)
 {
    auto sum = reduce@"a + b"(vec, 0);
    assert(sum > 0);
    foreach (ref e; vec) e /= sum;
 }

double[] vec;
static assert(foreach (e; vec) assert(e >= 0));  // line X

// now we know vec is all nonnegatives
normalize(vec);   // line Y

Imagine I have a prolog style symbolic unification engine to hand inside  
my compiler.

At line X the static assertion is evaluated.
The logical property e>=0 is asserted on the vec symbol.
The compiler reaches line Y.
Vec has not been modified so still has this property associated with it.
We now unify the symbol representing vec with the contract on normalise.
The unification succeeds and everything is fine.

Now imagine we have a stupid analyser.

double[] vec;
static assert(foreach (e; vec) assert(e >= 0));  // line X

vec[0] -= 1; // line Z

// now we know vec is all nonnegatives
normalize(vec);   // line Y

when the compile time analyser reaches line Z it can't work out whether or  
not the
contract still applies, so it removes the assertion that vec is e>=0 for  
all elements, or
rather asserts that it is not provably true.
Now when we reach Y the unification fails.
We don't throw a compile time contraint violation error. We haven't proved  
it to have failed.
We throw a compile time constraint unprovable error or warning.

Its like a lint warning. Your code may not be wrong but you might want to  
consider altering it
in a way that makes it provably correct.

We would really like to be able to assert that certain properties always  
hold for a variable
through its life-time. That is a harder problem.

I see something like this as a basis on which more advanced analysis can  
be built gradually.

Actually re-using static assert above was probably misleading. It would be  
better to have something
that says talk to the compile time theorem prover (a prolog interpreter  
would do).

I have been meaning to write something along these lines for years but so  
far I haven't got around to it
so I might as well stop keeping it under my hat.

Regards,

Bruce.
October 06, 2008
Re: shouting versus dotting
On 2008-10-05 20:57:31 -0400, "Chris R. Miller" 
<lordsauronthegreat@gmail.com> said:

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

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

Well, maybe not. You'll still have to resolve the same issues for constructors:

	class A(int x) {
		this() {}
	}
	class A() {
		this(int x) {}
	}

	auto a = new A(5);

Perhaps this is not a problem however: the only two valid ways to 
create an instance of one or the other are "new A!(5)" or "new 
A!()(5)", which would translate in non-"!" syntax as: "new A(5)" and 
"new A()(5)". Unfortunately, we don't have this "luck" with functions.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/
October 06, 2008
Re: Positive
Bruce Adams wrote:
> On Mon, 06 Oct 2008 00:55:33 +0100, Andrei Alexandrescu 
> <SeeWebsiteForEmail@erdani.org> wrote:
>>>>
>>>> Andrei
>>>  I disagree. I'm not saying its easy but it could be done. We would 
>>> have to start
>>> with something relatively simple and work our way up but it could be 
>>> done.
>>
>> I, too, think it can be done in the same way supersonic mass
>> transportation can be done, but having done research in the area I can
>> tell you you are grossly underestimating the difficulties. It is a
>> project of gargantuan size. Today the most advanced systems only managed
>> to automatically prove facts that look rather trivial to the casual
>> reader. There is absolutely no hope for D to embark on this.
>>
> I'm not asking for a generalised theorem prover. Something to handle 
> even the
> simple cases is a start.
> I agree that D won't have this (any time soon) but mainly because there
> are several hundred things higher up the priority list.
> 
>>> Compiler's already do all kinds of clever analyses behind the scenes 
>>> but each one
>>> is often hard coded. I suspect the main difficulty is giving users 
>>> too much rope
>>> by which to hang themselves, or rather hang the compiler trying to 
>>> prove something
>>> it doesn't realise it can't. Marrying declarative / constraint based 
>>> programming
>>> at compile time is creeping in via templates. I wish it was less well 
>>> hidden.
>>
>> I discussed the problem this morning with Walter and he also started
>> rather cocky: if you assert something early on, you can from then on
>> assume the assertion is true (assuming no assignment took place, which
>> is not hard if you have CFA in place). He got an arrow in a molar with
>> the following example:
>>
>> double[] vec;
>> foreach (e; vec) assert(e >= 0);
>> // now we know vec is all nonnegatives
>> normalize(vec);
>>
>> The definition of normalize is:
>>
>> void normalize(double[] vec)
>> {
>>      foreach (e; vec) assert(e >= 0);
>>      auto sum = reduce@"a + b"(vec, 0);
>>      assert(sum > 0);
>>      foreach (ref e; vec) e /= sum;
>> }
>>
>> If normalize takes udouble[] and you have one of those, there's no 
>> need to recheck. Automated elimination of the checking loop above is 
>> really hard.
>>
>>
>> Andrei
> 
> Is it? I think your example needs to be expanded or we may be talking
> at cross purposes.
> Firstly I would rearrange things a little, though in principle it makes
> no difference.
> 
>  pre
>  {
>     static assert(foreach (e; vec) assert(e >= 0));
>  }
>  void normalize(double[] vec)
>  {
>     auto sum = reduce@"a + b"(vec, 0);
>     assert(sum > 0);
>     foreach (ref e; vec) e /= sum;
>  }
> 
> double[] vec;
> static assert(foreach (e; vec) assert(e >= 0));  // line X
> 
> // now we know vec is all nonnegatives
> normalize(vec);   // line Y
> 
> Imagine I have a prolog style symbolic unification engine to hand inside 
> my compiler.
> 
> At line X the static assertion is evaluated.
> The logical property e>=0 is asserted on the vec symbol.
> The compiler reaches line Y.
> Vec has not been modified so still has this property associated with it.
> We now unify the symbol representing vec with the contract on normalise.
> The unification succeeds and everything is fine.
> 
> Now imagine we have a stupid analyser.
> 
> double[] vec;
> static assert(foreach (e; vec) assert(e >= 0));  // line X
> 
> vec[0] -= 1; // line Z
> 
> // now we know vec is all nonnegatives
> normalize(vec);   // line Y
> 
> when the compile time analyser reaches line Z it can't work out whether 
> or not the
> contract still applies, so it removes the assertion that vec is e>=0 for 
> all elements, or
> rather asserts that it is not provably true.
> Now when we reach Y the unification fails.
> We don't throw a compile time contraint violation error. We haven't 
> proved it to have failed.
> We throw a compile time constraint unprovable error or warning.
> 
> Its like a lint warning. Your code may not be wrong but you might want 
> to consider altering it
> in a way that makes it provably correct.
> 
> We would really like to be able to assert that certain properties always 
> hold for a variable
> through its life-time. That is a harder problem.
> 
> I see something like this as a basis on which more advanced analysis can 
> be built gradually.
> 
> Actually re-using static assert above was probably misleading. It would 
> be better to have something
> that says talk to the compile time theorem prover (a prolog interpreter 
> would do).
> 
> I have been meaning to write something along these lines for years but 
> so far I haven't got around to it
> so I might as well stop keeping it under my hat.
> 
> Regards,
> 
> Bruce.

I think it's terrific to try your hand at it. I for one know am not
equipped for such a pursuit. I have no idea how to perform unification
over loops, particularly when they may have myriads of little
differences while still having the same semantics; how to do that
cross-procedurally in reasonable time; how to take control flow
sensitivity into account; and why exactly people who've worked hard at
it haven't gotten very far. But I am equipped to define a type that
enforces all that simply and clearly, today.


Andrei
October 06, 2008
Re: Positive
Andrei Alexandrescu wrote:
> Bruce Adams wrote:
>> On Mon, 06 Oct 2008 00:55:33 +0100, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>>>>
>>>>> Andrei
>>>>  I disagree. I'm not saying its easy but it could be done. We would
>>>> have to start
>>>> with something relatively simple and work our way up but it could be
>>>> done.
>>>
>>> I, too, think it can be done in the same way supersonic mass
>>> transportation can be done, but having done research in the area I can
>>> tell you you are grossly underestimating the difficulties. It is a
>>> project of gargantuan size. Today the most advanced systems only managed
>>> to automatically prove facts that look rather trivial to the casual
>>> reader. There is absolutely no hope for D to embark on this.
>>>
>> I'm not asking for a generalised theorem prover. Something to handle
>> even the
>> simple cases is a start.
>> I agree that D won't have this (any time soon) but mainly because there
>> are several hundred things higher up the priority list.
>>
>>>> Compiler's already do all kinds of clever analyses behind the scenes
>>>> but each one
>>>> is often hard coded. I suspect the main difficulty is giving users
>>>> too much rope
>>>> by which to hang themselves, or rather hang the compiler trying to
>>>> prove something
>>>> it doesn't realise it can't. Marrying declarative / constraint based
>>>> programming
>>>> at compile time is creeping in via templates. I wish it was less
>>>> well hidden.
>>>
>>> I discussed the problem this morning with Walter and he also started
>>> rather cocky: if you assert something early on, you can from then on
>>> assume the assertion is true (assuming no assignment took place, which
>>> is not hard if you have CFA in place). He got an arrow in a molar with
>>> the following example:
>>>
>>> double[] vec;
>>> foreach (e; vec) assert(e >= 0);
>>> // now we know vec is all nonnegatives
>>> normalize(vec);
>>>
>>> The definition of normalize is:
>>>
>>> void normalize(double[] vec)
>>> {
>>>      foreach (e; vec) assert(e >= 0);
>>>      auto sum = reduce@"a + b"(vec, 0);
>>>      assert(sum > 0);
>>>      foreach (ref e; vec) e /= sum;
>>> }
>>>
>>> If normalize takes udouble[] and you have one of those, there's no
>>> need to recheck. Automated elimination of the checking loop above is
>>> really hard.
>>>
>>>
>>> Andrei
>>
>> Is it? I think your example needs to be expanded or we may be talking
>> at cross purposes.
>> Firstly I would rearrange things a little, though in principle it makes
>> no difference.
>>
>>  pre
>>  {
>>     static assert(foreach (e; vec) assert(e >= 0));
>>  }
>>  void normalize(double[] vec)
>>  {
>>     auto sum = reduce@"a + b"(vec, 0);
>>     assert(sum > 0);
>>     foreach (ref e; vec) e /= sum;
>>  }
>>
>> double[] vec;
>> static assert(foreach (e; vec) assert(e >= 0));  // line X
>>
>> // now we know vec is all nonnegatives
>> normalize(vec);   // line Y
>>
>> Imagine I have a prolog style symbolic unification engine to hand
>> inside my compiler.
>>
>> At line X the static assertion is evaluated.
>> The logical property e>=0 is asserted on the vec symbol.
>> The compiler reaches line Y.
>> Vec has not been modified so still has this property associated with it.
>> We now unify the symbol representing vec with the contract on normalise.
>> The unification succeeds and everything is fine.
>>
>> Now imagine we have a stupid analyser.
>>
>> double[] vec;
>> static assert(foreach (e; vec) assert(e >= 0));  // line X
>>
>> vec[0] -= 1; // line Z
>>
>> // now we know vec is all nonnegatives
>> normalize(vec);   // line Y
>>
>> when the compile time analyser reaches line Z it can't work out
>> whether or not the
>> contract still applies, so it removes the assertion that vec is e>=0
>> for all elements, or
>> rather asserts that it is not provably true.
>> Now when we reach Y the unification fails.
>> We don't throw a compile time contraint violation error. We haven't
>> proved it to have failed.
>> We throw a compile time constraint unprovable error or warning.
>>
>> Its like a lint warning. Your code may not be wrong but you might want
>> to consider altering it
>> in a way that makes it provably correct.
>>
>> We would really like to be able to assert that certain properties
>> always hold for a variable
>> through its life-time. That is a harder problem.
>>
>> I see something like this as a basis on which more advanced analysis
>> can be built gradually.
>>
>> Actually re-using static assert above was probably misleading. It
>> would be better to have something
>> that says talk to the compile time theorem prover (a prolog
>> interpreter would do).
>>
>> I have been meaning to write something along these lines for years but
>> so far I haven't got around to it
>> so I might as well stop keeping it under my hat.
>>
>> Regards,
>>
>> Bruce.
> 
> I think it's terrific to try your hand at it. I for one know am not
> equipped for such a pursuit. I have no idea how to perform unification
> over loops, particularly when they may have myriads of little
> differences while still having the same semantics; how to do that
> cross-procedurally in reasonable time; how to take control flow
> sensitivity into account; and why exactly people who've worked hard at
> it haven't gotten very far. But I am equipped to define a type that
> enforces all that simply and clearly, today.
> 
> 
> Andrei

I'm not an expert at optimizers, but I do read a whole lot.  This type
of analysis is often call 'value range propagation'.  Tracking the
possible values for data as it flows around and eliminating checks based
on prior events.  Most modern compilers do some amount of it.  The
question is how much and under what circumstances.  I'm not sure how
many combine that with static value analysis to create multiple function
versions.  IE, 'enough' callers to justify emitting two different forms
of the function, each with different base assumptions about the incoming
data and adjusting call sites.  I know that some compilers do that for
known constant values.  I guess it's something halfway to inlining.

I can guess at what dmd's backend does.. or rather doesn't do. :)

Later,
Brad
October 06, 2008
Re: shouting versus dotting
Michel Fortin a écrit :
> On 2008-10-05 20:57:31 -0400, "Chris R. Miller" 
> <lordsauronthegreat@gmail.com> said:
> 
>> 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).

What about the ^ ? I think it's not worst than !

foo^(int)(bar) but maybe this symbol is already used by D ?
Personally I would prefer to keep the C++, Java, C# syntax with <> 
because people are used to it even if in some cases it looks like a bit 
shift op.
October 06, 2008
Re: shouting versus dotting
Vincent Richomme wrote:
> Michel Fortin a écrit :
>> On 2008-10-05 20:57:31 -0400, "Chris R. Miller" 
>> <lordsauronthegreat@gmail.com> said:
>>
>>> 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).
> 
> What about the ^ ? I think it's not worst than !
> 
> foo^(int)(bar) but maybe this symbol is already used by D ?
> Personally I would prefer to keep the C++, Java, C# syntax with <> 
> because people are used to it even if in some cases it looks like a bit 
> shift op.

The problem isn't what it looks like to people -- people will generally 
be able to discern a template instantiation/declaration from a bitshift. 
 The problem is what it looks like to the compiler. If we had this in 
the compiler, the compiler would need to resolve symbols before it was 
able to produce a full parse tree, which leads to slower compilation 
times, more difficult tool creation, and a whole slew of other problems.
October 06, 2008
Re: shouting versus dotting
Chris R. Miller wrote:
> superdan wrote:
>> Andrei Alexandrescu Wrote:
>>
>>> dsimcha wrote:
>>>> == Quote from Andrei Alexandrescu (SeeWebsiteForEmail@erdani.org)'s 
>>>> article
>>>>> 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 didn't have much beef with other oddities unique to D. For 
>>>>> example, I
>>>>> found no problem accommodating binary "~" and I was wondering what 
>>>>> makes
>>>>> "!" different. I was just looking at a page full of templates and it
>>>>> looked like crap.
>>>>> One morning I woke up with the sudden realization of what the problem
>>>>> was: the shouting.
>>>>> In C, "!" is used as a unary operator. That may seem odd at first, but
>>>>> it nevers follows a word so it's tenuous to associate it with the
>>>>> natural language "!". In D, binary "!" _always_ follows a word, a 
>>>>> name,
>>>>> something coming from natural language. So the conotation with
>>>>> exclamation jumps at you.
>>>>> That's why I find the choice of "!" poor. I believe it can impede to
>>>>> some extent acquisition of templates by newcomers, and conversely I
>>>>> believe that using .() can make templates more palatable. I tried 
>>>>> using
>>>>> ".()" in my code and in only a couple of days it looked and felt way
>>>>> better to me. Based on that experience, I suggest that "!()" is 
>>>>> dropped
>>>>> in favor of ".()" for template instantiation for D2.
>>>>> Sean's argument that "The exclamation mark signifies an assertion of
>>>>> sorts" is exactly where I'd want templates not to be: they should be
>>>>> blended in, not a hiccup from normal code. Serious effort has been, 
>>>>> and
>>>>> still is, made in D to avoid shell-shocking people about use of
>>>>> templates, and I think ".()" would be a good step in that direction.
>>>>> Andrei
>>>> Personally, I think that ".()" looks a little too much like a normal
>>>> function/method call.  The "!()" syntax looks just different enough 
>>>> to make it
>>>> easy to keep straight in my head that stuff with the "!" is a 
>>>> compile-time
>>>> construct and stuff without it can be evaluated at runtime.
>>> I'm arguing we _should_ make template code look like "normal" code, 
>>> whatever "normal" is :o). We _should_ strive for "quiet" templates.
>>>
>>> You know what annoys the living heebiejeebies out of me? Nested 
>>> template instantiations.
>>>
>>> This!(That!(TheOther!(crap)))
>>>
>>> I have a ton + change of those. In superdan's words: intercourse that.
>>>
>>>
>>> Andrei
>>
>> im a bit drunk. but im much obliged since my name was mentioned n all.
>>
>> ! pisses me off too. i have an opinion. walter looked at unary ops 
>> that can be binary ops. first tilde. pulled tat off. ten he wanted the 
>> template thing. only 1 left was !. so he put that at work. right walt?
>> now i never like ! because of nother reason. i always forget to put 
>> it. and yes it's not needed. i look @ code its unambig. then wtf do i 
>> need that crap !
>>
>> anyhoo would be great if ! goes away. to hell with it. need to try 
>> asdad.(asdasd) to see how it feels. and yeah they all jump andreis 
>> neck whever he posts any. or walts. its funny. hold them guns folks. 
>> can i delete this later i wonder.
> 
> I live in California.  Legally I cannot own any gun that could 
> conceivably hurt someone when misused under the proper situations.  =/
> 
> I was never particularly annoyed by the !() syntax, but then again I 
> have not written much template code.  I can count the number of template 
> classes I have written on one hand.
> 
> I am deeply concerned about the proposed .() syntax, however, since (to 
> me) it's too similar to a function call.  This lack of finding some kind 
> of counterproposal left me studying my keyboard for any unused 
> characters that could become a symbol.  I saw these symbols that I could 
> remember no existing use for:
> 
> @, #, $, `
> 
> I'm favorable to the # symbol.  So a template would look like 
> foo#(int)(bar).
> 
> To me the # symbol looks like it could be two Latin 't' characters (not 
> to be confused with the Greek Tau 'T', which is different).  Thus one 
> could remember the mnemonic "template" with two t's for the # symbol.
> 
> Just a countersuggestion, I haven't really looked through specifications 
> or anything to verify the unused status of any of those symbols.

Sorry, ` is not possible because of `string like = this.toString();`.
12 13 14 15 16 17 18 19 20
Top | Discussion index | About this forum | D home