Positive

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sun Oct 5 07:12:13 PDT 2008


Bruce Adams wrote:
> On Sun, 05 Oct 2008 03:35:57 +0100, Andrei Alexandrescu 
> <SeeWebsiteForEmail at 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

Ok.

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

Yes.

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

Correct.

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

Andrei



More information about the Digitalmars-d mailing list