diff --git a/README.md b/README.md index ac54f94..1af9122 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,7 @@ These combinators require Emacs 24 for its lexical scope. So they are offered in * [-not](#-not-pred) `(pred)` * [-orfn](#-orfn-rest-preds) `(&rest preds)` * [-andfn](#-andfn-rest-preds) `(&rest preds)` +* [-iteratefn](#-iteratefn-fn-n) `(fn n)` ## Anaphoric functions @@ -1665,6 +1666,27 @@ In types: [a -> Bool] -> a -> Bool (-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) ;; => '(1 3 5) ``` +#### -iteratefn `(fn n)` + +Return a function `fn` composed `n` times with itself. + +`fn` is a unary function. If you need to use a function of higher +arity, use `-applify` first to turn it into an unary function. + +With n = 0, this acts as identity function. + +In types: (a -> a) -> Int -> a -> a. + +This function satisfies the following law: + + (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init (1+ n))). + +```cl +(funcall (-iteratefn (lambda (x) (* x x)) 3) 2) ;; => 256 +(funcall (-iteratefn '1+ 3) 1) ;; => 4 +(funcall (-iteratefn 'cdr 3) '(1 2 3 4 5)) ;; => '(4 5) +``` + ## Contribute diff --git a/dash-functional.el b/dash-functional.el index 4a00720..bd77519 100644 --- a/dash-functional.el +++ b/dash-functional.el @@ -60,7 +60,7 @@ each fn to the result of applying the previous fn to the arguments (right-to-left)." (lambda (&rest args) (car (-reduce-r-from (lambda (fn xs) (list (apply fn xs))) - args fns)))) + args fns)))) (defun -applify (fn) "Changes an n-arity function FN to a 1-arity function that @@ -120,6 +120,21 @@ PREDS returns non-nil on x. In types: [a -> Bool] -> a -> Bool" (lambda (x) (-all? (-cut funcall <> x) preds))) +(defun -iteratefn (fn n) + "Return a function FN composed N times with itself. + +FN is a unary function. If you need to use a function of higher +arity, use `-applify' first to turn it into an unary function. + +With n = 0, this acts as identity function. + +In types: (a -> a) -> Int -> a -> a. + +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)) + (provide 'dash-functional) ;;; dash-functional.el ends here diff --git a/dev/examples.el b/dev/examples.el index aabd343..220e846 100644 --- a/dev/examples.el +++ b/dev/examples.el @@ -712,4 +712,17 @@ (funcall (-andfn (-cut < <> 10) 'even?) 6) => t (funcall (-andfn (-cut < <> 10) 'even?) 12) => nil (-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) => '(1 3 5)) + + (defexamples -iteratefn + (funcall (-iteratefn (lambda (x) (* x x)) 3) 2) => 256 + (funcall (-iteratefn '1+ 3) 1) => 4 + (funcall (-iteratefn 'cdr 3) '(1 2 3 4 5)) => '(4 5) + (let ((init '(1 2 3 4 5)) + (fn 'cdr)) + (and (equal (funcall (-iteratefn fn 0) init) + (-last-item (-iterate fn init (1+ 0)))) + (equal (funcall (-iteratefn fn 3) init) + (-last-item (-iterate fn init (1+ 3)))) + (equal (funcall (-iteratefn fn 5) init) + (-last-item (-iterate fn init (1+ 5))))))) ))