October 05, 2008
Michel Fortin wrote:
> On 2008-10-05 01:55:43 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:
>> That will do a runtime check and throw if x is negative. That's unprecedented for an implicit cast, so I was thinking of defining a
>> universal "unsigned" template function that does the check:
>> auto y = sqrt(unsigned(x));
> Well, at this point I would prefer if it was a contract. Having to explicitly convert to unsigned just makes it harder than necessary.

But the point is that often you already traffic in nonnegatives, so you have them handy. Only passing the first time is difficult. But I hear you. We can make the conversion implicit.

> Throwing may be unprecedented for implict casts, but it is standard for contracts using assertions. So I think it would be okay to implicit cast and assert the value is non-negative (which would be equivalent to enforcing a contract).
> But then, shouldn't sqrt(-1) give you NaN, or i?

It can't yield i because i has a different type. It gives NaN now, and believe me, that doesn't help any.

October 05, 2008
KennyTM~ wrote:
> Michel Fortin wrote:
>> On 2008-10-05 01:14:17 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:
>>> I don't favor "." any more than the next guy, but I am glad there is awareness of how unfit a choice "!" is. If you have any ideas, please post them! Ah! I! Exclaimed! Again!
>> Hum, I don't think we have much choice, it'll have to be something in this lot:
>>     Positive!(real)(joke);
>>     Positive.(real)(joke);
>>     Positive#(real)(joke);
>>     Positive@(real)(joke);
>>     Positive&(real)(joke);
>>     Positive`(real)(joke);
>>     Positive´(real)(joke);
>>     Positive^(real)(joke);
>>     Positive¨(real)(joke);
>>     Positive\(real)(joke);
>> Anything else I forgot?
>> 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 "!(".
>> - - -
>> The ".(" syntax makes me think more of something like this:
>>     void func(T, alias methodOfT, A...)(T obj, A args)
>>     {
>>         obj.(methodOfT)(args);
>>     }
>> which I which I could do. If methodOfT was a string, I suppose I could use string mixins, but it pushes diagnostics about misnamed methods further in the template and requires adding quotes to the template parameter when instanciating.
> Argh, actually I once have a strong desire making
>   f«T»(x);
> a valid construct, and to workaround that « and » can't be easily typed you could substitute it with
>   f\<T\>(x);
> ---

Yah I would've like French quotes too.

> Anyway, I think the .() syntax is not as good as !() because the . is pretty hideous before another punctuation mark (which may be a good thing, I don't know), and one could easily miss it.
> And even if .() is allowed, please don't remove !() -- it will break significantly many code, and it doesn't cause any ambiguity either (unlike .func() vs .prop).

Many languages have successfully dealt with similar situations by simply allowing both but promoting only one in books and other documentation. Speaking of which, I'm on verge of signing with Addison Wesley Longman for delivering TDPL in April.

October 05, 2008
BLS wrote:
> I would prefer a more general, ADA like, solution.
> // ADA
> SUBTYPE Natural IS Integer RANGE 0 .. Integer'Last;
> SUBTYPE NonNegFloat IS Float RANGE 0.0 .. Float'Last;
> and also :
> SUBTYPE CapitalLetter IS Character RANGE 'A' .. 'Z';
> just my 2 euro cents;
> Bjoern

I think that's cool, particularly thinking that it can be done entirely at library level.


October 05, 2008
Anders F Björklund wrote:
> Andrei Alexandrescu wrote:
>>> 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.
>> I think that's a great idea. So, the question becomes: how do people feel about using ufloat, udouble, and ureal?
> I'll just insert my usual "real is not a type, but an alias"...

I thought it's a real type. No?

> At least udouble is easier to understand than Positive.(double)

The comparison was with Positive!(double). I'm Positive!

October 05, 2008
KennyTM~ wrote:
> Walter Bright wrote:
>> Andrei Alexandrescu wrote:
>>> 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 not a math major. But in college I took 4 years of math, up through integration in the complex plane and branch cuts (which I never did properly understand <g>). Every engineering/physics class was a math class. I never saw this notation. I am not suggesting it doesn't exist, just that it became commonplace fairly recently, or that it isn't commonplace at least at the undergraduate level. This plays into the numbers issue you mentioned.
> Probably they'd used (0, +∞) and [0, +∞) instead.

Depends on the field. The problem is, either notation is hard to google for.

> BTW, negative real numbers can also be indicated as ℝ⁻ (R^- if Unicode is not supported). Is it now special enough to deserve a Negative!() template? :p

Where I grew up I think the sign came as a subscript. This is because the nonzero "*" sign could then be added as a superscript. The notations I know of are (in TeX notation):

non-negative real numbers: R_+
non-zero real numbers: R^*
positive numbers: R_+^*

Rarely used (I never saw them, actually):

non-positive real numbers: R_-
negative numbers: R_-^*

Oh, I just realized that bounded numbers can't express nonzero real numbers.

> I think these sign checking should be done through contracts or "conditional template" (? whatever it's called; I haven't used one of these yet) instead. Unless you can runtime check that
>   Positive!(double) x = 6;
>   Positive!(double) y = 12;
>   Positive!(double) z = void;
>   z = x - y;  // raises error.
>   Positive!(double) w;
>   din.readf("%g", &w);  // raises error if user enters negative number.
> But I don't think uint, etc now even do these checks.

They don't because they have a slightly different purpose and charter.

October 05, 2008
Tom S wrote:
> I don't like using "." for template instantiation. The tokenizer in my eyes clearly separates constructs at ".". On the other hand, "!" as a graphical character is more 'filled', thus doesn't separate the identifier and arguments that much visually.
> foo.bar          <-  obviously member access
> foo.(bar, baz)   <-  multiple member access?

I hear you. I would have chosen the colon if it wasn't ambiguous.

> ... It looks like it should yield a tuple containing bar and baz :P
> foo!(bar, baz)   <-  distinct, no issue.

Looks great until you have twenty or thirty of these on a code screen. Then you're like, boy this is one ugly language. Believe me, I *tried* to put up with it.

> As for the other queries, I like how template instantiation stands out right now with the exclamation mark.

I wouldn't mind it either if I only had few of those.

> I would not like to have compile-time and run-time merged visually in code.

You already do in template argument deduction. Compile-time evaluation erodes the distinction further. The times go against the style of coding that separates compile-time stuff from run-time stuff.

> And I don't forget to put the exclamation mark there when programming templates.


> Let's also keep in mind what Ary said, that using "." will cause problems for IDEs.

No it won't.

> What's the point in pretending that run-time is the same as compile-time?

Because you shouldn't care.

> You can't instantiate compile-time constructs with run-time arguments, the costs are very different, too. Heck, when I see too many "!" in the code, it indicates that there may be a design issue and some massive bloat involved. I would not like this additional insight into the code removed from my eyes.

Conversely, if you have too few of those, I come and say you're doing too much manual work.

October 05, 2008
Lester L. Martin II wrote:
> Christopher Wright Wrote:
>> Andrei Alexandrescu 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 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.
>> Not only that, but typing it is annoying. First you need to put the
>>  right pinky on the shift key, which is a long reach; then you need
>> to put the left pinky on the 1 key, which is a long reach. Then you
>> need to move your left pinky all the way back to the left shift
>> key, which is a short reach, and move your right ring finger up to
>> the 9 key.
>> It's a lot of reaching and back and forth.
>> But I don't favor '.' since it's already used.
> I don't like the idea of '.' either. I currently like the '!'. I am
> not the best at templates and making templates similar to function
> call (looks like each other) would make templating so much harder. It
> should have something that lets you know right off that it's a
> template. Do you really want a template looking like a function.

You already have a template looking like a function. It works so well you don't even care, and consequently are not put off by it.

> That
> has potential to get confusing as your brain argues just at a glance
> over if a function is called and supplied parameters most functions
> wouldn't accept or is it a template and the list afterwards is the
> stuff supplied to the function (I don't remember ever passing to a
> function (real, real) so looking at that and having my brain think
> about "OH!" that's why the function call isn't working and the code
> won't compile, it's because you were dumb enough to supply types
> instead of values is not very intuitive).
> I like the '!' and don't look forward to seeing it changed but if it
> was to be changed, I'd prefer it not to be a '.' but maybe something
> along the line of a colon (':') because it doesn't show a function
> call. I can't remember ever using a ':' in my code except for that
> import this : function2 type stuff so I think this would be a good
> idea versus the '.'

I prefer the colon too, if ambiguity with ?: can be taken care of.

October 05, 2008
Bruce Adams wrote:
> On Sun, 05 Oct 2008 03:35:57 +0100, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>> Hello,
>> (Background: Walter has kindly allowed ".()" as an alternative to the ugly "!()" for template argument specifications.)
> I can't believe you posted this to this newsgroup expecting the bit about the positive
> template to be the focus of attention. As soon as I saw it, I anticipated the usual
> 'enflamed discussion'. Didn't you? or was that part of the plan?
> Anyway, I am glad some people did eventually get back to your main question.

I didn't expect that much hubbub.

>> 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
> As at least one other pointed out.
>   * means x >= 0 i.e. non negative
>   + means x > 0 i.e. strictly positive


> I think it is useful to support sub-typing as you suggest. Moreover, I would
> like to see more subtypes. Including things like Negative NegativeOrZero, and Odd
> or Even but not six of fifteen. Prime will be too expensive to check but it might
> still be useful. Its probably better to leave that to people to create when they
> find it useful.
> Generalised range restricted sub-types would be a real boon.
> I don't see what the problem is with proliferating types. If you have a function
> that works on a restricted range then declaring that makes sense.
> Regarding the name I have no good suggestions. There is "Unsigned" which is a C-ism
> that is out of kilter with the mathematical intent. There is "Cardinal" which is
> under rated outside of Modula derived languages but includes only whole numbers.
> Actually I think "Cardinal" would be a useful addition in its own right.
> I think subtyping is orthogonal to declaring a contract. Contracts apply to
> functions whereas this is a type declaration.
> Also you can use it to be more concise in your contracts. To declare that two non-negative
> numbers are greater than each other you could just write:
>   NonNegative!(x) > NonNegative!(y)
> If this is going to end up in a std library why is it a problem if few people use it?
> It is better that it is there and that people are aware of it than that people go down
> separate paths in solving the same problem at a later stage. Perhaps a more
> interesting question is how will you be using it?
> A second use I can see is selecting two different implementations at compile time.
> A (possibly faster) one for when the contract is supported and a slower or just different
> one when the type contract is not met.

These are excellent insights, thanks!

> Going back to the sqrt example. Do you propose to change the library declaration to
>  NonNegative!(numberType) sqrt( NonNegative!(numberType) X, NonNegative!(numberType) Y);
> Presumably changes like this are the real reason you want more feedback?

Yah. But what is the second argument for?

> My understanding of what you propose is:
> This is slightly less readable than using contracts but it is a more precise definition
> of the interface.

Yes. The contract goes out of the bowels of the function and from the documentation, straight in the interface of the function.

> Implicit type conversion would test the positivity in calls at compile time if possible
> but otherwise at runtime when necessary.


> The internal implementation of square root would not use the type constructor as it knows it answer
> will be positive.

Yes. (Wow I didn't think of that one!)

> It could end with a cast to NonNegative to avoid the unnecessary test or
> more likely always be using NonNegative numbers inside.


> Internal temporaries would be checked at compile time (when initialised to a compile time constant value)
> so there would be no added cost to implementing sqrt only using it with values that might
> be negative.

That can't be done in the current language, sigh.

> If my understanding is correct you are proposing this mainly because unlike contracts,
> templates are checked by the compiler at compile time.
> I suspect that is the real problem. I and others have previously tried to argue for compile
> time checkable contracts.
> Another advantage of compile time contracts is that you can design and test arbitrary new
> categories of type without having to add new type specifiers to the language. I'm thinking about
> const and pure here. Though pure would require functions to have visible compile time attributes
> (as opposed to the purely invisible ones which must exist internally) which is another kettle of fish.

I'd love compile-time-checked contracts, but they're simply not doable with current compiler technology.

October 05, 2008
Peter C. Chapin wrote:
> Andrei Alexandrescu wrote:
>> 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.
> Ada supports the ability to create new types from the primitive numeric
> types by adding range constraints to the primitive. The Ada community
> finds this useful and would appreciate the sort of feature you are
> talking about. In Ada there are even two predefined subtypes of Integer
> 	subtype Positive is Integer range 1 .. Integer'Last;
> 	subtype Natural is Integer range 0 .. Integer'Last;
> So for non-negative integers... what about "natural"?

Well uint kinda occupied that space, although as we all know it's not exactly a natural number.

I think the comparison with experience in Ada is sensible. I wished there was a predefined subtipe of Real too...

October 05, 2008
Denis Koroskin wrote:
> On Sun, 05 Oct 2008 07:36:58 +0400, Ary Borenszweig <ary@esperanto.org.ar> wrote:
>> Another problem, from an IDE perspective: "Positive." will trigger autocomplete of Positive's members, ugh.
> Thumbs up! That's you all over :)

Uninstantiated templates don't have members, except inside the template itself. This is a non-issue.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18