Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

let inside cond

Tags:

clojure

lisp

I'm working with clojure and while I've dabbled with lisps before, I'm having trouble finding a clean way to nest let statements in cond statements. For example, consider the following function:

(defn operate-on-list [xs]
  (let [[unpack vector] (first xs)]
    (cond
      [(empty? xs) 'empty
       unpack vector
       :else (operate-on-list (rest xs))])))

It's a pretty standard recursive operation on a list, but it needs to do some work on the first element in the list before it works with the contents. The issue, of course, is that the list may be empty.

In this example, it wouldn't be hard to change unpack to ((first xs) 0) and vector to ((first xs) 1), but this quickly gets ugly if more work needs to be done on (first xs).

Is there any way to effectively use a let statement part-way through a cond?

Thanks.

-Nate

like image 783
So8res Avatar asked Jan 14 '10 21:01

So8res


1 Answers

In cases like these, you're best off using if-let:

(defn operate-on-list [xs]
  (if-let [[unpack v] (first xs)]
    (cond
      unpack v
      :else  (operate-on-list (rest xs)))))

This code walks the given list seq-able (list, vector, array...) of vectors and returns the second element of the first vector whose first element is true (meaning not false or nil). nil is returned if no such vector is found.

Note that vector is a built-in function, so I've chosen v as the variable name, just in case the need to use the function in the body arises in the future. More importantly, you're using too many brackets in your cond syntax; fixed in this version.

UPDATE: Two additional things worth noting about if-let:

  1. The way if-let works, if (first xs) happens to be nil (false would be the same), the destructuring binding never takes place, so Clojure won't complain about not being able to bind nil to [unpack v].

  2. Also, if-let accepts an else clause (in which you can't refer to the variables bound in if-let bindings vector -- though if you're in the else clause, you know they where false or nil anyway).

like image 90
Michał Marczyk Avatar answered Oct 05 '22 23:10

Michał Marczyk