What's a more idiomatic and concise way of writing Pascal's Triangle with Clojure?

clojure, idioms, pascals-triangle

Solution

(defn pascal []
  (iterate (fn [row]
             (map +' `(0 ~@row) `(~@row 0)))
           [1]))

Or if you're going for maximum concision:

(defn pascal []
  (->> [1] (iterate #(map +' `(0 ~@%) `(~@% 0)))))

To expand on this: the higher-order-function perspective is to look at your original definition and realize something like: "I'm actually just computing a function `f` on an initial value, and then calling `f` again, and then `f` again...". That's a common pattern, and so there's a function defined to cover the boring details for you, letting you just specify `f` and the initial value. And because it returns a lazy sequence, you don't have to specify `n` now: you can defer that, and work with the full infinite sequence, with whatever terminating condition you want.

For example, perhaps I don't want the first `n` rows, I just want to find the first row whose sum is a perfect square. Then I can just `(first (filter (comp perfect-square? sum) (pascal)))`, without having to worry about how large an `n` I'll need to choose up front (assuming the obvious definitions of `perfect-square?` and `sum`).

Thanks to fogus for an improvement: I need to use `+'` rather than just `+` so that this doesn't overflow when it gets past `Long/MAX_VALUE`.

Problem

I implemented a naive solution for printing a Pascal's Triangle of N depth which I'll include below. My question is, in what ways could this be improved to make it more idiomatic? I feel like there are a number of things that seem overly verbose or awkward, for example, this `if` block feels unnatural: `(if (zero? (+ a b)) 1 (+ a b))`. Any feedback is appreciated, thank you! ``` (defn add-row [cnt acc] (let [prev (last acc)] (loop [n 0 row []] (if (= n cnt) row (let [a (nth prev (- n 1) 0) b (nth prev n 0)] (recur (inc n) (conj row (if (zero? (+ a b)) 1 (+ a b))))))))) (defn pascals-triangle [n] (loop [cnt 1 acc []] (if (> cnt n) acc (recur (inc cnt) (conj acc (add-row cnt acc)))))) ```

Original source