jeudi 28 septembre 2017

How to use let bindings conditionally in Clojure

I'm new to Clojure and trying to concisely write a recursive function to merge two sorted sequences into a new sorted sequence.

This is my attempt, which doesn't compile:

(defn seq-merge [a-seq b-seq]
  (cond
    (empty? a-seq) b-seq
    (empty? b-seq) a-seq
    :else (let (if (< (first a-seq) (first b-seq))
                 [f (first a-seq) r (rest a-seq) h b-seq]
                 [f (first b-seq) r (rest b-seq) h a-seq])
            (cons f (seq-merge r h)))))

Initially, I wanted something like:

(if condition
  (let [...] 
  (let [...]
    (code-that-uses-conditional-bindings))

But it seemed that each 'let' needed to be directly followed by the code so this didn't work.

The aim is to not have to repeat the (cons f (seq-merge r h)) line twice if it can be avoided.

My current solution is this:

(defn seq-merge [a-seq b-seq]
  (cond
    (empty? a-seq) b-seq
    (empty? b-seq) a-seq
    :else (let [a-low? (< (first a-seq) (first b-seq))
                f (if a-low? (first a-seq) (first b-seq))
                r (if a-low? (rest a-seq) (rest b-seq))
                h (if a-low? b-seq a-seq)]
            (cons f (seq-merge r h)))))

But this seems much clunkier by having an 'if' for every binding value.

Aucun commentaire:

Enregistrer un commentaire