View mode: basic / threaded / horizontal-split · Log in · Help
October 05, 2008
Re: Positive
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.

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?

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/
October 05, 2008
Re: shouting versus dotting
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);

---

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).
October 05, 2008
Re: Positive
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
October 05, 2008
Re: Positive
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"...

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

--anders
October 05, 2008
Re: Positive
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.

---

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

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.
October 05, 2008
Re: shouting versus dotting
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?

... It looks like it should yield a tuple containing bar and baz :P


foo!(bar, baz)   <-  distinct, no issue.


As for the other queries, I like how template instantiation stands out 
right now with the exclamation mark. I would not like to have 
compile-time and run-time merged visually in code. 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.

What's the point in pretending that run-time is the same as 
compile-time? 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.


-- 
Tomasz Stachowiak
http://h3.team0xf.com/
h3/h3r3tic on #D freenode
October 05, 2008
Re: shouting versus dotting
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. 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 '.'

Lester L. Martin II
October 05, 2008
Re: Positive
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.

[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.
October 05, 2008
Re: Positive
On Sun, 05 Oct 2008 09:04:37 +0100, Michel Fortin  
<michel.fortin@michelf.com> 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.
>
> 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?
>

Depends on the type of argument.

For normal integers it should balk at compile time if possible and  
assert/throw if necessary
For complex types i would make sense.
For IEEE real numbers the specification probably mandates some behaviour  
such as NaN. Anyone read it recently?
October 05, 2008
Re: shouting versus dotting
On Sun, 05 Oct 2008 11:48:35 +0100, Tom S  
<h3r3tic@remove.mat.uni.torun.pl> 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?
>
> ... It looks like it should yield a tuple containing bar and baz :P
>
That is actually a very nice idea and a good syntax for it.
1 2 3 4 5 6 7 8 9
Top | Discussion index | About this forum | D home