[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

MIN and MAX (long message)



   Date: Mon, 7 Aug 89 16:02:42 PDT
   From: will@cs.uoregon.edu

   Guy Steele Jr:
       ...every C weenie has the formula
	 #define max(x,y) ((x) > (y)) ? (x) : (y)
       engraved in his little weenie brain.  See?  MAX really is a conditional.

   I'm not much of a C weenie, and I don't have a description of the
   proposed (or actual?) ANSI standard, but I think I know enough C to
   suspect that Guy didn't mean for us Scheme weenies to take this seriously.
   When examined more closely, Guy's example shows that C weenies think more
   like me than like Guy.  (This doesn't surprise me, unfortunately.)

   C is a statically typed language, with very little polymorphism, that
   regards ints and floats as different types.  (I'm going to speak as
   though all the different integer types were collapsed into one type, and
   all the different float types into one type.)  The two alternatives of
   a conditional expression must have the same type, or else be convertible
   to the same type using C's conversion rules.  If you define max as Guy
   suggested and then write max(2.5, 1000) as an expression, then the result
   of that expression will be a float (1000.0), not an int.

   If you write max(2.5, 1000) in a context that expects an int, then the
   floating point 1000.0 will be converted back into an int (1000).  (It
   isn't wise to regard that conversion as part of the expression's
   semantics, because you would then have to believe that max(2, 1000.5)
   also evaluates to an int.)  Hence max(2.5, 1000) in an int context is
   really the equivalent of (INEXACT->EXACT (TRUNCATE (MAX 2.5 1000))) in
   Scheme.

   So if MAX really is a conditional in C, then (MAX 2.5 1000) ==> 1000.0
   is consistent with MAX being a conditional.  It seems that Guy's example
   actually supports the R3.95RS semantics he was arguing against.

But my point of view is that the MAX operation per se, like other C
operators is *not* polymorphic.  They operate only on two ints or
two floats.  The type mechanism enforces this requirement by inserting
coercions; the point is that these coercions are outside the control
of the implementation of the operation itself, and therefore not
properly a part of them.  In exactly the same way that max(2.5, 1000)
in an int context ends up having a coercion inserted, so the coercion
that converts 1000 to a float is artificially inserted.