user1028880
user1028880

Reputation:

Clojure vector -> vector function using # and % syntax sugar?

Is it possible to code using #, %1, %2 for the below?

(defn fib-step [[a b]]
  [b (+ a b)])

(defn fib-seq []
  (map first (iterate fib-step [0 1])))

user> (take 20 (fib-seq))
(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)

In short, I'd like to know how to write vector -> vector function using # and % syntax sugar.

Thanks

Upvotes: 1

Views: 189

Answers (4)

user1028880
user1028880

Reputation:

Here is the code:

(def step #(-> [(% 1) (+ (% 0) (% 1))]))
(def fib #(map first (iterate step [0 1])))

(println 
 (take 20 (fib))
)

or

(def step #(-> [(% 1) (+ (% 0) (% 1))]))
(def fib (->> [0 1]
              (iterate step)
              (map first)))

(println
  (->> fib 
       (take 20))
))

Upvotes: 0

Joost Diepenmaat
Joost Diepenmaat

Reputation: 17773

I think using the vector function is clearer than the (-> [...]) "trick":

#(vector (% 1) (apply + %))

Though in this instance, with destructuring, I'd just use a named function or (fn [...] ...) anyway.

Upvotes: 0

Ankur
Ankur

Reputation: 33637

I would suggest making fib-step take 2 parameters rather than a vector as that would make things more clear that this function need two values whereas a vector as param means it can take any number of values as param (in the form of the vector).

(def fib-step #(-> [%2 (+ %1 %2)]))

(defn fib-seq []
  (map first (iterate (partial apply fib-step) [0 1])))

Upvotes: 0

DaoWen
DaoWen

Reputation: 33019

You can easily produce a vector using the #() reader form with the -> threading macro. For example, the following two functions are equivalent:

(fn [a b] [b a])
#(-> [%2 %])

However, if you need to do destructuring, as in your case, you're best off just sticking with one of the fn forms with an explicit parameter list. The best you'd get with #() is something like this:

#(-> [(% 1) (+ (% 0) (% 1))])

or

#(-> [(% 1) (apply + %)])

Using the higher-order juxt function is another nice way to create vectors, but unfortunately in this case it doesn't buy you much either:

(def fib-step (juxt second #(apply + %)))

I think out of all the options, using fn is still the best fit because of its easy support for destructuring:

(fn [[a b]] [b (+ a b)])

Upvotes: 3

Related Questions