October 05, 2008
Sean Kelly wrote:
> Is there anything this change in syntax gives us over what we currently have?  If not, I don't want it.

It's purely aesthetic. There are no technical advantages of one over the other.
October 05, 2008
Walter Bright wrote:
> Sean Kelly wrote:
>> Is there anything this change in syntax gives us over what we currently have?  If not, I don't want it.
> 
> It's purely aesthetic. There are no technical advantages of one over the other.

“T!()” just works. There’s no other meaning to it than template instantiation, whereas ”.” is heavily used as member accessor. I don’t see any technical or even aesthetical advantages here that might help understanding code. I just don’t get it.
October 05, 2008
Andrei Alexandrescu Wrote:

> Hello,
> 
> 
> (Background: Walter has kindly allowed ".()" as an alternative to the ugly "!()" for template argument specifications.)

I don't think .() is visually distinct enough, especially when property syntax can be used.


> 
> Just a quick question - I am feeling an increasing desire to add a template called Positive to std.typecons. Then Positive.(real) would restrict its values to only positive real numbers etc.

It's interesting, but I'd use contracts instead. I'd use an ultra short notation with no perceptible user impact (to save me typing). A not null type is more interesting to me.

> 
> The implementation would accept conversion from its base type, e.g. Positive.(real) can be constructed from a real. The constructor enforces dynamically the condition. Also, Positive.(real) accepts implicit conversion to real (no checking necessary).
> 
> There are many places in which Positive can be useful, most notably specifications of interfaces. For example:
> 
> Positive.(real) sqrt(Positive.(real) x);

Ummm... That's not even the correct signature for square root. It should accept non negative numbers.




> 
> These specifications are also efficient because checking for positivity is done outside sqrt; if you had a Positive.(real) to start with, there is no cascading checking necessary so there's one test less to do.
> 
> However, there is also the risk that Positive has the same fate the many SafeInt implementation have had in C++: many defined them, nobody used them. What do you think? If you had Positive in std and felt like crunching some numbers, would you use it?
> 
> In order to get things really started, there's already been an exchange with Walter on the matter. His reply was (I haven't asked for permission, but I'm pretty sure he'd agree making it public):
> 
> ==============
> Honestly, I wouldn't use it. I'd rather have an in contract for sqrt
> that asserts the argument is positive. Also, this opens the door to
> Negative, NegativeOrZero, ZeroOrInfinity, Odd, Even, Prime,
> SixOrFifteen, etc.
> ==============
> 
> My answer to that was:
> 
> ==============
> About contracts: Let me explain how I think that's inferior to Positive
> in two ways.
> 
> 1. Enough functions are defined on positive numbers only, to justify factoring that contract out of the functions themselves.
> 
> 2. The efficiency perk is that when using several such functions together, there's only one check; once in Positive-land, no more checks are necessary.
> 
> About proliferation of types: I don't think that follows at all. Math
> found positive numbers special enough to dedicate them a special
> notation (|R with subscript "+"). There's also a special notation for
> nonzero real numbers (|R with superscript "*"). There is no special
> notation for any of the sets you mentioned. That is bound to mean something.
> ==============
> 
> I'm interesting in further arguments. This feature is a numbers issue (pun not intended), meaning it will be any good only if enough people find it useful enough to actually use it in their own code and libraries, therefore building momentum behind it.
> 
> 
> Andrei

October 05, 2008
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

October 05, 2008
Jason House wrote:
> Andrei Alexandrescu Wrote:
>> Positive.(real) sqrt(Positive.(real) x);
> 
> Ummm... That's not even the correct signature for square root. It
> should accept non negative numbers.

Rats. I was thinking positive means >= 0 and strictly positive means > 0. According to Wikipedia, positive really means strictly positive and the longer-to-type NonNegative should be used instead :o|. For such a simple concept, a short and sweet name is pivotal. If there are any ideas for a better choice, please make them known.

Andrei
October 05, 2008
== 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.
October 05, 2008
Andrei Alexandrescu escribió:
> 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.

I was thinking about in which other way templates could be specified... Most of the other symbols already have a meaning as binary operator. And it also would be nice to have an opening and closing symbols, like <> in Java, C++, etc.

Can't {} be used for that? For example:

List{int} someList;

void foo{T}(T val) {
}

It seems more quiet. :-)

The only thing is, I don't know if this can lead to ambiguos parsing. I thought about it a little, and it seems it's ok. Another thing is that maybe { and ( look alike, so it can lead to confusion...

Oh, mmm... does it conflict with struct initializers?
October 05, 2008
Andrei Alexandrescu wrote:
> There are many places in which Positive can be useful, most notably specifications of interfaces. For example:
> 
> Positive.(real) sqrt(Positive.(real) x);

I think such restrictions/contracts are up to the implementation of an interface. There’s no point in defining them with interfaces, besides specific mathematical functions, which don’t play such big role in the “real world” as far as I can tell.

> These specifications are also efficient because checking for positivity is done outside sqrt; if you had a Positive.(real) to start with, there is no cascading checking necessary so there's one test less to do.

Same goes for contracts. It basically happens outside the body of the function, already.

> However, there is also the risk that Positive has the same fate the many SafeInt implementation have had in C++: many defined them, nobody used them. What do you think? If you had Positive in std and felt like crunching some numbers, would you use it?

I wouldn’t, since I can’t seem to see the point of it — well, besides trying to express mathematical notations in D, which in turn I find pretty pointless..

> About contracts: Let me explain how I think that's inferior to Positive in two ways.
> 
> 1. Enough functions are defined on positive numbers only, to justify factoring that contract out of the functions themselves.

I don’t think that the amount of functions defined as such really justify such a kind of (additional) restriction option. Positivity can be asserted by only accepting positive (unsigned) primitive types and a null argument is asserted in a contract. Adding another layer of restriction doesn’t make it any better. Especially not if you only need it in a very specific set of functions.

> 2. The efficiency perk is that when using several such functions together, there's only one check; once in Positive-land, no more checks are necessary.

Speaking mathematically correct, you can’t really let sqrt return a signed, positive value, since every sqrt has two results — positive and negative. There’s no point in restricting the return type to positive and especially not signed values.
October 05, 2008
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail@erdani.org)'s article
> Jason House wrote:
> > Andrei Alexandrescu Wrote:
> >> Positive.(real) sqrt(Positive.(real) x);
> >
> > Ummm... That's not even the correct signature for square root. It should accept non negative numbers.
> Rats. I was thinking positive means >= 0 and strictly positive means >
> 0. According to Wikipedia, positive really means strictly positive and
> the longer-to-type NonNegative should be used instead :o|. For such a
> simple concept, a short and sweet name is pivotal. If there are any
> ideas for a better choice, please make them known.
> Andrei

Maybe create the templates as a back end using whatever name, and then create typedefs/aliases for ufloat, udouble, ureal?  This would definitely be consistent with ints and easy to remember.
October 05, 2008
Alexander Pánek wrote:
> Andrei Alexandrescu wrote:
>> There are many places in which Positive can be useful, most notably specifications of interfaces. For example:
>>
>> Positive.(real) sqrt(Positive.(real) x);
> 
> I think such restrictions/contracts are up to the implementation of an interface. There’s no point in defining them with interfaces, besides specific mathematical functions, which don’t play such big role in the “real world” as far as I can tell.

Well we do use uint in the real world and we hope (partially in vain, sigh) that it models natural numbers. Positive gives ufloat, udouble, or ureal, as truly checked positive numbers. I mean nonnegative. Damn.

>> These specifications are also efficient because checking for positivity is done outside sqrt; if you had a Positive.(real) to start with, there is no cascading checking necessary so there's one test less to do.
> 
> Same goes for contracts. It basically happens outside the body of the function, already.

No. Contracts are not foldable. Folding them could be in theory done by the compiler, but requires nonscalable interprocedural analysis.

>> However, there is also the risk that Positive has the same fate the many SafeInt implementation have had in C++: many defined them, nobody used them. What do you think? If you had Positive in std and felt like crunching some numbers, would you use it?
> 
> I wouldn’t, since I can’t seem to see the point of it — well, besides trying to express mathematical notations in D, which in turn I find pretty pointless..

Why is that pointless? To the extent it's doable, it would only help.

>> About contracts: Let me explain how I think that's inferior to Positive in two ways.
>>
>> 1. Enough functions are defined on positive numbers only, to justify factoring that contract out of the functions themselves.
> 
> I don’t think that the amount of functions defined as such really justify such a kind of (additional) restriction option. Positivity can be asserted by only accepting positive (unsigned) primitive types and a null argument is asserted in a contract. Adding another layer of restriction doesn’t make it any better. Especially not if you only need it in a very specific set of functions.

No, this is a misunderstanding. There's no more need for sqrt to check its argument - it's guaranteed to be nonnegative. That's the whole point of the whole shtick.

>> 2. The efficiency perk is that when using several such functions together, there's only one check; once in Positive-land, no more checks are necessary.
> 
> Speaking mathematically correct, you can’t really let sqrt return a signed, positive value, since every sqrt has two results — positive and negative. There’s no point in restricting the return type to positive and especially not signed values.

I think this is off. In pretty much all languages I know, sqrt for real numbers never returns both roots. It returns the positive square root.


Andrei