comp.lang.ada
 help / color / mirror / Atom feed
* What's the difference between...
@ 1993-02-12 18:52 Kenneth Anderson
  0 siblings, 0 replies; 13+ messages in thread
From: Kenneth Anderson @ 1993-02-12 18:52 UTC (permalink / raw)


these two type declarations:

type Placement is range 0 .. 10;

subtype Placement is INTEGER range 0 .. 10;


The reason I ask this, is that I have the duty here at U.C. Irvine of teaching
the students of an Intro to Software Engineering course enough Ada for them
to do their homework assignments.  I get two 1.5 hour lectures to do this.

One of my students asked what is the difference between the two type
declarations.

My answer was "Not much.  I'll get back to you on what the conceptual
difference is."

So I would like to tell him at the next lecture what the difference is.

Can someone help me out?

Thanks in advance,

Ken

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

* Re: What's the difference between...
@ 1993-02-12 22:58 Robert I. Eachus
  0 siblings, 0 replies; 13+ messages in thread
From: Robert I. Eachus @ 1993-02-12 22:58 UTC (permalink / raw)


    A value of the subtype can be assigned to variable of type
STANDARD.INTEGER, a value of the type cannot.  (Unless you do an
explicit conversion.)  The principal advantage to using many different
integer types is that the compiler will prevent you from accidently
assigning Apples to Oranges.

    Some people object to all those #$@#%*! messages from the
compiler, but software engineers know that it saves a lot of money to
find the bugs as early as possible.


--

					Robert I. Eachus

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

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

* Re: What's the difference between...
@ 1993-02-12 23:51 kronos.arc.nasa.gov!butch!LMSC5.IS.LMSC.LOCKHEED.COM!LJ10891
  0 siblings, 0 replies; 13+ messages in thread
From: kronos.arc.nasa.gov!butch!LMSC5.IS.LMSC.LOCKHEED.COM!LJ10891 @ 1993-02-12 23:51 UTC (permalink / raw)


------------------------- Original Article -------------------------
>type Placement is range 0 .. 10;
>subtype Placement is INTEGER range 0 .. 10;

  I'm no maven, but I'll give it a shot.

  The first declaration defines a new type whose base type is the infamous
{anonymous integer}.  The second declaration defines a subtype whose base
type is the named type STANDARD.INTEGER.  This subtype inherits all of
the operations defined on its parent type.

   Illustrative example:

X : INTEGER := 5;
P1 : PLACEMENT_1 := 6;
P2 : PLACEMENT_2 := 6;

begin
  X := P1 + 3;  --illegal: result type is PLACEMENT_1
  P1 := X + 3;  --illegal: result type is INTEGER
  P2 := X + 3;  --legal
  P2 := X + 6;  --CONSTRAINT_ERROR
end;

   Hope that helps.  Send comments to ghaddad@lunacity.com.  Send flames
to someone@who.needs.them.

-------------------------------------------
I found these opinions on my doorstep, could you please give them a good home.

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

* Re: What's the difference between...
@ 1993-02-12 23:57 Mark A Biggar
  0 siblings, 0 replies; 13+ messages in thread
From: Mark A Biggar @ 1993-02-12 23:57 UTC (permalink / raw)


In article <9302121052.aa23420@Paris.ics.uci.edu> kanderso@mabillon.ICS.UCI.EDU
 (Kenneth Anderson) writes:
>What is the difference between
>these two type declarations:
>
>type Placement is range 0 .. 10;
>
>subtype Placement is INTEGER range 0 .. 10;
>
>The reason I ask this, is that I have the duty here at U.C. Irvine of teaching
>the students of an Intro to Software Engineering course enough Ada for them
>to do their homework assignments.  I get two 1.5 hour lectures to do this.

Remember that in Ada all type names are really subtype names on an anonymous
type.

The second declaration above specifies that the type of Placement is the same
type as that of INTEGER, or in other words Placement'BASE is the same as
INTEGER'BASE.  Therefore assignment between variables of subtype Placement
and subtype INTEGER are legal with out any explisit type conversion.
Of course a constraint check may be necessary.

For the first declaration you are leaving it up to the compiler to
select the type ('BASE) for Placement. (Note you still only get a subtype)
The compiler may pick INTEGER'BASE or it may pick SHORT_INTEGER'BASE
or even LONG_INTEGER'BASE.  Most compiler pick the smallest type that
contains all the values of the specified constraint.  It then creates
a new anonymous interger type with the same properties as the selected
'BASE type and uses it as the Placement'BASE.  Now as Placement is a
subtype of a different type than the the subtype INTEGER, you must use
an explisit conversion when assigning from one to the other.

--
Mark Biggar
mab@wdl1.wdl.loral.com

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

* Re: What's the difference between...
@ 1993-02-13  5:30 Alex Blakemore
  0 siblings, 0 replies; 13+ messages in thread
From: Alex Blakemore @ 1993-02-13  5:30 UTC (permalink / raw)


In article <9302121052.aa23420@Paris.ics.uci.edu> kanderso@mabillon.ICS.UCI.EDU
 (Kenneth Anderson) writes:
> these two type declarations:
> type Placement is range 0 .. 10;
> subtype Placement is INTEGER range 0 .. 10;


first remember what a type is (its two things)
  1. a _set_ of values
  2. a set of operations

a whole lot. here's a quick answer.

the first one introduces a new numeric type. 

  it is a distinct type from other numeric types and thus you cannot
  assign the contents integer of an integer variable ot a placement
  variable without a conversion.  this is useful in the abstract to
  keep apples and oranges separate, even if both can be represented
  by integral values.

  the compiler is free to choose any representation that can hold
  any value of the type - so it will likely choose 1 byte in this case.
  (it could choose less or more).

  the type definition (like a derived type) introduces a completely
  new set of values and operations - though they may be copied
  from the base type.

the second one introduces a subtype of integer.

  subtypes merely restrict the set of values of a type to a subset.
  they do not introduce a new set of values and operations.
  variables of the subtype can be assigned freely to/from objects
  of the type (or its other subtypes).  constraint checks will be made
  if needed to guarantee the range constraint is satisfied.

  the compiler must use the same representation for all objects of
  a type (irregardless of any subtypes) in this case, a placement
  must take as many bits as any other integer, so the compiler
  will likely use 4 bytes (say) and not 1 byte for each placement object.


this should be a FAQ
-- 
---------------------------------------------------
Alex Blakemore alex@cs.umd.edu   NeXT mail accepted

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

* Re: What's the difference between...
@ 1993-02-13 19:18 agate!spool.mu.edu!hri.com!noc.near.net!inmet!spock!stt
  0 siblings, 0 replies; 13+ messages in thread
From: agate!spool.mu.edu!hri.com!noc.near.net!inmet!spock!stt @ 1993-02-13 19:18 UTC (permalink / raw)


In article <64238@mimsy.umd.edu> alex@cs.umd.edu (Alex Blakemore) writes:

  [good stuff deleted]

> . . .
>  the compiler must use the same representation for all objects of
>  a type (irregardless of any subtypes) in this case, a placement
>  must take as many bits as any other integer, so the compiler
>  will likely use 4 bytes (say) and not 1 byte for each placement object.

This is not true.  In the absence of a size clause,
objects of a given subtype may be of any
size sufficient to hold every possible value of the subtype.
Actually, objects can be even smaller (in fact, non-existent)
if an optimizer knows all of the uses of the object, and knows
the actual range of values ever stored into the object.

It is true that some compilers follow the rule you state,
but others do not (and still validate, for what that's worth ;-).
With this latter group of compilers, objects of the subtype
could also be just one byte.  Remember that all numeric types
use pass by copy for parameter passing, so the actual representation
of a numeric object need not be known outside its lexical scope,
and need not be the same as other objects of the same numeric type.

The important point (which you and others have already made) has
to do with static semantics, not representation.  Operands of distinct types
cannot be mistakenly combined using the predefined operators or
assignment.  Explicit type conversion is required (of course
that's a bit annoying for multiplication -- we never did get
around to putting full support for "units" into Ada).

By contrast, operands which differ only in subtype are freely
combinable with the predefined operators and assignment (subject
to run-time constraint checks on assignment).

>Alex Blakemore alex@cs.umd.edu   NeXT mail accepted

S. Tucker Taft    stt@inmet.com
Intermetrics, Inc.
Cambridge, MA  02138

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

* Re: What's the difference between...
@ 1993-02-14  3:08 agate!spool.mu.edu!sdd.hp.com!portal!cup.portal.com!R_Tim_Coslet
  0 siblings, 0 replies; 13+ messages in thread
From: agate!spool.mu.edu!sdd.hp.com!portal!cup.portal.com!R_Tim_Coslet @ 1993-02-14  3:08 UTC (permalink / raw)


In Article: <1993Feb13.191810.4452@inmet.camb.inmet.com>
	stt@spock.camb.inmet.com (Tucker Taft) Wrote:
>The important point (which you and others have already made) has
>to do with static semantics, not representation.  Operands of distinct types
>cannot be mistakenly combined using the predefined operators or
>assignment.  Explicit type conversion is required (of course
>that's a bit annoying for multiplication -- we never did get
>around to putting full support for "units" into Ada).
Actually, if you know you are going to be multiplying mixed types
(e.g. APPLES in a crate by CRATES to get APPLES in a shipment) just
define a new multiply operator on the mixed types so the "conversion"
is hidden and "units" are enforced by the compiler.

                                        R. Tim Coslet

Usenet: R_Tim_Coslet@cup.portal.com
        technology, n.  domesticated natural phenomena

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

* Re: What's the difference between...
@ 1993-02-14 19:55 Adam Beneschan
  0 siblings, 0 replies; 13+ messages in thread
From: Adam Beneschan @ 1993-02-14 19:55 UTC (permalink / raw)


In article <75591@cup.portal.com> R_Tim_Coslet@cup.portal.com writes:

> In Article: <1993Feb13.191810.4452@inmet.camb.inmet.com>
>         stt@spock.camb.inmet.com (Tucker Taft) Wrote:
> >The important point (which you and others have already made) has
> >to do with static semantics, not representation.  Operands of distinct types
> >cannot be mistakenly combined using the predefined operators or
> >assignment.  Explicit type conversion is required (of course
> >that's a bit annoying for multiplication -- we never did get
> >around to putting full support for "units" into Ada).

> Actually, if you know you are going to be multiplying mixed types
> (e.g. APPLES in a crate by CRATES to get APPLES in a shipment) just
> define a new multiply operator on the mixed types so the "conversion"
> is hidden and "units" are enforced by the compiler.
>
>                                         R. Tim Coslet

This only solves part of the problem, though.  It's no problem to
define this function: 

    function "*" (left : APPLES;  right : CRATES) return APPLES_IN_SHIPMENT;

But ideally, you'd like a way to prevent the programmer from doing
something dumb like multiplying apples and apples.

    type APPLES is new FLOAT;
    x, y, z : APPLES;

    z := x * y;

This last statement, of course, makes no sense in real life, but it's
allowed in Ada.  You could try something cute like redefining "*":

    function "*" (left, right : APPLES) return APPLES is
    begin
        raise PROGRAM_ERROR;
        return 0.0;     -- Ada won't let us write a function that just raises
                        -- an exception without returning anything!
    end "*";

But the error would not be caught until runtime, unless you have an
optimizer that detects this situation or your compiler supports a
pragma that causes a warning message to be displayed when "*" is used
improperly.  Even more annoying:

    type DISTANCE is new FLOAT;
    type SQUARE_DISTANCE is new FLOAT;

    function "*" (x, y : DISTANCE) return SQUARE_DISTANCE;
    function "/" (x : SQUARE_DISTANCE;  y : DISTANCE) return DISTANCE;

    function "*" (x, y : DISTANCE) return DISTANCE;
        -- implemented as an exception raise
    function "/" (x, y : DISTANCE) return DISTANCE;
        -- implemented as an exception raise

    ...

    d1, d2, d3, d4 : DISTANCE;

    ...
   
    d1 := (d2 * d3) / d4;

This is an example you would like to see be legal, since it does make
sense in terms of physics.  But Ada will, I believe, think the
expression is ambiguous.  Which "*" do you use for d2 * d3?  The one
that returns SQUARE_DISTANCE, or the one that returns DISTANCE and
raises an exception?  There's no way for the compiler to tell, so
you'll get an error at compile time.  In this case, you really need
the ability to *delete* the standard "*" function, instead of just
coding it as a function that raises PROGRAM_ERROR.  Does 9X support
this type of feature?

By the way, you can get around this particular problem like this:

   d1 := SQUARE_DISTANCE'(d2 * d3) / d4;

                                -- Adam

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

* Re: What's the difference between...
@ 1993-02-15  1:55 cis.ohio-state.edu!zaphod.mps.ohio-state.edu!sdd.hp.com!portal!cup.portal
  0 siblings, 0 replies; 13+ messages in thread
From: cis.ohio-state.edu!zaphod.mps.ohio-state.edu!sdd.hp.com!portal!cup.portal @ 1993-02-15  1:55 UTC (permalink / raw)


In article: <C2GFBx.GJH@irvine.com>
	adam@irvine.com (Adam Beneschan) wrote:
>In article <75591@cup.portal.com> R_Tim_Coslet@cup.portal.com writes:
>> Actually, if you know you are going to be multiplying mixed types
>> (e.g. APPLES in a crate by CRATES to get APPLES in a shipment) just
>> define a new multiply operator on the mixed types so the "conversion"
>> is hidden and "units" are enforced by the compiler.
>>
>>                                         R. Tim Coslet
>
>This only solves part of the problem, though.  It's no problem to
>define this function: 
>
>    function "*" (left : APPLES;  right : CRATES) return APPLES;
>
>But ideally, you'd like a way to prevent the programmer from doing
>something dumb like multiplying apples and apples.

Well, if you REALLY want this level of control, creat a package with all
your types in it and make them PRIVATE and only define the operations
that are actually physically correct. Then the compiler catches everything
at compile time.

                                        R. Tim Coslet

Usenet: R_Tim_Coslet@cup.portal.com
        technology, n.  domesticated natural phenomena

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

* Re: What's the difference between...
@ 1993-02-15 13:24 cis.ohio-state.edu!zaphod.mps.ohio-state.edu!darwin.sura.net!haven.umd.ed
  0 siblings, 0 replies; 13+ messages in thread
From: cis.ohio-state.edu!zaphod.mps.ohio-state.edu!darwin.sura.net!haven.umd.ed @ 1993-02-15 13:24 UTC (permalink / raw)


It is so nice to see an Ada discussion in comp.lang.ada ....

Ken.
.

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

* Re: What's the difference between...
@ 1993-02-16 15:03 Robert I. Eachus
  0 siblings, 0 replies; 13+ messages in thread
From: Robert I. Eachus @ 1993-02-16 15:03 UTC (permalink / raw)


In article <75650@cup.portal.com> R_Tim_Coslet@cup.portal.com writes:

 > Well, if you REALLY want this level of control, creat a package with all
 > your types in it and make them PRIVATE and only define the operations
 > that are actually physically correct. Then the compiler catches everything
 > at compile time.

   Actually, for this example the best choice is to use a fixed point
type for Apples.  The only predefined multiply and divide operations
you get (that don't require conversions) are for multplication and
division by integers:

       type Apples is delta 1.0 range 0.0..2.0**31;
       -- Use a smaller delta if you need to slice apples.
       subtype Crates is Integer range 0.0..Integer'LAST;
       -- Could use a type and define * and / for Apples, but then 2 *
       -- Apples would be ambiguous.
       A,T: Apples;
       C: Crates;
     begin
       T := A * C; -- OK;
       T := A * A; -- wrong.
       ..


       
--

					Robert I. Eachus

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

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

* Re: What's the difference between...
@ 1993-02-16 16:17 enterpoop.mit.edu!ira.uka.de!scsing.switch.ch!sicsun!disuns2!lglsun!kipfe
  0 siblings, 0 replies; 13+ messages in thread
From: enterpoop.mit.edu!ira.uka.de!scsing.switch.ch!sicsun!disuns2!lglsun!kipfe @ 1993-02-16 16:17 UTC (permalink / raw)


In article <9302121052.aa23420@Paris.ics.uci.edu>, you write:
: these two type declarations:
: 
: type Placement is range 0 .. 10;
: 
: subtype Placement is INTEGER range 0 .. 10;
: 
: The reason I ask this, is that I have the duty here at U.C. Irvine of 
: teaching the students of an Intro to Software Engineering course 
: enough Ada for them to do their homework assignments.  I get two 
: 1.5 hour lectures to do this.
: 
: One of my students asked what is the difference between the two type
: declarations.

You didn't write two type declarations; you wrote one type declaration
and one subtype declaration.

Look first at the definition of a type declaration (RM 3.3)

Declaring a numerical type has the effect to define a new type AND to
implicitely define the operations on it (RM 3.5.4, 3.5.5, 4.5.3 to
4.5.5).  This type is either the "Base type" and his own subtype.

When you define a new type, you are free to add a representation
clause (RM 13.2) such as

  type Placement is range 0 .. 10;
  for Placement use 4;

The compiler must store objects on 4 bits if it accepts the
representation but the compiler is free to generate some code to move
the 4 bits objects into 8 or 32 bits registers. You can see that the
operations related to objects of type Placement can't be strictly the
same as those for predefined type Integer. This is the effect of type
definition.

Now look at the definition of a subtype declaration (RM 3.3.2)

The declaration of a subtype is in fact the declaration of new bounds
applied to a base type in order to restrict the available set of
values. The bounds can be those defined for the base type or more
restrictive.

  subtype My_1_Placement is Placement range 0 .. 10; -- Renaming
  subtype My_2_Placement is Placement range 0 ..  5; -- restriction
  
The subtype actually serves as an invariant, objects are always of base
type, the storage size and operations are always those from base type.
The key here is to know that some "operations" act on the base type,
while others act on the subtype. Operations like "+", "-" act on the
base type, some attributes like 'First, 'Last act accordingly to the
subtype bounds.  Look carefully the expression "base type" and
"subtype" in the section RM-A, in particular for 'SUCC, 'FIRST and
'BASE'FIRST.


There is one more point. Imagine you have an expression like
  Dest := A + B + C - D - E;
Each individual value of A, B, C, D, E can be inside bounds. Some
subexpressions can be out of bounds (e.g. A + B) but the result of
expression can be inside of bounds. Compiler may or may not return a
result, depending on the implementation. If it stores objects on 4 bits but
use primitive operations of processor on 8 bits, it can handle
some subexpressions out of bounds.

This is because of the main principle of assignment:

  " Assignment consist of: evaluating the right part, verifying if 
    the result is compatible with the left part; if they are compatible
    make the assignment, if not raise an exception".

Hope this helps.

			Phil.

-- 
| Swiss Federal Institute of Technology |  
| Software Engineering Laboratory       |  Clever thougth is currently
| Philippe Kipfer (PKR)                 |         proceeding ....
| E-Mail: kipfer@lglsun.epfl.ch         |

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

* Re: What's the difference between...
@ 1993-02-16 17:34 John Bollenbacher
  0 siblings, 0 replies; 13+ messages in thread
From: John Bollenbacher @ 1993-02-16 17:34 UTC (permalink / raw)


Mr. Kenneth Rowe (rowe@umbc.edu) wrote:
: It is so nice to see an Ada discussion in comp.lang.ada ....
: 
Hear, hear.

: Ken.
: .
: 

--
-----------------------------------------------------------------------------
- John Bollenbacher                                        jhb@dale.cts.com -
- Titan Linkabit Corp.                                       (619) 552-9963 -
- 3033 Science Park Rd.                                                     -
- San Diego, Ca. 92121                                                      -
-----------------------------------------------------------------------------

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

end of thread, other threads:[~1993-02-16 17:34 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1993-02-12 22:58 What's the difference between Robert I. Eachus
  -- strict thread matches above, loose matches on Subject: below --
1993-02-16 17:34 John Bollenbacher
1993-02-16 16:17 enterpoop.mit.edu!ira.uka.de!scsing.switch.ch!sicsun!disuns2!lglsun!kipfe
1993-02-16 15:03 Robert I. Eachus
1993-02-15 13:24 cis.ohio-state.edu!zaphod.mps.ohio-state.edu!darwin.sura.net!haven.umd.ed
1993-02-15  1:55 cis.ohio-state.edu!zaphod.mps.ohio-state.edu!sdd.hp.com!portal!cup.portal
1993-02-14 19:55 Adam Beneschan
1993-02-14  3:08 agate!spool.mu.edu!sdd.hp.com!portal!cup.portal.com!R_Tim_Coslet
1993-02-13 19:18 agate!spool.mu.edu!hri.com!noc.near.net!inmet!spock!stt
1993-02-13  5:30 Alex Blakemore
1993-02-12 23:57 Mark A Biggar
1993-02-12 23:51 kronos.arc.nasa.gov!butch!LMSC5.IS.LMSC.LOCKHEED.COM!LJ10891
1993-02-12 18:52 Kenneth Anderson

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