Welcome! Please see the About page for a little more info on how this works.

0 votes
in Macros by

This is more of a suggestion, not really sure where to post it though. Please refer me to the relevant forum if there exists a better one.

Basically I'm going under the assumption that no one uses let without a body. The only reason I can imagine for doing that is purely for side-effects, and do etc. are a much better fit, and currently (let [x 1 y 2 z (+ x y)]) => nil (rather than throwing a spec error, as if this is useful expected behavior? But why?)

In any case, if my assumption is correct, then I propose let returns the last assigned value, such that (let [x 1 y 2 z (+ x y)]) => 3, that is z. This is ergonomic, and intuitive in my eyes. It's also especially useful for long binding forms building off of the same variables only for the final one to be important, which then requires a whole row with special funky indentation just for that.

1 Answer

+4 votes

This behavior is expected, as with any other form that evaluates a body. The return value is the final expression in the body. If you want to return one of your bindings, you must do so explicitly. This is even shown in the example in the official Clojure documentation about the let special form, at https://clojure.org/reference/special_forms#let

If you are using a good linter like clj-kondo, it will warn you if you have any bindings that you have not done anything with.

Changing this would be quite jarring for people who are used to LISPs, and make let inconsistent with other forms in Clojure as well.

Probably also worth mentioning that the body of a let is wrapped in an implicit do, so (let [x 1 y 2]) is really equivalent to (let [x 1 y 2] (do)) and (do) is going to return nil