Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure: let scope and function return value

I am having some troubles figuring how to use the "let" form. In the example below, I would like to locally bind the value "cols" in order to work on it later in the function. What I am noticing, however, is that if I use "let" the function sel-opt-tmp will return a nil value instead than a list.

(defn sel-opt-tmp []
  (let [cols "test"]))

(prn (sel-opt-tmp))

*The above code returns a nil value.

I understand that "let" only binds a value in the scope of a function, what I do not know is if there is a way to pass the value out of the let scope. Maybe there is something like "return" that I am not aware of? Or this is simply bad design and I should not use the binding at all in this case (this tends to create long chains of functions that are difficult to read although)?

like image 473
kfk Avatar asked Nov 18 '11 16:11

kfk


People also ask

How do you return a value in Clojure?

There isn't a return statement in Clojure. Even if you choose not to execute some code using a flow construct such as if or when , the function will always return something, in these cases nil .

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.

Does Clojure have closures?

This is a perfect opportunity to enforce encapsulation to avoid drowning the client in board-implementation details. Clojure has closures, and closures are an excellent way to group functions (Crockford 2008) with their supporting data.


2 Answers

It returns nil because the contents of the let statement is empty (or nil). Try:

(let [cols "test"] cols)

Which will return the value of cols. As seh says, a let statement evaluates to the value of its last sub-expression.

like image 163
Adrian Mouat Avatar answered Oct 01 '22 02:10

Adrian Mouat


There is no such problem with passing values outside the scope as you mention. The binding cols is in force only within the scope, but the lifetime of the value of (:ks cols) is not similarly restricted. (That's why you have garbage collection: you can return values that point to data, and the data stays live as long as there are references to it.)

If you get nil from the function, that likely means that cols does not have a :ks key... or indeed might not be a map. Since cols is the result from filter, it is a sequence, and when the :ks keyword is used as a function, it returns nil for non-collections. To guard against that kind of bugs it may be a useful convention to always write (cols :ks) instead of (:ks cols) so that you get an error when what you think is a map is something else.

like image 45
Jouni K. Seppänen Avatar answered Oct 01 '22 00:10

Jouni K. Seppänen