On Saturday, November 15, 2014 11:31:50 AM UTC-5, Udayakumar Rayala wrote: > > <Cross posting from Clojurescript group. Sorry if you got this question > twice> > > Hi, > > Is it idiomatic to have defn inside defn? eastwood throws def-in-def > warning when I have the following code: > > (defn double-square [y] > (defn square [x] (* x x)) > (+ (square y) (square y))) > > The above code is a simplified example to show the problem. In the above > case, square is a function which is local and I dont want it to be shared > outside the context of double-square. > > I can change it to use letfn like below: > > (defn double-square [y] > (letfn [(square [x] (* x x))] > (+ (square y) (square y)))) > > But when you have multiple local functions, it doesnt seem nice to read. >
Actually, the main use case of letfn *is* when you have multiple local functions, and they need to refer to one another, and this referring has directed cycles. For a case like the above I'd just use let: (defn double-square [y] (let [square (fn [x] (* x x))] (+ (square y) (square y)))) Although, for that exact case I'd probably go with (let [s (* y y)] (+ s s)) or with (* 2 y y). :) (The former might be more efficient if y is likely to be a bignum, as addition of bignums is O(n) while multiplication is probably O(n^2) and at best O(n^1.5)ish.) Let has these advantages over letfn: * Easier to remember syntax, because you use it all the time anyway. * Can use the even more compact local function notation: (let [square #(* % %)] ...) * Can mix local named functions with non-function local bindings such as intermediate computations Letfn has this advantage over let: * Functions in letfn can refer to one another, including forward references within the same letfn binding vector. Thus allowing circular references, e.g. mutually recursive local functions and/or trampolining ones. The def forms always produce a namespace-scoped Var rather than a local binding, even if nested in something else. Sometimes you may want to nest defs in a let, so they may share a bit of private state or data. Defs in a def can always be replaced with something better, save for macros that *emit* defs (so, (defmacro foo [args] ... `(defn ~@something ...))) and blackbelt-level metaprogramming involving using eval to create whole namespaces on the fly. And then the "nested" defs should be quoted and used there as *data* rather than actually being executed in place. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.