October 11, 2004
<alert comment="newbie"?

Is there a way to define a numeric type to have a restricted range? Ada (and Pascal?) had something like:

subtype Temperatures is short range -50 .. 200;
subtype BookNum is ubyte range 1 .. 66;

Is this done in 'D' by defining an object derived from short or ubyte? Would this be inefficient? How about the properties .max and .min?

The kind of thing I want to do is have a lookup table such that the index into the lookup table has to have a restricted one-based range (from 1 to 66). I can accomplish roughly the equivalent of this with "dbc in";

ushort GetMaxChap(ushort bk) {
in { assert((bk >= 1) && (bk <= 66));
body {
 ...
}

But can I define a subrange for a type such as
ubyte BookNum bk;
that has to be between 1 and 66? I'd also like to be able for use
"foreach" on all the allowable values of BookNum.

void main() {
  foreach(BookNum) {
  ... some code
  }
  ushort maxChap = GetMaxChap(0); // rejected by compiler
}

ushort GetMaxChap(BookNum bk) {
... return lookup
}

If this syntax isn't available in 'D', what is the appropriate way to accomplish this for readability and/or efficiency and/or error minimization?

</alert>




October 11, 2004
"Lynn Allan" <l_d_allan@adelphia.net> wrote in message news:cke3d1$1ehf$1@digitaldaemon.com...
> <alert comment="newbie"?
>
> Is there a way to define a numeric type to have a restricted range?

not builtin to the language

> Ada (and Pascal?) had something like:
>
> subtype Temperatures is short range -50 .. 200;
> subtype BookNum is ubyte range 1 .. 66;
>
> Is this done in 'D' by defining an object derived from short or ubyte? Would this be inefficient? How about the properties .max and .min?

Technically speaking since short and ubyte aren't classes one can't derive from them. I'd recommend using either short or ubyte (or aliases for these) and checking the range explicitly as your code below illustrates.


>
> The kind of thing I want to do is have a lookup table such that the index into the lookup table has to have a restricted one-based range (from 1 to 66). I can accomplish roughly the equivalent of this with "dbc in";
>
> ushort GetMaxChap(ushort bk) {
> in { assert((bk >= 1) && (bk <= 66));
> body {
>  ...
> }
>
> But can I define a subrange for a type such as
> ubyte BookNum bk;
> that has to be between 1 and 66? I'd also like to be able for use
> "foreach" on all the allowable values of BookNum.
>
> void main() {
>   foreach(BookNum) {
>   ... some code
>   }
>   ushort maxChap = GetMaxChap(0); // rejected by compiler
> }
>
> ushort GetMaxChap(BookNum bk) {
> ... return lookup
> }
>
> If this syntax isn't available in 'D', what is the appropriate way to accomplish this for readability and/or efficiency and/or error minimization?
>
> </alert>

You could also define variables like "books" that stores an array of Books
which contain arrays of Chapters and then the array indexing bounds checking
will take care of  making sure the values stay inside the ranges (though I
suppose the builtin range support could improve compile-time vs run-time
checks). So for example instead of
 foreach(BookNum) {
  ... some code
 }
looping over a type (which isn't supported by the way) write
 foreach(Book book; books) {
 }
to loop over the collection of books. And then instead of GetMaxChap(ushort
bk) you could get the length property of the chapters field of a given Book.
I'm just making up data structures for you on the fly so who knows if arrays
of Books containing arrays of Chapters are useful for your app.

good luck,
-Ben