DEFUN

define a function symbol
Major Section:  EVENTS

Examples:
(defun app (x y)
  (if (consp x)
      (cons (car x) (app (cdr x) y))
      y))

(defun fact (n) (declare (xargs :guard (and (integerp n) (>= n 0)))) (if (zp n) 1 (* n (fact (1- n)))))

General Form: (defun fn (var1 ... varn) doc-string dcl ... dcl body),

where fn is the symbol you wish to define and is a new symbolic name (see name), (var1 ... varn) is its list of formal parameters (see name), and body is its body. The definitional axiom is logically admissible provided certain restrictions are met. These are sketched below.

Note that ACL2 does not support the use of lambda-list keywords (such as &optional) in the formals list of functions. We do support some such keywords in macros and often you can achieve the desired syntax by defining a macro in addition to the general version of your function. See defmacro. The documentation string, doc-string, is optional; for a description of its form, see doc-string.

The declarations (see declare), dcl, are also optional. If more than one dcl form appears, they are effectively grouped together as one. Perhaps the most commonly used ACL2 specific declaration is of the form (declare (xargs :guard g :measure m)). This declaration in the defun of some function fn has the effect of making the ``guard'' for fn be the term g and the ``measure'' be the term m. The notion of ``measure'' is crucial to ACL2's definitional principle. The notion of ``guard'' is not, and is discussed elsewhere; see verify-guards and see set-verify-guards-eagerness. Note that the :measure is ignored in :program mode; see defun-mode.

We now briefly discuss the ACL2 definitional principle, using the following definition form which is offered as a more or less generic example.

(defun fn (x y)
  (declare (xargs :guard (g x y)
                  :measure (m x y)))
  (if (test x y)
      (stop x y)
    (step (fn (d x) y))))
Note that in our generic example, fn has just two arguments, x and y, the guard and measure terms involve both of them, and the body is a simple case split on (test x y) leading to a ``non-recursive'' branch, (stop x y), and a ``recursive'' branch. In the recursive branch, fn is called after ``decrementing'' x to (d x) and some step function is applied to the result. Of course, this generic example is quite specific in form but is intended to illustrate the more general case.

Provided this definition is admissible under the logic, as outlined below, it adds the following axiom to the logic.

Defining Axiom:
(fn x y)
  =
(if (test x y)
    (stop x y)
  (step (fn (d x) y)))
Note that the guard of fn has no bearing on this logical axiom.

This defining axiom is actually implemented in the ACL2 system by a :definition rule, namely

(equal (fn x y)
       (if (test a b)
           (stop a b)
         (step (fn (d a) b)))).
See definition for a discussion of how definition rules are applied. Roughly speaking, the rule causes certain instances of (fn x y) to be replaced by the corresponding instances of the body above. This is called ``opening up'' (fn x y). The instances of (fn x y) opened are chosen primarily by heuristics which determine that the recursive calls of fn in the opened body (after simplification) are more desirable than the unopened call of fn.

This discussion has assumed that the definition of fn was admissible. Exactly what does that mean? First, fn must be a previously unaxiomatized function symbol (however, see ld-redefinition-action). Second, the formal parameters must be distinct variable names. Third, the guard, measure, and body should all be terms and should mention no free variables except the formal parameters. Thus, for example, body may not contain references to ``global'' or ``special'' variables; ACL2 constants or additional formals should be used instead.

The final conditions on admissibility concern the termination of the recursion. Roughly put, all applications of fn must terminate. In particular, there must exist a binary relation, rel, and some unary predicate mp such that rel is well-founded on objects satisfying mp, the measure term m must always produce something satisfying mp, and the measure term must decrease according to rel in each recursive call, under the hypothesis that all the tests governing the call are satisfied. By the meaning of well-foundedness, we know there are no infinitely descending chains of successively rel-smaller mp-objects. Thus, the recursion must terminate.

The only primitive well-founded relation in ACL2 is o< (see o<), which is known to be well-founded on the o-ps (see o-p). For the proof of well-foundedness, see proof-of-well-foundedness. However it is possible to add new well-founded relations. For details, see well-founded-relation. We discuss later how to specify which well-founded relation is selected by defun and in the present discussion we assume, without loss of generality, that it is o< on the o-ps.

For example, for our generic definition of fn above, with measure term (m x y), two theorems must be proved. The first establishes that m produces an ordinal:

(o-p (m x y)).
The second shows that m decreases in the (only) recursive call of fn:
(implies (not (test x y))
         (o< (m (d x) y) (m x y))).
Observe that in the latter formula we must show that the ``m-size'' of (d x) and y is ``smaller than'' the m-size of x and y, provided the test, (test x y), in the body fails, thus leading to the recursive call (fn (d x) y).

See o< for a discussion of this notion of ``smaller than.'' It should be noted that the most commonly used ordinals are the natural numbers and that on natural numbers, o< is just the familiar ``less than'' relation (<). Thus, it is very common to use a measure m that returns a nonnegative integer, for then (o-p (m x y)) becomes a simple conjecture about the type of m and the second formula above becomes a conjecture about the less-than relationship of nonnegative integer arithmetic.

The most commonly used measure function is acl2-count, which computes a nonnegative integer size for all ACL2 objects. See acl2-count.

Probably the most common recursive scheme in Lisp programming is when some formal is supposed to be a list and in the recursive call it is replaced by its cdr. For example, (test x y) might be simply (atom x) and (d x) might be (cdr x). In that case, (acl2-count x) is a suitable measure because the acl2-count of a cons is strictly larger than the acl2-counts of its car and cdr. Thus, ``recursion by car'' and ``recursion by cdr'' are trivially admitted if acl2-count is used as the measure and the definition protects every recursive call by a test insuring that the decremented argument is a consp. Similarly, ``recursion by 1-'' in which a positive integer formal is decremented by one in recursion, is also trivially admissible. See built-in-clauses to extend the class of trivially admissible recursive schemes.

We now turn to the question of which well-founded relation defun uses. It should first be observed that defun must actually select both a relation (e.g., o<) and a domain predicate (e.g., o-p) on which that relation is known to be well-founded. But, as noted elsewhere (see well-founded-relation), every known well-founded relation has a unique domain predicate associated with it and so it suffices to identify simply the relation here.

The xargs field of a declare permits the explicit specification of any known well-founded relation with the keyword :well-founded-relation. An example is given below. If the xargs for a defun specifies a well-founded relation, that relation and its associated domain predicate are used in generating the termination conditions for the definition.

If no :well-founded-relation is specified, defun uses the :well-founded-relation specified in the acl2-defaults-table. See set-well-founded-relation to see how to set the default well-founded relation (and, implicitly, its domain predicate). The initial default well-founded relation is o< (with domain predicate o-p).

This completes the brief sketch of the ACL2 definitional principle. Optionally, see ruler-extenders for a more detailed discussion of the termination analysis and resulting proof obligations for admissibility, as well as a discussion of the relation to how ACL2 stores induction schemes.

On very rare occasions ACL2 will seem to "hang" when processing a definition, especially if there are many subexpressions of the body whose function symbol is if (or which macroexpand to such an expression). In those cases you may wish to supply the following to xargs: :normalize nil. This is an advanced feature that turns off ACL2's usual propagation upward of if tests.

The following example illustrates all of the available declarations, but is completely nonsensical. For documentation, see xargs and see hints.

(defun example (x y z a b c i j)
  (declare (ignore a b c)
           (type integer i j)
           (xargs :guard (symbolp x)
                  :measure (- i j)
                  :ruler-extenders :basic
                  :well-founded-relation my-wfr
                  :hints (("Goal"
                           :do-not-induct t
                           :do-not '(generalize fertilize)
                           :expand ((assoc x a) (member y z))
                           :restrict ((<-trans ((x x) (y (foo x)))))
                           :hands-off (length binary-append)
                           :in-theory (set-difference-theories
                                        (current-theory :here)
                                        '(assoc))
                           :induct (and (nth n a) (nth n b))
                           :use ((:instance assoc-of-append
                                            (x a) (y b) (z c))
                                 (:functional-instance
                                   (:instance p-f (x a) (y b))
                                   (p consp)
                                   (f assoc)))))
                  :guard-hints (("Subgoal *1/3'"
                                 :use ((:instance assoc-of-append
                                                  (x a) (y b) (z c)))))
                  :mode :logic
                  :normalize nil
                  :verify-guards nil
                  :non-executable t
                  :otf-flg t))
  (example-body x y z i j))