1

Iam another Clojure-newbi!

How can i assign a vector containing some values to another one? I want to do:

[a b] >>> [b (+ a b)] so that afterwards b has the value of (a+b) and a that of b.

1 Answer 1

2

It looks like you're trying to do a fibonacci sequence.

user=> (def fibseq (map first (iterate (fn [[a b]] [b (+ a b)]) [1 1])))
#'user/fibseq
user=> (take 10 fibseq)
(1 1 2 3 5 8 13 21 34 55)

What you've got to remember in clojure is immutability, so you don't change a and b to be the new values. So something like:

user=> (defn next-fib [[a b]]
         (let [na b
               nb (+ a b)]
           [na nb]))
user=> (next-fib [1 2])
[2 3]

would produce a function next-fib that would return the next 2 values from your input. During the function, a and b cannot be changed, they are immutable, hence assignment to new values.

Here, i'm using destructuring to immediately break the elements of the input vector into values a and b, which are then used to calculate the next element, and is the same as how the 1 liner at the top of my answer works.

Or if you're doing looping, you can recur with values that get substitute over their previous iteration, this is not changing a and b (during any iteration their values are fixed and still immutable), but redoing the entire stack with new values in their place, subtle difference. See articles on tail recursion.

user=> (loop [a 1 b 1]
         (if (< a 20)
           (recur b (+ a b))
           [a b]))
[21 34]

Here's a simple version of the Fibonacci Sequence using recur, it returns the first n numbers.

(defn fib-recur [n]
  (loop [fib [] x n a 0 b 1]
    (if (zero? x)
      fib
      (recur (conj fib b) (dec x) b (+ a b)))))

It works by starting with an empty array of numbers it's building, then recurs by decrementing the counter (x) from n to 0, each iteration changes a and b to be new values as part of the recursion, and it adds the latest number to the array fib returning that when the counter gets to zero.

Sign up to request clarification or add additional context in comments.

5 Comments

i was actually trying to do the fibunacci with a loop/recur and was wondering if there would be some way to do this. By the way now i dont understand something with recur. i have tested the following:(loop [a 0 b 0] (println a b) (if (< b 3) (recur (inc b) a) (println "end..."a b))) and the result is: 0 0 1 0 1 1 2 1 2 2 3 2 3 3 end... 3 3 i havent incremented a but recur seems to apply inc to both a b. how this happens??
i've added a recur version of fibonacci with a bit of explanation to my answer
each time the iteration restarts, feed the values from the (recur ...) into a and b, so you are starting with 0,0. Next iteration you go back to top with calling (recur 1 0). So the new value of a is 1, and b is 0. Next recur you get 1,1 as a,b. And so on
interesting! Does this mean that clojure does not recognize a and b if you change the order of them in recur, and assign the new values to them exactly in the same order as they appeared at loop [a b]?
Whatever you put in the recur call get put into a and b. The first time loop occurs, you are initialising the values, the recur sends it back to the loop with new values in it. In my final example, see how the vars fib, x, a and b are initialised with [], n, 0, 1, and when recur happens the new values for those same variables are (conj fib b), (dec x), b, (+ a b). Thus in effect a = b, b = (a+b), and we decrement the loop counter, and store the current fibonacci value in the array

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.