GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/eintr/Compute-a-Remainder.html ・ emacs-doc.conao3.com

C.2.1 サイドトリップ:剰余の計算

Lispにおいて、剰余を計算する関数は % です。 この関数は、第1引数を第2引数で割ったときの剰余を返します。 たまたま、% は Emacs Lisp の関数であり、apropos を使って見つけることはできません。M-x apropos RET remainder RET と入力しても、何も見つからないからです。 % の存在を知る唯一の方法は、このような書籍や Emacs Lisp のソースコードでそれについて読むことです。

以下の2つの式を評価することで、%関数を試すことができます。

(% 7 5)

(% 10 5)

1つ目の式は2を返し、2つ目の式は0を返します。

戻り値が0かそれ以外の数値かを判定するには、zerop関数を使用できます。この関数は、数値である必要がある引数が0の場合、tを返します。

(zerop (% 7 5))
     ⇒ nil

(zerop (% 10 5))
     ⇒ t

したがって、グラフの高さが5で割り切れる場合、次の式はtを返します。

(zerop (% height 5))

(heightの値は、もちろん(apply 'max numbers-list)から求めることができます。)

一方で、height の値が5の倍数でない場合は、値を次の大きい5の倍数にリセットしたいと考えます。これは、すでに馴染みのある関数を用いた単純な算術処理です。まず、height の値を5で割り、その数に5が何回入るかを算出します。したがって、12を5で割ると2になります。この商に1を足して5を掛ければ、高さよりも大きい次の5の倍数が得られます。12を5で割ると2になります。2に1を足して5を掛けると、結果は15となり、これが12より大きい次の5の倍数となります。これを表すLispの式は以下の通りです:

(* (1+ (/ height 5)) 5)

例えば、以下を評価すると、結果は15になります:

(* (1+ (/ 12 5)) 5)

これまでの議論では、Y軸の間隔ラベルの値として5を使用してきましたが、別の値を使いたい場合もあるでしょう。汎用性を持たせるため、5を値を代入できる変数に置き換えるべきです。この変数に付ける名前として考えられる最善のものは、Y-axis-label-spacingです。

この用語とif式を用いて、以下を生成します。

(if (zerop (% height Y-axis-label-spacing))
    height
  ;; else
  (* (1+ (/ height Y-axis-label-spacing))
     Y-axis-label-spacing))

この式は、高さがY-axis-label-spacingの値の偶数倍である場合はheightの値そのものを返し、そうでない場合はY-axis-label-spacingの値の次の上位倍数に等しいheightの値を計算して返します。

これで、この式を(まずY-axis-label-spacingの値を設定した後で)print-graph関数のlet式に組み込むことができます:

(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))))
...

(let* 関数の使用に注意してください。height の初期値は (apply 'max numbers-list) 式によって一度計算され、その後、height の計算結果を用いて最終的な値が算出されます。let* の詳細については、let* 式を参照してください。)