【Common Lisp】
短い変数名で十分な理由を考える
(リファクタリングと局所的な文脈)

  • 変数名は短くても長くても、読み手が意味を復元できるかどうかが判断基準になる。
  • 数式やループのように、スコープが短く記号が共有されている文脈では、xdxのような短い名前が構造を見やすくする。
  • letの右辺が意味を補えるなら、束縛変数は短くても読みにくくならない。

関連記事

1. 数理科学とリファクタリング

リファクタリングの文脈では、意味のわかりやすい変数名が保守性を高めるとされています。
たとえば、x より userCountd より discountRate のほうが、定義箇所に戻らなくても変数の意味がわかります。

数学とリファクタリング 数学の記法 E = mc² m → 意味が即座に伝わる 共有された記号体系が前提 (loop for x in xs sum (* x x)) スコープが短い → x で十分 プログラミング each-number (* each-number each-number) ← 式の構造が埋もれる dx, dy(慣用的省略形) (sqrt (+ (* dx dx) (* dy dy))) 判断基準:読み手が意味を復元できるか、文脈で十分か

一方、物理学や数学では、 xnε のような短い記号を使うのが標準的です。
たとえば、 E=mc2E = mc^2 の m が質量(mass)を指すと、即座に分かります。

この短さは手抜きではなく、「共有された記号体系」が前提にあります。

1.1. ループの中では記号が自然

プログラミングでも短い変数名の方が読みやすいことがあります。

たとえば、数行のループをそのまま実装した処理です。

(defun sum-of-squares (xs)
  (loop for x in xs
        sum (* x x)))Code language: Lisp (lisp)

xxs の各要素で、スコープは loop の中だけです。
これを説明的に書くなら、

(defun sum-of-squares (numbers)
  (loop for each-number in numbers
        sum (* each-number each-number)))Code language: Lisp (lisp)

(* x x)(* each-number each-number) では、一目で読める量が違うため、かえって把握しにくいです。

1.2. 数式の実装

ユークリッド距離の実装でも同様です。

(defun distance (x1 y1 x2 y2)
  (let ((dx (- x2 x1))
        (dy (- y2 y1)))
    (sqrt (+ (* dx dx)
             (* dy dy)))))Code language: Lisp (lisp)

dxdy は「x方向の差分」「y方向の差分」の慣用的省略で、数学や物理の文脈では広く共有されています。
これを difference-in-x-coordinate にすると、式はわかりにくくなります。

とくに、Common Lispは括弧が多いので、変数名まで長くなると構造を把握しにくくなりやすいです。

2. 記号・省略形・概念名

すべての変数を説明的にしようとすると、かえってコードの構造が見えにくくなることがあるのです。

変数名の3分類 記号 x i n t スコープが極短い 数式・反復処理 意味が文脈で確定 (loop for x in xs sum (* x x)) 慣用的省略形 dx len cfg 省略元が広く共有 読み手がほぼ迷わない 式中で繰り返す値 (let ((len (length v)) …)) 概念名 customer-count retry-limit ドメインの意味を持つ 関数引数・スロット 複数箇所から参照 (defun apply-discount (order discount-rate)) 右辺(let の値式)が意味を補えるなら、変数名は短くてよい

変数名の長さは、三種類に分けて考えることができます。

  • xint のような純粋な記号は、数式や反復処理の中で、その場の操作のための名前として使います。
    スコープが非常に短く、意味が文脈で一意に決まる場合に限ります。
  • lencntidxmsgcfgdxdy のような慣用的省略形は、省略元が広く共有されていて、読み手がほぼ迷わない場合に使います。
    元の語が長く、式の中で何度も出てくるときに特に力を発揮します。
  • customer-countretry-limitinvoice-total のような概念名は、ドメインの意味を持つ値や、関数の引数、クラスのスロット、複数箇所から参照される変数に使います。

短い名前が有効なのは、

  • スコープが短く、定義から使用箇所まで目で追える
  • 読み手が意味を一意に復元できる(記号が共有されているか、文脈で明らか)
  • 完全な名前にすると、式や処理の構造が埋もれる

2.1. letの右辺が意味を補う

Common Lispでは、ローカル変数の定義でletを使います。
このletは、比較的短い変数名に適しています。

let による変数束縛は有効範囲も明確で、変数名は多少、短くても式が十分に説明的なら、読みにくくならないからです。

(let ((len (vector-length v))
      (sum (reduce #'+ xs))
      (msg (render-error-message err)))
  ...)Code language: Lisp (lisp)

たとえば、lensummsg は短いですが、vector-lengthreducerender-error-message という右辺が意味をかなり補っています。
「何から得た値か」がわかりやすく、迷いにくいです。

2.2. 短さが「局所変数のシグナル」になる

Common Lispでは、短い変数名には、意味の省略以外にもう一つ働きがあります。
「これはその場の局所的な束縛だ」と読み手に伝える効果です。

(defun normalize-vector (vec)
  (let ((len (vector-length vec)))
    (scale-vector vec (/ 1 len))))Code language: Lisp (lisp)

vector-lengthscale-vector は関数らしい名前で、len は局所変数らしい名前です。

説明的な名前は「再利用される概念かもしれない」「他の文脈ともつながるかもしれない」と感じさせやすいです。
短い名前は「今ここでだけ使う補助的な値だ」という印象を与えます。
副次的な効果ですが、コードのリズムに影響します。

3. 一般的でない変数名

逆に言えば、スコープが長い、意味が曖昧になりうる、ドメイン知識を背負っている、このいずれかに当てはまるなら、説明的な名前が必要になります。

しかし、letの変数でも、省略名が「一般的」でないと、途端に読みにくくなります。

とくに、業務ロジックの意味を持つ値には、短い名前は向きません。

(let ((d (compute-final-discount order customer campaign)))
  ...)Code language: Lisp (lisp)

たとえば、この d は、discount を省略しているつもりです。
しかし、dは、 deltaday などの意味でよく使われます。
この例では、discount-amount あるいは、せめて disc などと、読む手がかりを残す方がよいでしょう。

3.1. 関数引数の名前

特に、関数の引数はスコープが関数全体に及び、呼び出し側から見ても意味を持ちます。

apply-discountの関数引数orderdiscount-rateor などにすると「何の値か」伝わりません。

;; 読めない
(defun apply-discount (o r)
  (let ((p (order-price o))
        (d (* (order-price o) r)))
    (- p d)))

;; 読める
(defun apply-discount (order discount-rate)
  (let ((original-price (order-price order))
        (discount-amount (* (order-price order) discount-rate)))
    (- original-price discount-amount)))Code language: Lisp (lisp)

引数の名前は、関数の使い方のヒントになるので、わかりやすくした方がよいでしょう。

4. まとめ

短い変数名と説明的な変数名は、どちらも有効です。
これらは、最適化の方向性が違います。

数学は局所的な文脈と共有された記号体系で読む負担を下げます。
プログラミングは局所文脈だけでは足りない場面が多いので、名前そのものに意味を持たせることで補います。

プログラミングでも「局所的で、数式的で、構造上すぐ読める」条件がそろえば、短い名前はよい設計です。
Common Lispでは括弧による構造密度が高いため、その効果が特に大きく出ます。

つまり、判断の基準は「読み手が名前から意味を復元できるか、それとも文脈と右辺だけで十分か」です。
この問いに答えられれば、長さ自体にこだわる必要はありません。