eintr: Compute a Remainder

 
 C.2.1 Side Trip: Compute a Remainder
 ------------------------------------
 
 In Lisp, the function for computing a remainder is ‘%’.  The function
 returns the remainder of its first argument divided by its second
 argument.  As it happens, ‘%’ is a function in Emacs Lisp that you
 cannot discover using ‘apropos’: you find nothing if you type ‘M-x
 apropos <RET> remainder <RET>’.  The only way to learn of the existence
 of ‘%’ is to read about it in a book such as this or in the Emacs Lisp
 sources.
 
    You can try the ‘%’ function by evaluating the following two
 expressions:
 
      (% 7 5)
 
      (% 10 5)
 
 The first expression returns 2 and the second expression returns 0.
 
    To test whether the returned value is zero or some other number, we
 can use the ‘zerop’ function.  This function returns ‘t’ if its
 argument, which must be a number, is zero.
 
      (zerop (% 7 5))
           ⇒ nil
 
      (zerop (% 10 5))
           ⇒ t
 
    Thus, the following expression will return ‘t’ if the height of the
 graph is evenly divisible by five:
 
      (zerop (% height 5))
 
 (The value of ‘height’, of course, can be found from ‘(apply 'max
 numbers-list)’.)
 
    On the other hand, if the value of ‘height’ is not a multiple of
 five, we want to reset the value to the next higher multiple of five.
 This is straightforward arithmetic using functions with which we are
 already familiar.  First, we divide the value of ‘height’ by five to
 determine how many times five goes into the number.  Thus, five goes
 into twelve twice.  If we add one to this quotient and multiply by five,
 we will obtain the value of the next multiple of five that is larger
 than the height.  Five goes into twelve twice.  Add one to two, and
 multiply by five; the result is fifteen, which is the next multiple of
 five that is higher than twelve.  The Lisp expression for this is:
 
      (* (1+ (/ height 5)) 5)
 
 For example, if you evaluate the following, the result is 15:
 
      (* (1+ (/ 12 5)) 5)
 
    All through this discussion, we have been using 5 as the value for
 spacing labels on the Y axis; but we may want to use some other value.
 For generality, we should replace 5 with a variable to which we can
 assign a value.  The best name I can think of for this variable is
 ‘Y-axis-label-spacing’.
 
    Using this term, and an ‘if’ expression, we produce the following:
 
      (if (zerop (% height Y-axis-label-spacing))
          height
        ;; else
        (* (1+ (/ height Y-axis-label-spacing))
           Y-axis-label-spacing))
 
 This expression returns the value of ‘height’ itself if the height is an
 even multiple of the value of the ‘Y-axis-label-spacing’ or else it
 computes and returns a value of ‘height’ that is equal to the next
 higher multiple of the value of the ‘Y-axis-label-spacing’.
 
    We can now include this expression in the ‘let’ expression of the
 ‘print-graph’ function (after first setting the value of
 ‘Y-axis-label-spacing’):
 
      (defvar Y-axis-label-spacing 5
        "Number of lines from one Y axis label to next.")
 
      ...
      (let* ((height (apply 'max numbers-list))
             (height-of-top-line
              (if (zerop (% height Y-axis-label-spacing))
                  height
                ;; else
                (* (1+ (/ height Y-axis-label-spacing))
                   Y-axis-label-spacing)))
             (symbol-width (length graph-blank))))
      ...
 
 (Note use of the ‘let*’ function: the initial value of height is
 computed once by the ‘(apply 'max numbers-list)’ expression and then the
 resulting value of ‘height’ is used to compute its final value.  See
 The ‘let*’ expression fwd-para let, for more about ‘let*’.)