これらの式を組み合わせることで、動作する関数定義を作成できます。しかし、詳しく見てみると、ローカル変数の一つが不要であることがわかります!
関数の定義は次のようになります。
;;; First subtractive version.
(defun triangle (number-of-rows)
"Add up the number of pebbles in a triangle."
(let ((total 0)
(number-of-pebbles-in-row number-of-rows))
(while (> number-of-pebbles-in-row 0)
(setq total (+ total number-of-pebbles-in-row))
(setq number-of-pebbles-in-row
(1- number-of-pebbles-in-row)))
total))
記述通り、この関数は動作します。
ただし、number-of-pebbles-in-rowは不要です。
triangle 関数が評価される際、シンボル number-of-rows
には数値が束縛され、初期値が与えられます。その数値は、あたかもローカル変数であるかのように関数本体内で変更でき、そのような変更が関数外の変数の値に影響を与える心配はありません。これは
Lisp の非常に有用な特性であり、変数 number-of-rows を、number-of-pebbles-in-row
が使用されている関数内のあらゆる箇所で使用できることを意味します。
こちらが、もう少しすっきりと記述した関数の別バージョンです:
(defun triangle (number) ; Second version.
"Return sum of numbers 1 through NUMBER inclusive."
(let ((total 0))
(while (> number 0)
(setq total (+ total number))
(setq number (1- number)))
total))
要するに、適切に記述されたwhileループは、3つの部分で構成されます: