DEFUN.html -- ACL2 Version 6.3

## 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-p`s (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-p`s.

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-count`s 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-clause 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 and most hint keywords, 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))