People have often heard that code can be "self-commenting" but that--in lisp--may not mean what you think it does (more often than not I see chunks of code a few lines long with no comments at all and when asked, they always say the "comments are not necessary because the code comments itself"; which is almost always NOT true). The best example of `self-commenting` code I can think of (because it was the first example I saw), comes from the SICP book on the example of rational numbers. The topic/example was in essence about using bottom-up design to support a new data type called a "pair" but it also created what is called `self-commenting` code.
The example starts by building seemingly trivial functions, but those functions assign a "name" to concepts which in turn will result in `self-commenting` code.
;; (numer <pair>)
;; return the numerator of a rational number.
;; (denom <pair>)
;; return the denominator of a rational number.
As you can see these two functions could be replaced with simple calls to `CAR` and `CDR` but the name--the function name--is what is important, not the actual functions within.
Below are a few functions to make a rational number and another to print one and some to perform some arithmetic on the rational numbers.
(defun make
-rat
(n d
/ x
) ;; (make-rat <n> <d>)
;; returns the rational number whose numerator is the integer <n>
;; and whose denominator is the integer <d>.
;; (print-rat <pair>)
;; prints a rational number with a slash.
(defun add
-rat
(pairx pairy
) ;; (add-rat <pairx> <pairy>)
;; preforms addition on two rational number pairs.
(make-rat (+ (* (numer pairx) (denom pairy))
(* (numer pairy) (denom pairx)))
(* (denom pairx) (denom pairy))) )
(defun sub
-rat
(pairx pairy
) ;; (sub-rat <pairx> <pairy>)
;; preform subtraction on two rational number pairs.
(make-rat (- (* (numer pairx) (denom pairy))
(* (numer pairy) (denom pairx)))
(* (denom pairx) (denom pairy))))
(defun mul
-rat
(pairx pairy
) ;; (mul-rat <pairx> <pairy>)
;; preform multiplication on two rational number pairs.
(make-rat (* (numer pairx) (numer pairy))
(* (denom pairx) (denom pairy))) )
(defun div
-rat
(pairx pairy
) ;; (div-rat <pairx> pairy>)
;; preform division on two rational number pairs.
(make-rat (* (numer pairx) (denom pairy))
(* (denom pairx) (numer pairy))) )
(defun equal
-rat?
(pairx pairy
) ;; (eual-rat? <pairx> <pairy>)
;; determine if two rational number pairs are equal.
(= (* (numer pairx) (denom pairy))
(* (numer pairy) (denom pairx))) )
Now we can begin to construct `self-commenting` code. As you can see the operations are pretty self-explanatory; each operation lists the parts and operations and if you try to follow along you can go back upwards into the support procedures and see what parts are what/where. This is because of the names we assigned to each part.
;; make a few rational numbers.
(setq one
-half
(make
-rat
1 2) one-third (make-rat 1 3))
;; print them to the command line.
(print-rat one-half)
(print-rat one-third)
;; add two rational numbers and print the result.
(print-rat
(add-rat
one-half
one-half))
;; subtract two rational numbers and print the results.
(print-rat
(sub-rat
one-half
one-third))
Because of the "bottom-up" and `self-commenting` design this example, we can change the way our program handles rational numbers--easier--without having to refactor. For example, if we alter the `make-rat` function to reduce the rational numbers to their lowest terms before actual construction of the `pair` the entire program is altered without much change.
;; (make-rat <n> <d>)
;; returns the rational number whose numerator is the integer <n>
;; and whose denominator is the integer <d>.
;;
;; NOTE: both <n> and <d> are reduced to their lowest terms before
;; construction of the rational number.
(
This example, given in the SICP book, was a very good example because it taught many lessons in one, but I think it demonstrates the "proper definition of `self-commenting code`" well. However, in reality, the code itself cannot document the "why" something was done, so comments in my opinion are always necessary.
Full code listing:
;; (numer <pair>)
;; return the numerator of a rational number.
;; (denom <pair>)
;; return the denominator of a rational number.
;; (make-rat <n> <d>)
;; returns the rational number whose numerator is the integer <n>
;; and whose denominator is the integer <d>.
;;
;; NOTE: both <n> and <d> are reduced to their lowest terms before
;; construction of the rational number.
(
;; (print-rat <pair>)
;; prints a rational number with a slash.
(defun add
-rat
(pairx pairy
) ;; (add-rat <pairx> <pairy>)
;; preforms addition on two rational number pairs.
(make-rat (+ (* (numer pairx) (denom pairy))
(* (numer pairy) (denom pairx)))
(* (denom pairx) (denom pairy))) )
(defun sub
-rat
(pairx pairy
) ;; (sub-rat <pairx> <pairy>)
;; preform subtraction on two rational number pairs.
(make-rat (- (* (numer pairx) (denom pairy))
(* (numer pairy) (denom pairx)))
(* (denom pairx) (denom pairy))))
(defun mul
-rat
(pairx pairy
) ;; (mul-rat <pairx> <pairy>)
;; preform multiplication on two rational number pairs.
(make-rat (* (numer pairx) (numer pairy))
(* (denom pairx) (denom pairy))) )
(defun div
-rat
(pairx pairy
) ;; (div-rat <pairx> pairy>)
;; preform division on two rational number pairs.
(make-rat (* (numer pairx) (denom pairy))
(* (denom pairx) (numer pairy))) )
(defun equal
-rat?
(pairx pairy
) ;; (eual-rat? <pairx> <pairy>)
;; determine if two rational number pairs are equal.
(= (* (numer pairx) (denom pairy))
(* (numer pairy) (denom pairx))) )
I hope you have as much fun studying this seemingly simple example as I did.
EDIT: Fixed small typo in the first DENOM function listed.
EDIT: Fixed function CDR in DENOM function (Bug by VovKa).
EDIT: changed function LIST to CONS in lowest terms make-rat (Bug by VovKa).