@ -135,18 +135,65 @@ This function satisfies the following law:
( funcall ( -iteratefn fn n ) init ) = ( -last-item ( -iterate fn init ( 1+ n ) ) ) . "
( lambda ( x ) ( --dotimes n ( setq x ( funcall fn x ) ) ) x ) )
( defun -fixfn ( fn )
( defun -counter ( &optional beg end inc )
" Return a closure that counts from BEG to END, with increment INC.
The closure will return the next value in the counting sequence
each time it is called, and nil after END is reached. BEG
defaults to 0 , INC defaults to 1 , and if END is nil , the counter
will increment indefinitely.
The closure accepts any number of arguments, which are discarded. "
( let ( ( inc ( or inc 1 ) )
( n ( or beg 0 ) ) )
( lambda ( &rest _ )
( when ( or ( not end ) ( < n end ) )
( prog1 n
( setq n ( + n inc ) ) ) ) ) ) )
( defvar -fixfn-max-iterations 1000
" The default maximum number of iterations performed by `-fixfn'
unless otherwise specified. " )
( defun -fixfn ( fn &optional equal-test halt-test )
" Return a function that computes the (least) fixpoint of FN.
FN is a unary function, results are compared with ` equal '.
FN must be a unary function. The returned lambda takes a single
argument, X, the initial value for the fixpoint iteration. The
iteration halts when either of the following conditions is satisified:
1. Iteration converges to the fixpoint, with equality being
tested using EQUAL-TEST. If EQUAL-TEST is not specified,
` equal ' is used. For functions over the floating point
numbers, it may be necessary to provide an appropriate
appoximate comparsion test.
2. HALT-TEST returns a non-nil value. HALT-TEST defaults to a
simple counter that returns t after ` -fixfn-max-iterations ',
to guard against infinite iteration. Otherwise, HALT-TEST
must be a function that accepts a single argument, the
current value of X, and returns non-nil as long as iteration
should continue. In this way, a more sophisticated
convergence test may be supplied by the caller.
The return value of the lambda is either the fixpoint or, if
iteration halted before converging, a cons with car ` halted ' and
cdr the final output from HALT-TEST.
In types: ( a -> a ) -> a -> a. "
( lambda ( x )
( let ( ( re ( funcall fn x ) ) )
( while ( not ( equal x re ) )
( setq x re )
( setq re ( funcall fn re ) ) )
re ) ) )
( let ( ( eqfn ( or equal-test 'equal ) )
( haltfn ( or halt-test
( -not
( -counter 0 -fixfn-max-iterations ) ) ) ) )
( lambda ( x )
( let ( ( re ( funcall fn x ) )
( halt? ( funcall haltfn x ) ) )
( while ( and ( not halt? ) ( not ( funcall eqfn x re ) ) )
( setq x re
re ( funcall fn re )
halt? ( funcall haltfn re ) ) )
( if halt? ( cons 'halted halt? )
re ) ) ) ) )
( defun -prodfn ( &rest fns )
" Take a list of n functions and return a function that takes a