Next: Y Axis Element, Previous: Height of label, Up: print-Y-axis [Contents][Index]
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, for more about
let*
.)
Next: Y Axis Element, Previous: Height of label, Up: print-Y-axis [Contents][Index]