patternMinor
Clojure Fibonacci
Viewed 0 times
clojurefibonaccistackoverflow
Problem
I'm a Clojure novice working through 4Clojure problems. In one problem I am supposed to create a function that takes a number and returns that number of Fibonaccis. My first thought was to create a function that creates a lazy sequence of Fibonaccis and then just takes however many it needs. Here is what I came up with:
This did work in my IDE but it wasn't accepted by 4Clojure due to the private defn. defs are not accepted by the website.
How can I refactor this function to remove the defn? And what are the problems with style and readability? Is it easy to reason about the function?
(fn [numberOfFibs]
(defn lazyFib [a b]
(cons a (lazy-seq (lazyFib b (+ b a)))))
(take numberOfFibs (lazyFib 1 1)))This did work in my IDE but it wasn't accepted by 4Clojure due to the private defn. defs are not accepted by the website.
How can I refactor this function to remove the defn? And what are the problems with style and readability? Is it easy to reason about the function?
Solution
How can I refactor this function to remove the defn?
What you are looking for is
And what are the problems with style and readability?
You shouldn't use nested
Especially confusing is that just evaluating the
Is it easy to reason about the function?
Other than the nested
What you are looking for is
letfn. It can be used to locally define a recursive function or corecursive functions. In this case:(fn [numberOfFibs]
(letfn [(lazyFib [a b] (cons a (lazy-seq (lazyFib b (+ b a)))))]
(take numberOfFibs (lazyFib 1 1))))And what are the problems with style and readability?
You shouldn't use nested
defs. Behavior is not misleading. Especially it is not scoped in the form it appears and affects the current namespace, as if it was a top level form.=> lazyFib
CompilerException java.lang.RuntimeException: Unable to resolve symbol: lazyFib in this context, compiling:(NO_SOURCE_PATH:1:42)
=> (fn [numberOfFibs]
(defn lazyFib [a b]
(cons a (lazy-seq (lazyFib b (+ b a)))))
(take numberOfFibs (lazyFib 1 1)))
#
=> lazyFib
#
=> ((fn [numberOfFibs]
(defn lazyFib [a b]
(cons a (lazy-seq (lazyFib b (+ b a)))))
(take numberOfFibs (lazyFib 1 1))) 10)
(1 1 2 3 5 8 13 21 34 55)
=> lazyFib
#Especially confusing is that just evaluating the
fn without calling it pollutes the namespace with an unbound name.Is it easy to reason about the function?
Other than the nested
defn it is very understandable.Code Snippets
(fn [numberOfFibs]
(letfn [(lazyFib [a b] (cons a (lazy-seq (lazyFib b (+ b a)))))]
(take numberOfFibs (lazyFib 1 1))))=> lazyFib
CompilerException java.lang.RuntimeException: Unable to resolve symbol: lazyFib in this context, compiling:(NO_SOURCE_PATH:1:42)
=> (fn [numberOfFibs]
(defn lazyFib [a b]
(cons a (lazy-seq (lazyFib b (+ b a)))))
(take numberOfFibs (lazyFib 1 1)))
#<resistors$eval4432$fn__4433 deneme.resistors$eval4432$fn__4433@49531c8c>
=> lazyFib
#<Unbound Unbound: #'deneme.resistors/lazyFib>
=> ((fn [numberOfFibs]
(defn lazyFib [a b]
(cons a (lazy-seq (lazyFib b (+ b a)))))
(take numberOfFibs (lazyFib 1 1))) 10)
(1 1 2 3 5 8 13 21 34 55)
=> lazyFib
#<resistors$eval4440$fn__4441$lazyFib__4442 deneme.resistors$eval4440$fn__4441$lazyFib__4442@6d17b6ce>Context
StackExchange Code Review Q#73827, answer score: 5
Revisions (0)
No revisions yet.