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