5.3.1 Optional Arguments

Unless told otherwise, Lisp expects that a function with an argument in its function definition will be called with a value for that argument. If that does not happen, you get an error and a message that says ‘Wrong number of arguments’.

However, optional arguments are a feature of Lisp: a particular keyword is used to tell the Lisp interpreter that an argument is optional. The keyword is &optional. (The ‘&’ in front of ‘optional’ is part of the keyword.) In a function definition, if an argument follows the keyword &optional, no value need be passed to that argument when the function is called.

The first line of the function definition of beginning-of-buffer therefore looks like this:

(defun beginning-of-buffer (&optional arg)

In outline, the whole function looks like this:

(defun beginning-of-buffer (&optional arg)
  (interactive "P")
  (or (is-the-argument-a-cons-cell arg)
      (and are-both-transient-mark-mode-and-mark-active-true)
  (let (determine-size-and-set-it)

The function is similar to the simplified-beginning-of-buffer function except that the interactive expression has "P" as an argument and the goto-char function is followed by an if-then-else expression that figures out where to put the cursor if there is an argument that is not a cons cell.

(Since I do not explain a cons cell for many more chapters, please consider ignoring the function consp. See How Lists are Implemented, and Cons Cell and List Types in The GNU Emacs Lisp Reference Manual.)

The "P" in the interactive expression tells Emacs to pass a prefix argument, if there is one, to the function in raw form. A prefix argument is made by typing the META key followed by a number, or by typing C-u and then a number. (If you don’t type a number, C-u defaults to a cons cell with a 4. A lowercase "p" in the interactive expression causes the function to convert a prefix arg to a number.)

The true-or-false-test of the if expression looks complex, but it is not: it checks whether arg has a value that is not nil and whether it is a cons cell. (That is what consp does; it checks whether its argument is a cons cell.) If arg has a value that is not nil (and is not a cons cell), which will be the case if beginning-of-buffer is called with a numeric argument, then this true-or-false-test will return true and the then-part of the if expression will be evaluated. On the other hand, if beginning-of-buffer is not called with an argument, the value of arg will be nil and the else-part of the if expression will be evaluated. The else-part is simply point-min, and when this is the outcome, the whole goto-char expression is (goto-char (point-min)), which is how we saw the beginning-of-buffer function in its simplified form.