Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use let vs. if-let in Clojure

Tags:

clojure

When does using if-let rather than let make code look better and does it have any performance impact?

like image 306
Arthur Ulfeldt Avatar asked Jan 06 '10 00:01

Arthur Ulfeldt


People also ask

When let vs if let?

They're used like let to bind values to variables, but if a value is nil then when-let will return nil without running the body, and if-let will execute its alternative branch.

What is let in Clojure?

Clojure let is used to define new variables in a local scope. These local variables give names to values. In Clojure, they cannot be re-assigned, so we call them immutable.

What is SEQ in Clojure?

Clojure defines many algorithms in terms of sequences (seqs). A seq is a logical list, and unlike most Lisps where the list is represented by a concrete, 2-slot structure, Clojure uses the ISeq interface to allow many data structures to provide access to their elements as sequences.


2 Answers

I guess if-let should be used when you'd like to reference an if condition's value in the "then" part of the code:

i.e. instead of

(let [result :foo]   (if result     (do-something-with result)     (do-something-else))) 

you write:

(if-let [result :foo]   (do-something-with result)   (do-something-else)) 

which is a little neater, and saves you indenting a further level. As far as efficiency goes, you can see that the macro expansion doesn't add much overhead:

(clojure.core/let [temp__4804__auto__ :foo]   (if temp__4804__auto__     (clojure.core/let [result temp__4804__auto__]       (do-something-with result))     (do-something-else))) 

This also illustrates that the binding can't be referred to in the "else" part of the code.

like image 103
harto Avatar answered Sep 18 '22 06:09

harto


A good use case for if-let is to remove the need to use anaphora. For example, the Arc programming language provides a macro called aif that allows you to bind a special variable named it within the body of an if form when a given expression evaluates to logical true. We can create the same thing in Clojure:

(defmacro aif [expr & body]   `(let [~'it ~expr] (if ~'it (do ~@body))))  (aif 42 (println it)) ; 42 

This is fine and good, except that anaphora do not nest, but if-let does:

(aif 42 (aif 38 [it it])) ;=> [38 38]  (aif 42 [it (aif 38 it)]) ;=> [42 38]  (if-let [x 42] (if-let [y 38] [x y])) ;=> [42 38] 
like image 29
fogus Avatar answered Sep 21 '22 06:09

fogus