comp.lang.ada
 help / color / mirror / Atom feed
* 'Digit is generic package
@ 1996-08-23  0:00 Richard A. O'Keefe
  1996-08-24  0:00 ` Robert I. Eachus
  1996-08-29  0:00 ` Robert A Duff
  0 siblings, 2 replies; 3+ messages in thread
From: Richard A. O'Keefe @ 1996-08-23  0:00 UTC (permalink / raw)



Some time ago I posted a question but never saw a reply,
so here it is again, in somewhat less detail.

What I *want* to do is

	generic

	    type Coord is digits <>;
	    type Value is digits <>;

	package Foo_Pkg is

	    type Number is digits Max(Coord'Digits, Value'Digits);

	    ...

	end Foo_Pkg;

I _could_ handle this by making Number a generic type too, and then
checking that Number'Digits >= Coord'Digits and Number'Digits >= Value'Digits,
but heck, I could use C++ or Fortran 90, or better still, Common Lisp.

There is another rather horrible workaround that I just thought of,
which could be used for a procedure, but not for a package:

	generic
	    type Coord is digits <>;
	    type Value is digits <>;
	    type Number is digits <>;
	procedure Hidden_Foo(.....);


	generic
	    type Coord is digits <>;
	    type Value is digits <>;
	procedure Visible_Foo(...);

	procedure Visible_Foo(...) is
	    procedure X is new Hidden_Foo(Coord, Value, Coord);
	    procedure Y is new Hidden_Foo(Value, Coord, Coord);
	begin
	    if Coord'Digits >= Value'Digits then
		X(...);
	    else
		Y(...);
	    end if;
	end Visible_Foo;

but it's a bit like a Johnson's "dog walking on its hind legs".

I have read the annotated Ada 95 RM carefully, and I know that when Gnat
rejects the code I want to write it is doing exactly what the standard
requires.  Apart from the problem with Max, there is the unpleasant fact
that Coord'Digits is not a static something-or-other expression, much to
my surprise.  This has the consequence, which I still find, um, quirky,
that

	type Number is new Coord;

is legal inside a generic package like this, but

	type Number is new digits Coord'Digits;

is not.

(a) I would get some consolation from knowing whether this was an *intended*
    restriction for Ada 95 and if so what harm would have resulted had this
    restriction not been in the language.

(b) Is there any better approach for doing this with a procedure than the
    make-to-instances-and-pick-one-at-runtime one shown above?

(c) Is there any reasonable approach for doing what I want with a package?


For what it's worth, the least ugly and most robust workaround I could
come up with was just to do

	type Number is new Long_Float;

and comment it to say what I really want.
-- 
Australian citizen since 14 August 1996.  *Now* I can vote the xxxs out!
Richard A. O'Keefe; http://www.cs.rmit.edu.au/~ok; RMIT Comp.Sci.




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

* Re: 'Digit is generic package
  1996-08-23  0:00 'Digit is generic package Richard A. O'Keefe
@ 1996-08-24  0:00 ` Robert I. Eachus
  1996-08-29  0:00 ` Robert A Duff
  1 sibling, 0 replies; 3+ messages in thread
From: Robert I. Eachus @ 1996-08-24  0:00 UTC (permalink / raw)



In article <4vj3e6$hi1@goanna.cs.rmit.edu.au> ok@goanna.cs.rmit.edu.au (Richard A. O'Keefe) writes:

  > Some time ago I posted a question but never saw a reply,
  > so here it is again, in somewhat less detail.

  > What I *want* to do is...

  >	       type Number is digits Max(Coord'Digits, Value'Digits);

  > (procedural solution deleted)
  > ...but it's a bit like a Johnson's "dog walking on its hind legs".

    One of the most easily forgotten features of Ada is that generic
instantiation happens at run-time.  This has a lot of advantages, but
there are some consequences that get ignored until they slap you in
the face.  This is one of them.  You can't generate code on most
machines which will operate on different numeric machine types.  So
Ada requires that choices of such types must occur at compile
time--sort of.  The compiler is expected to be able to reason that
several different are required for a single generic, and to call the
correct one.  However, for efficiency reasons, it is expected to be
possible to decide between versions for each source call at compile
time.  (The language is also defined so that all such calls can be
parameterized, but that is a different issue.)

    None of this prevents you from doing the dirty work under the
covers, and many math packages do.  The usual is to correctly
implement the algorithm for each machine type, and dispatch to the
correct (non-generic) version inside the generic:

    function Float_Float(X: in Float) return Float;
    function Long_Float_Float(X: in Long_Float) return Float;
    function Long_Float_Long_Float(X: in Long_Float) return Long_Float;
    ...

    generic
      type Foo is digits <>;
      type Bar is digits <>:
    function Generic_F(X: in Foo) return Bar is 
      case Foo'digits is
        when 1..6 => 
          case Bar'digits is
            when 1..6 => return Bar(Float_Float(Float(X)));
            when 7..13 => ...

    So yes, the pragmatic decision in building the language is that
single dispatch on sizes of machine types are comfortably handled
implicitly by generics.  Multiple dispatch works, but the default is
not right for all cases, and sometimes you have to roll your own.
Algorithms which depend on arithmetic functions of sizes definitely
fall in that category.

--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Re: 'Digit is generic package
  1996-08-23  0:00 'Digit is generic package Richard A. O'Keefe
  1996-08-24  0:00 ` Robert I. Eachus
@ 1996-08-29  0:00 ` Robert A Duff
  1 sibling, 0 replies; 3+ messages in thread
From: Robert A Duff @ 1996-08-29  0:00 UTC (permalink / raw)



In article <4vj3e6$hi1@goanna.cs.rmit.edu.au>,
Richard A. O'Keefe <ok@goanna.cs.rmit.edu.au> wrote:
>(a) I would get some consolation from knowing whether this was an *intended*
>    restriction for Ada 95 and if so what harm would have resulted had this
>    restriction not been in the language.

This restriction comes from Ada 83, and as far as I know, nobody wanted
to change it for Ada 9X.  I recall some earlier version of Ada 83 (Ada
80, or Green, or something) was more liberal, along the lines you're
asking for.  I don't remember the exact rules, but I think it was
possible to say things like "type T is digits X;" where X was a generic
formal parameter.  You could look at the old pre-1983 documents...

The reason for the rule is essentially just to keep things simple, I
think.  It would be more complicated to describe a rule that allowed
some expressions to be static, depending on knowing that they will be
static in the instance.  And it would probably be harder to implement.
Also, if you allowed what you want in a generic body, then it would
violate the contract model, and cause trouble for code-sharing
implementations.

In general, the definition of "static expression" was never intended to
be "any expression that can be evaluated at compile time" -- just a
reasonably useful, but not-too-hard-to-implement subset of those
expressions.  For example, composite expressions are never static in Ada
83, and in Ada 95, are static only in some severely-restricted string
cases.

>(b) Is there any better approach for doing this with a procedure than the
>    make-to-instances-and-pick-one-at-runtime one shown above?

I think your best bet is to pass in three types, and check at run time
that their 'Digits have the right relationship.  That's not *so* awful.

- Bob




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

end of thread, other threads:[~1996-08-29  0:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-08-23  0:00 'Digit is generic package Richard A. O'Keefe
1996-08-24  0:00 ` Robert I. Eachus
1996-08-29  0:00 ` Robert A Duff

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