diff --git a/README.md b/README.md index 2b44acf..9567edf 100644 --- a/README.md +++ b/README.md @@ -250,6 +250,7 @@ These combinators require Emacs 24 for its lexical scope. So they are offered in * [-orfn](#-orfn-rest-preds) `(&rest preds)` * [-andfn](#-andfn-rest-preds) `(&rest preds)` * [-iteratefn](#-iteratefn-fn-n) `(fn n)` +* [-fixfn](#-fixfn-fn) `(fn)` * [-prodfn](#-prodfn-rest-fns) `(&rest fns)` ## Anaphoric functions @@ -1930,6 +1931,19 @@ This function satisfies the following law: (funcall (-iteratefn 'cdr 3) '(1 2 3 4 5)) ;; => '(4 5) ``` +#### -fixfn `(fn)` + +Return a function that computes the (least) fixpoint of `fn`. + +`fn` is a unary function, results are compared with `equal`. + +In types: (a -> a) -> a -> a. + +```cl +(funcall (-fixfn 'cos) 0.7) ;; => 0.7390851332151607 +(funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0) ;; => 1.8555845286409378 +``` + #### -prodfn `(&rest fns)` Take a list of n functions and return a function that takes a diff --git a/dash-functional.el b/dash-functional.el index eb2484a..115f137 100644 --- a/dash-functional.el +++ b/dash-functional.el @@ -135,6 +135,19 @@ 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) + "Return a function that computes the (least) fixpoint of FN. + +FN is a unary function, results are compared with `equal'. + +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))) + (defun -prodfn (&rest fns) "Take a list of n functions and return a function that takes a list of length n, applying i-th function to i-th element of the diff --git a/dash.el b/dash.el index c90d3bf..9ba16ea 100644 --- a/dash.el +++ b/dash.el @@ -1780,6 +1780,7 @@ structure such as plist or alist." "-orfn" "-andfn" "-iteratefn" + "-fixfn" "-prodfn" )) (special-variables '( diff --git a/dev/examples.el b/dev/examples.el index 04fb8c3..9d8c9ea 100644 --- a/dev/examples.el +++ b/dev/examples.el @@ -801,6 +801,12 @@ new list." (equal (funcall (-iteratefn fn 5) init) (-last-item (-iterate fn init (1+ 5))))))) + (defexamples -fixfn + ;; Find solution to cos(x) = x + (funcall (-fixfn 'cos) 0.7) => 0.7390851332151607 + ;; Find solution to x^4 - x - 10 = 0 + (funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0) => 1.8555845286409378) + (defexamples -prodfn (funcall (-prodfn '1+ '1- 'int-to-string) '(1 2 3)) => '(2 1 "3") (-map (-prodfn '1+ '1-) '((1 2) (3 4) (5 6) (7 8))) => '((2 1) (4 3) (6 5) (8 7))