recursive bindings not available in let form?
Hi clojure-world, I think maybe this is actually related to the complexities of binding referenced in the previous thread (https://groups.google.com/forum/?utm_source=digest&utm_medium=email#!topic/clojure/zBXsrqTN2xs)... maybe? But it would be amazing if some wise person would help explain... So for obscure reasons, I found myself trying to use a naive recursive fibonacci function interactively. So naturally, the first thing my fingers went to was: (let [fib (fn [x] (cond (< x 2) x :else (+ (fib (- x 2)) (fib (- x 1)] (fib 5)) which threw an unable to resolve symbol error because it couldn't resolve the recursive calls to fib inside the let binding. But swap out the let for a def and it works just fine: (def fib (fn [x] (cond (< x 2) x :else (+ (fib (- x 2)) (fib (- x 1)) (fib 5) Can someone clarify for me what's going on here? Why can a def binding get access to its own name in the body of a function, but not a let binding? thanks! -Paul -- 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.
Re: recursive bindings not available in let form?
Note that letfn does allow recursive bindings, though I couldn't comment as to the implementation details. On Friday, December 2, 2016 at 3:01:13 PM UTC-5, Paul Gowder wrote: > > Hi clojure-world, > > I think maybe this is actually related to the complexities of binding > referenced in the previous thread ( > https://groups.google.com/forum/?utm_source=digest&utm_medium=email#!topic/clojure/zBXsrqTN2xs)... > > maybe? But it would be amazing if some wise person would help explain... > > So for obscure reasons, I found myself trying to use a naive recursive > fibonacci function interactively. So naturally, the first thing my fingers > went to was: > > (let [fib (fn [x] > (cond > (< x 2) x > :else (+ (fib (- x 2)) (fib (- x 1)] > (fib 5)) > > which threw an unable to resolve symbol error because it couldn't resolve > the recursive calls to fib inside the let binding. > > But swap out the let for a def and it works just fine: > > (def fib (fn [x] > (cond > (< x 2) x > :else (+ (fib (- x 2)) (fib (- x 1)) > (fib 5) > > Can someone clarify for me what's going on here? Why can a def binding > get access to its own name in the body of a function, but not a let binding? > > thanks! > > -Paul > -- 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.
recursive bindings not available in let form?
Let bindings are immutable bindings, not refs. They must act as if their value could be substituted at the moment they are referenced. Def (i.e. a ref) is a mutable container whose contents is examined when it is used (not when referenced), which is why your second example works. Why doesn't let work how you expect? Well, how would the following code work if let worked as you intend? (let [a 1 a (+ a 2)] (= a 3)) However, fn accepts an optional name binding, so you can do this: (let [fib (fn fib [...] (fib ...))] fib) The inner fib reference is bound by the fn form, but the outer fib reference is still bound by let. Or you can use letfn instead of let, which is the same as above with less typing AND the bindings can all see one another simultaneously. It's best for groups of closed-over but mutually recursive functions. (letfn [(fib [...] (fib ...))] (fib ...)) -- 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.
Re: recursive bindings not available in let form?
AFAIK there are two options. You can add a symbol after fn: (let [fib (fn y [x] (cond (< x 2) x :else (+ (y (- x 2)) (y (- x 1)] (fib 5)) Or, as Bobby already suggested, you can use letfn: (letfn [(fib [x] (cond (< x 2) x :else (+ (fib (- x 2)) (fib (- x 1)] (fib 5)) -- 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.
Re: recursive bindings not available in let form?
Thanks Bobby, Francis, Walter! Now trying to wrap my head around the idea of def as a ref... On Friday, December 2, 2016 at 2:57:13 PM UTC-6, Francis Avila wrote: > > Let bindings are immutable bindings, not refs. They must act as if their > value could be substituted at the moment they are referenced. Def (i.e. a > ref) is a mutable container whose contents is examined when it is used (not > when referenced), which is why your second example works. > > > Why doesn't let work how you expect? Well, how would the following code > work if let worked as you intend? > > (let [a 1 > a (+ a 2)] > (= a 3)) > > However, fn accepts an optional name binding, so you can do this: > > (let [fib (fn fib [...] (fib ...))] fib) > > The inner fib reference is bound by the fn form, but the outer fib > reference is still bound by let. > > Or you can use letfn instead of let, which is the same as above with less > typing AND the bindings can all see one another simultaneously. It's best > for groups of closed-over but mutually recursive functions. > > (letfn [(fib [...] (fib ...))] (fib ...)) > > -- 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.
Re: recursive bindings not available in let form?
Your "y" could also be "fib". You are permitted to use the same name inside the fn. On Fri, Dec 2, 2016 at 12:59 PM, Walter van der Laan < waltervanderl...@gmail.com> wrote: > AFAIK there are two options. > > You can add a symbol after fn: > > (let [fib (fn y [x] > (cond > (< x 2) x > :else (+ (y (- x 2)) (y (- x 1)] > (fib 5)) > > > -- 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.