sommar@enea.se (Erland Sommarskog) (03/15/90)
Marvin Rubenstein (marv@ism780.UUCP) writes: >I am unaware of any commonly available language that prevents this form of >mistake. Look at the following: > > double distance; > double time; > double velocity; > > velocity = distance/time; /* this makes sense */ > velocity = distance+time; /* I mixed 'apples' and 'oranges' and produced > a lemon :-) */ The program below contains the same error and does not compile. I have edited the error messages to stay below 80 columns. PROCEDURE Type_test IS TYPE Meter IS NEW Float; TYPE Seconds IS NEW Float; TYPE Meter_per_seconds IS NEW Float; x : Meter := 2.2; s : Seconds := 3.3; v : Meter_per_seconds; FUNCTION "/"(x : Meter; s : Seconds) RETURN Meter_per_seconds IS BEGIN RETURN Meter_per_seconds(x) / Meter_per_seconds(s); END "/"; BEGIN v := x / s; v := x + s; --------^A ------------^B --A:error: RM 3.3: base type of expression must be meter_per_seconds, line 5 --B:error: RM 3.3: base type of expression must be meter_per_seconds, line 5 END Type_test; In order to get division to work we had to define a function for it. In fact we have to define a function of a similar kind for every operation we want to make. This is a lot of typing, on the other hand: it does well document the rules at hand. Performance won't be an issue. In the sample above, the subprogram would disappear rapidly in the hands of the optimizer. Normally it would be part of a package, but you would mention in it in the INLINE pragma. -- Erland Sommarskog - ENEA Data, Stockholm - sommar@enea.se
news@ism780c.isc.com (News system) (03/16/90)
In article <883@enea.se> sommar@enea.se (Erland Sommarskog) writes: >Marvin Rubenstein (marv@ism780.UUCP) writes: I (Marv Rubinstein) talked about using units for an aid in error detection. [Erland Sommarskog responded] :The program below contains the same error and does not compile. :I have edited the error messages to stay below 80 columns. : : PROCEDURE Type_test IS : : TYPE Meter IS NEW Float; : TYPE Seconds IS NEW Float; : TYPE Meter_per_seconds IS NEW Float; : : x : Meter := 2.2; : s : Seconds := 3.3; : v : Meter_per_seconds; : : FUNCTION "/"(x : Meter; s : Seconds) RETURN Meter_per_seconds IS : BEGIN : RETURN Meter_per_seconds(x) / Meter_per_seconds(s); : END "/"; : : BEGIN : v := x / s; : v := x + s; : --------^A : ------------^B : --A:error: RM 3.3: base type of expression must be meter_per_seconds, line 5 : --B:error: RM 3.3: base type of expression must be meter_per_seconds, line 5 : END Type_test; : :In order to get division to work we had to define a function for it. :In fact we have to define a function of a similar kind for every operation :we want to make. The language I had in mind was more like this. units m -- mass l -- length t -- time f = m*l/(t*t) -- force end units data velocity :real, unit l/t; distance :real, unit l; time :real, unit t; area :real, unit l*l; end data velocity = area/(time*distance); -- this is ok area = distance*distance; -- so is this time =velocity/distance; -- not good area =distance+distance; -- bad The actual language that I was refering to also allowed conversion constants (e.g. for feet to meters) to appear in the units declarations. Thus, conversions were inserted automatically by the compiler. What you are suggesting would, in my opinion, make the programming of a large scientific computation almost impossible. Marv Rubinstein
djones@megatest.UUCP (Dave Jones) (03/17/90)
From article <40346@ism780c.isc.com), by news@ism780c.isc.com (News system): ) In article <883@enea.se) sommar@enea.se (Erland Sommarskog) writes: ))Marvin Rubenstein (marv@ism780.UUCP) writes: ) I (Marv Rubinstein) talked about using units for an aid in error ) detection. ... ) The language I had in mind was more like this. ) ) units ) m -- mass ) l -- length ) t -- time ) f = m*l/(t*t) -- force ) end units I think the catch-phrase here is 'dimensional analysis'. It's not hard to do. I've implemented it in a Pascal superset. It can be done by the compiler if things are simple enough, or at runtime otherwise. You could do a pretty good job of it in C++ without touching the compiler, relying on runtime checks, of course. The trick is to keep, along with each value, an array of integers, one for each dimension, e.g. mass, length, time, force. When values are multiplied, their dimensions are added. Get it? For example, pure 'length' would have a dimension of (0,1,0,0) -- a one in the length-dimension. 'time' would have a dimension of (0,0,1,0) -- a one in the time dimension. 'length/time' would have the dimension (0,1,-1,0) -- the dimension of length _minus_ the dimension of time. Because division is the inverse of multiplication, the time dimension is _subtracted_. I think you can work out the rest.
sommar@enea.se (Erland Sommarskog) (03/20/90)
Marvin Rubenstein (marv@ism780.UUCP) writes: > I (Marv Rubinstein) talked about using units for an aid in error > detection. Where upon I suggested a method of implementing this in Ada. Marvin responds: >The language I had in mind was more like this. > > units > m -- mass > l -- length > t -- time > f = m*l/(t*t) -- force > end units > data > velocity :real, unit l/t; > distance :real, unit l; > time :real, unit t; > area :real, unit l*l; > end data > >The actual language that I was refering to also allowed conversion >constants (e.g. for feet to meters) to appear in the units declarations. >Thus, conversions were inserted automatically by the compiler. What you are >suggesting would, in my opinion, make the programming of a large scientific >computation almost impossible. I was fully aware of what I proposed was not really what you wanted, on the other hand, I don't see any important conceptual difference in your out-line. Your notation is far more compact that the Ada package you would have to write, but once you would had it done, you could go ahead and program your computation. And the package would still be there the next time. Or did I miss something? What in my proposal would make your program impossible to write? The gain, as I see it, with the Ada solution is that we are saved another language with some quite special features that are not of general interest, but instead we implement those features with general mechanisms. After all, there are plenty of applications where units plays about no role at all. There is one point where Ada fails, though. If you declare: US_distance : Feet; Real_world_distance : Meter; you cannot simply write: Real_world_distance := US_distance; but have to rely on a conversion routine: Real_world_distance := Feet_to_meter(US_distance); since Ada doesn't provide overloadable assignment. What's worse is that: Real_world_distance := Meter(US_distance); is a legal, but does only move the bits from the right-hand side to the other, and thus constitute a trap you may fall in. -- Erland Sommarskog - ENEA Data, Stockholm - sommar@enea.se
karl@haddock.ima.isc.com (Karl Heuer) (03/22/90)
In article <907@enea.se> sommar@enea.se (Erland Sommarskog) writes: >Marvin Rubenstein (marv@ism780.UUCP) writes: >>[about having dimensional analysis built into a language] > >I was fully aware of what I proposed was not really what you wanted, >on the other hand, I don't see any important conceptual difference >in your out-line. Your notation is far more compact that the Ada >package you would have to write, but once you would had it done, >you could go ahead and program your computation. And the package >would still be there the next time. The problem is that there are a *lot* of distinct types: a true dimensional analysis language would accept "meter^3/(kilogram*second^2)" automatically; in Ada it works only if the package author had the foresight to include it. >[One pitfall in Ada is that you] have to rely on a conversion routine: > Real_world_distance := Feet_to_meter(US_distance); Or just use a predefined constant of the appropriate type: Real_world_distance := METERS_PER_FOOT * US_distance; since the dimensional analysis will keep you from doing it backwards. Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint