MUTUAL-RECURSION

define some mutually recursive functions
Major Section: EVENTS

Example:
(mutual-recursion
 (defun evenlp (x)
 (if (consp x) (oddlp (cdr x)) t))
 (defun oddlp (x)
 (if (consp x) (evenlp (cdr x)) nil)))
General Form:
(mutual-recursion def1 ... defn)
where each defi is a call of defun , defund , defun-nx ,
or defund-nx.
When mutually recursive functions are introduced it is necessary to do the termination analysis on the entire clique of definitions. Each defun form specifies its own measure, either with the :measure keyword xarg (see xargs) or by default to acl2-count . When a function in the clique calls a function in the clique, the measure of the callee's actuals must be smaller than the measure of the caller's formals -- just as in the case of a simply recursive function. But with mutual recursion, the callee's actuals are measured as specified by the callee's defun while the caller's formals are measured as specified by the caller's defun . These two measures may be different but must be comparable in the sense that o< decreases through calls.

If you want to specify :hints or :guard-hints (see xargs), you can put them in the xargs declaration of any of the defun forms, as the :hints from each form will be appended together, as will the guard-hints from each form.

You may find it helpful to use a lexicographic order, the idea being to have a measure that returns a list of two arguments, where the first takes priority over the second. Here is an example.

(include-book "ordinals/lexicographic-ordering" :dir :system)
(encapsulate
 ()
 (set-well-founded-relation l<) ; will be treated as LOCAL
 (mutual-recursion
 (defun foo (x)
 (declare (xargs :measure (list (acl2-count x) 1)))
 (bar x))
 (defun bar (y)
 (declare (xargs :measure (list (acl2-count y) 0)))
 (if (zp y) y (foo (1- y))))))

The guard analysis must also be done for all of the functions at the same time. If any one of the defun s specifies the :verify-guards xarg to be nil, then guard verification is omitted for all of the functions. Similarly, if any one of the defun s specifies the :non-executable xarg to be t, or if any of the definitions uses defun-nx or defund-nx, then every one of the definitions will be treated as though it specifies a :non-executable xarg of t.

Technical Note: Each defi above must be a call of defun , defund , defun-nx , or defund-nx. In particular, it is not permitted for a defi to be an arbitrary form that macroexpands into a defun form. This is because mutual-recursion is itself a macro, and since macroexpansion occurs from the outside in, at the time (mutual-recursion def1 ... defk) is expanded the defi have not yet been macroexpanded.

Suppose you have defined your own defun -like macro and wish to use it in a mutual-recursion expression. Well, you can't. (!) But you can define your own version of mutual-recursion that allows your defun -like form. Here is an example. Suppose you define

(defmacro my-defun (&rest args) (my-defun-fn args))
where my-defun-fn takes the arguments of the my-defun form and produces from them a defun form. As noted above, you are not allowed to write (mutual-recursion (my-defun ...) ...). But you can define the macro my-mutual-recursion so that
(my-mutual-recursion (my-defun ...) ... (my-defun ...))
expands into (mutual-recursion (defun ...) ... (defun ...)) by applying my-defun-fn to each of the arguments of my-mutual-recursion.
(defun my-mutual-recursion-fn (lst)
 (declare (xargs :guard (alistp lst)))
; Each element of lst must be a consp (whose car, we assume, is always
; MY-DEFUN). We apply my-defun-fn to the arguments of each element and
; collect the resulting list of DEFUNs.
 (cond ((atom lst) nil)
 (t (cons (my-defun-fn (cdr (car lst)))
 (my-mutual-recursion-fn (cdr lst))))))
(defmacro my-mutual-recursion (&rest lst)
; Each element of lst must be a consp (whose car, we assume, is always
; MY-DEFUN). We obtain the DEFUN corresponding to each and list them
; all inside a MUTUAL-RECURSION form.
 (declare (xargs :guard (alistp lst)))
 (cons 'mutual-recursion (my-mutual-recursion-fn lst))).




AltStyle によって変換されたページ (->オリジナル) /