Positive

Bruce Adams tortoise_74 at yeah.who.co.uk
Sun Oct 5 04:02:59 PDT 2008


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.

[snip]
>
> 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.

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?

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.

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

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.

Regards,

Bruce.


 



More information about the Digitalmars-d mailing list