This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-10-21
Channels
- # announcements (3)
- # babashka (98)
- # beginners (69)
- # chlorine-clover (6)
- # cider (24)
- # cljsrn (2)
- # clojure (97)
- # clojure-australia (2)
- # clojure-berlin (6)
- # clojure-dev (57)
- # clojure-dusseldorf (4)
- # clojure-europe (19)
- # clojure-italy (5)
- # clojure-nl (10)
- # clojure-seattle (1)
- # clojure-uk (44)
- # clojuredesign-podcast (13)
- # clojurescript (45)
- # cursive (4)
- # data-science (1)
- # datomic (32)
- # emacs (7)
- # events (5)
- # fulcro (17)
- # java (12)
- # jobs (1)
- # lumo (2)
- # malli (5)
- # observability (16)
- # off-topic (1)
- # pathom (3)
- # pedestal (4)
- # rdf (14)
- # re-frame (54)
- # reagent (4)
- # releases (3)
- # remote-jobs (1)
- # reveal (55)
- # shadow-cljs (34)
- # spacemacs (14)
- # specter (9)
- # tools-deps (16)
- # xtdb (7)
letfn
lets you define recursive functions while (let [my-fn (fn ...)])
does not — one of the benefits of letfn
that occurred to me while listening to your let
cast. Enjoyed it. Thanks guys!
from
:
> All of the names are available in all of the definitions of the functions, as well as the body.
Anonymous functions can be recursive. Most of the time you can use recur
. If you have multiple arities you can name the anonymous (!) function, e.g. (fn my-func ([x] (my-func x nil)) ([x y] ...))
. You only need let-fn
when you want local mutually recursive functions. And even then you could hack around it using atoms (which is essentially what Clojure does at the top level, when you use declare
). Example:
(let [odd? (atom nil)
even? (fn even? [n]
{:pre [(integer? n)]}
(cond
(pos? n) (@odd? (dec n))
(zero? n) true
:else (even? (- n))))
_ (reset! odd? (fn [n]
(cond
(zero? n) false
:else (even? (dec n)))))
odd? @odd?]
[(map (complement odd?) (range -3 (inc 3)))
(map even? (range -3 (inc 3)))])
And if you want to go crazy, you can use the Y combinator for mutually recursive functions, like so:
(let [[even? odd?] (Y* (fn [even? odd?]
(fn [n]
{:pre [(integer? n)]}
(cond
(pos? n) (odd? (dec n))
(zero? n) true
:else (even? (- n)))))
(fn [even? odd?]
(fn [n]
(cond
(zero? n) false
:else (even? (dec n))))))]
[(map (complement odd?) (range -3 (inc 3)))
(map even? (range -3 (inc 3)))])
And the Y* function uses no magic or atoms, even though it is incomprehensible. 🙂 (You can just google "y combinator mutual recursion" to find a version of it.)
Woah, @U8J6W2SC8 that's some intense code. thanks for posting it
@U0510902N I don't even remember when I last needed that. And yeah, trampolining is probably a good idea for any recursion that doesn't use recur
since there's no tail call optimization. It's been a long time since I needed trampoline as well. 🙂