comp.lang.ada
 help / color / mirror / Atom feed
* Overlapping ranges
@ 2003-06-22  0:40 AG
  2003-06-22  1:23 ` Mark A. Biggar
  2003-06-29  0:36 ` Richard Riehle
  0 siblings, 2 replies; 13+ messages in thread
From: AG @ 2003-06-22  0:40 UTC (permalink / raw)


Assuming I have a package declaration like this:


package range is
  type x1 is range 0..255;
  type x2 is range 127..2**15-1;
end ranges;


Is there a way to declare a function
using that package that will accept
values of either x1 or x2 (and nothing
else) restricted to the range 127..255 ?





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-22  0:40 Overlapping ranges AG
@ 2003-06-22  1:23 ` Mark A. Biggar
  2003-06-22  2:58   ` AG
  2003-06-22 17:55   ` Robert I. Eachus
  2003-06-29  0:36 ` Richard Riehle
  1 sibling, 2 replies; 13+ messages in thread
From: Mark A. Biggar @ 2003-06-22  1:23 UTC (permalink / raw)


AG wrote:
> Assuming I have a package declaration like this:
> 
> 
> package range is
>   type x1 is range 0..255;
>   type x2 is range 127..2**15-1;
> end ranges;
> 
> 
> Is there a way to declare a function
> using that package that will accept
> values of either x1 or x2 (and nothing
> else) restricted to the range 127..255 ?

You have a bug in your design abstraction.  x1 and x2 are different
types and there is no way to declare a parameter with more then one
type.  This is like the doctor joke: "patient: Doc it hurts when I do 
this.  Doctor: So don't do that!"

But if that's really what you want to do this, there are several way to
do it.

First option fix the abstraction:

package range is
    type xBase is range 0..2**15-1;
    subtype x1 is xBase range 0..255;
    subtype x2 is xBase range 127..2**15-1;
    subtype x1x2Intersect is xbase range 127..255;

    function foo(p: x1x2Intersect) return ...;
  end ranges;

If you really need two separate types:

package range is
    type xBase is range 0...2**15-1;
    subtype x1x2Intersect is xBase range 127..255;
    type x1 is new xBase range xBase'First..255;
    type x2 is new xBase range 127..xBase'Last;

    function foo(p: x1x2intersect) return ...;
end ranges;

But now you must call foo with a view conversion to xBase:
a := foo(xBase(200));

Another option is to use a discriminated record:

package range is
    type x1 is range 0..255;
    type x2 is range 127..2**15-1;

    type x1x2intersect(b: boolean) is record
	case b is
	when false => x1val: x1 range 127..255;
	when true  => x2val: x2 range 127..255;
	end case;
    end record;

    function foo(p: x1x2intersect) return ...;
end ranges;

But now you need to call foo like:
a := foo((false, x1'(200)));
or
a := foo((true,  x2'(200)));


Personally, I'd try to get the design fixed :-)

-- 
mark@biggar.org
mark.a.biggar@attbi.com




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-22  1:23 ` Mark A. Biggar
@ 2003-06-22  2:58   ` AG
  2003-06-22  3:17     ` tmoran
  2003-06-22 17:55   ` Robert I. Eachus
  1 sibling, 1 reply; 13+ messages in thread
From: AG @ 2003-06-22  2:58 UTC (permalink / raw)



"Mark A. Biggar" <mark@biggar.org> wrote in message
news:My7Ja.54206$hz1.129990@sccrnsc01...
> AG wrote:
> > Assuming I have a package declaration like this:
> >
> >
> > package range is
> >   type x1 is range 0..255;
> >   type x2 is range 127..2**15-1;
> > end ranges;
> >
> >
> > Is there a way to declare a function
> > using that package that will accept
> > values of either x1 or x2 (and nothing
> > else) restricted to the range 127..255 ?
>
> You have a bug in your design abstraction.

It's not a bug it's a feature  -)

>  x1 and x2 are different
> types and there is no way to declare a parameter with more then one
> type.

Exactly. And that's the problem - I'm looking for a way
to declare a function [and/or whatever] that could handle
values of either of the two [test-bed of course] types and,
on top of that, impose range restrictions on the values passed in.

> First option fix the abstraction:
>
> package range is
>     type xBase is range 0..2**15-1;
>     subtype x1 is xBase range 0..255;
>     subtype x2 is xBase range 127..2**15-1;
>     subtype x1x2Intersect is xbase range 127..255;

Sorry, won't work. V1, V2 and V1x2 of the subtypes
are all mutually assignment-compatible. How would
the function know what you passed in?

> If you really need two separate types:
>
> package range is
>     type xBase is range 0...2**15-1;
>     subtype x1x2Intersect is xBase range 127..255;
>     type x1 is new xBase range xBase'First..255;
>     type x2 is new xBase range 127..xBase'Last;
>
>     function foo(p: x1x2intersect) return ...;
> end ranges;

That's a little bit better but: you've declared
the intersect [sub]type as coming from the type
xBase. What exactly does it have to do with
derived types x1 & x2?

> Another option is to use a discriminated record:

No, sorry, let's not go there. I know it's possible
but it's not exactly what I'm after ...





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-22  2:58   ` AG
@ 2003-06-22  3:17     ` tmoran
  0 siblings, 0 replies; 13+ messages in thread
From: tmoran @ 2003-06-22  3:17 UTC (permalink / raw)


> Exactly. And that's the problem - I'm looking for a way
> to declare a function [and/or whatever] that could handle
> values of either of the two [test-bed of course] types and,
> on top of that, impose range restrictions on the values passed in.
Can you just have two different functions overloading a single name?
   type x1 is range 0..255;
   type x2 is range 127..2**15-1;
   subtype x1_and_x2_range is x1 range 127 .. 255;
   subtype x2_and_x1_range is x2 range 127 .. 255;
   function f(x : x1_and_x2_range) return ...
   function f(x : x2_and_x1_range) return ...
   an_x1 : x1;
   an_x2 : x2;
   ...
   result := f(an_x1); -- checks an_x1 in 127 .. 255, then calls first "f"
   result := f(an_x2); -- checks an_x2 in 127 .. 255, then calls second "f"



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-22  1:23 ` Mark A. Biggar
  2003-06-22  2:58   ` AG
@ 2003-06-22 17:55   ` Robert I. Eachus
  2003-06-23  9:05     ` AG
  1 sibling, 1 reply; 13+ messages in thread
From: Robert I. Eachus @ 2003-06-22 17:55 UTC (permalink / raw)


Mark A. Biggar wrote:
> AG wrote:
> 
>> Assuming I have a package declaration like this:
>>
>>
>> package range is
>>   type x1 is range 0..255;
>>   type x2 is range 127..2**15-1;
>> end ranges;
>>
>>
>> Is there a way to declare a function
>> using that package that will accept
>> values of either x1 or x2 (and nothing
>> else) restricted to the range 127..255 ?
> 
> 
> You have a bug in your design abstraction.  x1 and x2 are different
> types and there is no way to declare a parameter with more then one
> type.  This is like the doctor joke: "patient: Doc it hurts when I do 
> this.  Doctor: So don't do that!"

That is the most important part of this advice.  Something is almost 
certainly wrong in your design, fix it.

> But if that's really what you want to do this, there are several way to
> do it.

And here is another.  (Again, this looks like a kludge because it is.)

Lower: X2 := X2'Max(X2'First, X2'Base(X1'First));
Upper: X2 := X2'Min(X2'Last, X2'Base(X1'Last));
subtype Restricted1 is X1 range X1(Upper)..X1(Lower);
subtype Restricted2 is X2 range Upper..Lower;

function Do_Something(Input: Restricted1) return ...;
function Do_Something(Input: Restricted2) return ...;

function Do_Something(Input: Restricted1) return ... is
begin return Do_Something(X2(Input)); end Do_Something;

function Do_Something(Input: Restricted2) return ... is
-- the "real" function...
...

Now let's see which problem requirements seem silly:

Why are X1 and X2 different types rather than subtypes?  Even if you 
need to crowd the X1 value into a byte in some record, it could be done 
with a subtype.

Why is X1 not a modular type?

Why do you need the Constraint_Error to be raised outside the function 
call?  Wouldn't raising it inside OR outside work just fine?

Why do you want one function which accepts parameters of two different 
types?  My solution has the call to one calling the other, but still...







^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-22 17:55   ` Robert I. Eachus
@ 2003-06-23  9:05     ` AG
  2003-06-23 10:46       ` David C. Hoos
  0 siblings, 1 reply; 13+ messages in thread
From: AG @ 2003-06-23  9:05 UTC (permalink / raw)


"Robert I. Eachus" <rieachus@attbi.com> wrote in message
news:3EF5EDA1.1010702@attbi.com...

> Now let's see which problem requirements seem silly:
>
> Why are X1 and X2 different types rather than subtypes?

Because I'd rather keep them separate except in the case
of that one specialised function which knows enough about
them to handle either. Declaring them as subtypes makes
all sorts of other things available too.

> Why is X1 not a modular type?

I'm afraid I didn't follow you there: I'm not interested
in modular or wrap-around semantics, so why should it be?

>
> Why do you need the Constraint_Error to be raised outside the function
> call?  Wouldn't raising it inside OR outside work just fine?

No. Because it results in an externally visible different behaviour.
Let's see an example (a bit silly as all examples are but an example
nevertheless):

package overlap is
type x1 is range 0..255;
type x2 is range 127..2**15-1;
subtype x1_and_x2_range is range x1(x2'first)..x1'last;
-- function f(x1_an_x2_range) return boolean;     -- *1*
-- function f(x: x1) return boolean;                       -- *2*
end;

with ada.text_io; use ada.text_io;
package body overlap is
-- *1*
  function f(x1_and_x2_range) return boolean is
    a: x1_and_x2_range;
  begin
     put_line("Here");
     a := x;
     return false;
  end;

-- *2*
  function f(x: x1) return boolean is
-- same code as above;
  end;

Finally, the use:  abc := f(0);

The result (running it under GNAT):

Uncommenting version *2* compiles fine
and generates constraint error when run.

Uncommenting version *1* generates
exactly the same error when run but also
provides two compile-time warnings.
Seems to be a valuable addition, doesn't it?

> Why do you want one function which accepts parameters of two different
> types?  My solution has the call to one calling the other, but still...

Someone else has already suggested the overloading solution.
Thanks, that seems like a good idea
.





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-23  9:05     ` AG
@ 2003-06-23 10:46       ` David C. Hoos
  2003-06-24  8:09         ` AG
  0 siblings, 1 reply; 13+ messages in thread
From: David C. Hoos @ 2003-06-23 10:46 UTC (permalink / raw)


Neither example will compile because the declaration
subtype x1_and_x2_range is range x1(x2'first)..x1'last;
is illegal;

Example 2 will not compile because the declaration
function f(x1_an_x2_range) return boolean;
is illegal.  Did you mean this?
function f(x : x1_and_x2_range) return boolean;

Both examples would give constraint error at runtime because
abc = f (0); has an argument outside the range of x1_and_x1_range.

"AG" <ang@xtra.co.nz> wrote in message
news:kszJa.45970$JA5.800915@news.xtra.co.nz...
> "Robert I. Eachus" <rieachus@attbi.com> wrote in message
> news:3EF5EDA1.1010702@attbi.com...
>
> > Now let's see which problem requirements seem silly:
> >
> > Why are X1 and X2 different types rather than subtypes?
>
> Because I'd rather keep them separate except in the case
> of that one specialised function which knows enough about
> them to handle either. Declaring them as subtypes makes
> all sorts of other things available too.
>
> > Why is X1 not a modular type?
>
> I'm afraid I didn't follow you there: I'm not interested
> in modular or wrap-around semantics, so why should it be?
>
> >
> > Why do you need the Constraint_Error to be raised outside the function
> > call?  Wouldn't raising it inside OR outside work just fine?
>
> No. Because it results in an externally visible different behaviour.
> Let's see an example (a bit silly as all examples are but an example
> nevertheless):
>
> package overlap is
> type x1 is range 0..255;
> type x2 is range 127..2**15-1;
> subtype x1_and_x2_range is range x1(x2'first)..x1'last;
> -- function f(x1_an_x2_range) return boolean;     -- *1*
> -- function f(x: x1) return boolean;                       -- *2*
> end;
>
> with ada.text_io; use ada.text_io;
> package body overlap is
> -- *1*
>   function f(x1_and_x2_range) return boolean is
>     a: x1_and_x2_range;
>   begin
>      put_line("Here");
>      a := x;
>      return false;
>   end;
>
> -- *2*
>   function f(x: x1) return boolean is
> -- same code as above;
>   end;
>
> Finally, the use:  abc := f(0);
>
> The result (running it under GNAT):
>
> Uncommenting version *2* compiles fine
> and generates constraint error when run.
>
> Uncommenting version *1* generates
> exactly the same error when run but also
> provides two compile-time warnings.
> Seems to be a valuable addition, doesn't it?
>
> > Why do you want one function which accepts parameters of two different
> > types?  My solution has the call to one calling the other, but still...
>
> Someone else has already suggested the overloading solution.
> Thanks, that seems like a good idea
> .
>
>
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>
>





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-23 10:46       ` David C. Hoos
@ 2003-06-24  8:09         ` AG
  0 siblings, 0 replies; 13+ messages in thread
From: AG @ 2003-06-24  8:09 UTC (permalink / raw)


"David C. Hoos" <david.c.hoos.sr@ada95.com> wrote in message
news:PGAJa.19179$bH3.5754@fe02.atl2.webusenet.com...
> Neither example will compile because the declaration
> subtype x1_and_x2_range is range x1(x2'first)..x1'last;
> is illegal;

Sorry, just a typing error on my part.
The line should have read:

subtype x1_and_x2_range is x1 range x1(x2'first)..x1'last;

A cut and past from AdaGide follows (which compiles fine):

package overlap is

type x1 is range 0..255;

type x2 is range 127.. 2**15-1;

subtype x1_and_x2_range is x1 range x1(x2'first)..x1'last;


function f(x: x1) return boolean;

end;



Sorry for the typo omission. Doesn't change the rest of it though.





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-22  0:40 Overlapping ranges AG
  2003-06-22  1:23 ` Mark A. Biggar
@ 2003-06-29  0:36 ` Richard Riehle
  2003-06-29  6:24   ` AG
  1 sibling, 1 reply; 13+ messages in thread
From: Richard Riehle @ 2003-06-29  0:36 UTC (permalink / raw)


AG wrote:

> Assuming I have a package declaration like this:
>
> package range is
>   type x1 is range 0..255;
>   type x2 is range 127..2**15-1;
> end ranges;
>
> Is there a way to declare a function
> using that package that will accept
> values of either x1 or x2 (and nothing
> else) restricted to the range 127..255 ?

Perhaps I don't understand why this is a problem for
you.  Why not something such as,

package ranges is
  type Number is range 0..2**15-1;
  type x1 is new Number range 0..255;
  type x2 is new Number range 127..2**15-1;
  function Fudge (A : X1; B : X2) return Number'Base;
  function Fudge (A : X2; B : X1) return Number'Base;
  X2_Error   : exception;
  X1_Error   : exception;
end ranges;

Tested using the following procedure,

with ranges;
with Ada.Integer_Text_IO;
procedure Test_Ranges is
   First  : ranges.X1 := 128;
   Second : ranges.X2 := 130;
   Result : ranges.Number'Base;
begin
   Result := ranges.Fudge(A => First, B => Second);
   Ada.Integer_Text_IO.Put(Integer(Result));  --  258
end Test_Ranges;

With this as a possible implementation of the body,

package body ranges is

   function Fudge (A : X1; B : X2) return Number'Base is
   begin
     if A in X1 then
         return Number(A) + Number(B);
      else
         raise X1_Error;
      end if;
   end Fudge;

   function Fudge (A : X2; B : X1) return Number'Base is
   begin
      if A in X2 then
         return Number(A) + Number(B);
      else
         raise X2_Error;
      end if;
   end Fudge;
end ranges;






^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-29  0:36 ` Richard Riehle
@ 2003-06-29  6:24   ` AG
  2003-06-29  6:42     ` AG
  2003-06-29 18:49     ` Richard Riehle
  0 siblings, 2 replies; 13+ messages in thread
From: AG @ 2003-06-29  6:24 UTC (permalink / raw)


"Richard Riehle" <richard@adaworks.com> wrote in message
news:3EFE3491.F968568D@adaworks.com...
> AG wrote:
>
> > Assuming I have a package declaration like this:
> >
> > package range is
> >   type x1 is range 0..255;
> >   type x2 is range 127..2**15-1;
> > end ranges;
> >
> > Is there a way to declare a function
> > using that package that will accept
> > values of either x1 or x2 (and nothing
> > else) restricted to the range 127..255 ?
>
> Perhaps I don't understand why this is a problem for
> you.  Why not something such as,

Because I don't want to allow an illegal
value to make it inside the function
(not even to raise an exception)

What I was after was some implementation
that won't need custom exceptions/error
codes or so.


> With this as a possible implementation of the body,
>
> package body ranges is
>
>    function Fudge (A : X1; B : X2) return Number'Base is

-- What happens here if you do something like
-- X3 := A + 1   ???

>    begin
>      if A in X1 then
>          return Number(A) + Number(B);
>       else
>          raise X1_Error;
>       end if;
>    end Fudge;





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-29  6:24   ` AG
@ 2003-06-29  6:42     ` AG
  2003-06-29 18:40       ` Richard Riehle
  2003-06-29 18:49     ` Richard Riehle
  1 sibling, 1 reply; 13+ messages in thread
From: AG @ 2003-06-29  6:42 UTC (permalink / raw)


> "Richard Riehle" <richard@adaworks.com> wrote in message
> news:3EFE3491.F968568D@adaworks.com...

On second thoughts and having re-read that:

> >    function Fudge (A : X1; B : X2) return Number'Base is
> >    begin
> >      if A in X1 then
       -- Can this test fail here at all ?





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-29  6:42     ` AG
@ 2003-06-29 18:40       ` Richard Riehle
  0 siblings, 0 replies; 13+ messages in thread
From: Richard Riehle @ 2003-06-29 18:40 UTC (permalink / raw)


AG wrote:

> > "Richard Riehle" <richard@adaworks.com> wrote in message
> > news:3EFE3491.F968568D@adaworks.com...
>
> On second thoughts and having re-read that:
>
> > >    function Fudge (A : X1; B : X2) return Number'Base is
> > >    begin
> > >      if A in X1 then
>        -- Can this test fail here at all ?

You're right.   However, we might do other kinds of tests
to ensure the correctness of the algorithm.

Richard Riehle







^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Overlapping ranges
  2003-06-29  6:24   ` AG
  2003-06-29  6:42     ` AG
@ 2003-06-29 18:49     ` Richard Riehle
  1 sibling, 0 replies; 13+ messages in thread
From: Richard Riehle @ 2003-06-29 18:49 UTC (permalink / raw)


AG wrote:

> "Richard Riehle" <richard@adaworks.com> wrote in message
> news:3EFE3491.F968568D@adaworks.com...
> > AG wrote:
> >
> > > Assuming I have a package declaration like this:
> > >
> > > package range is
> > >   type x1 is range 0..255;
> > >   type x2 is range 127..2**15-1;
> > > end ranges;
> > >
> > > Is there a way to declare a function
> > > using that package that will accept
> > > values of either x1 or x2 (and nothing
> > > else) restricted to the range 127..255 ?
> >
> > Perhaps I don't understand why this is a problem for
> > you.  Why not something such as,
>
> Because I don't want to allow an illegal
> value to make it inside the function
> (not even to raise an exception)
>
> What I was after was some implementation
> that won't need custom exceptions/error
> codes or so.

This is a good argument for the addition of pre-conditions,
post-conditions, and invariants to the language.  I like the
designations from Eiffel.  So the function might look like,

          function Fudge(A, B : Number'Base) return Number'Base;
          require A in X2'First..X1'Last;         -- pre-condition
          require B in X2'First..X1'Last;         -- pre-condition
          ensure return in X2'First..X2'Last;   -- post-condition

The only problem now is what the program does with a pre-
or post-condition violation.   The answer to this question is
not as trivial as it might at first seem.

Richard Riehle






^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2003-06-29 18:49 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-22  0:40 Overlapping ranges AG
2003-06-22  1:23 ` Mark A. Biggar
2003-06-22  2:58   ` AG
2003-06-22  3:17     ` tmoran
2003-06-22 17:55   ` Robert I. Eachus
2003-06-23  9:05     ` AG
2003-06-23 10:46       ` David C. Hoos
2003-06-24  8:09         ` AG
2003-06-29  0:36 ` Richard Riehle
2003-06-29  6:24   ` AG
2003-06-29  6:42     ` AG
2003-06-29 18:40       ` Richard Riehle
2003-06-29 18:49     ` Richard Riehle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox