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

+1 vote
ago in Macros by

We can use :let in for to define local variable like this

(for [i (range 5)
      :let [inc-i (inc i)]]
  [i inc-i])
;;=> ([0 1] [1 2] [2 3] [3 4] [4 5])

Otherwise, if we specified :let as first element, it causes an macro expansion error.

(for [:let [range-end 5]
      i (range range-end)
      :let [inc-i (inc i)]]
  [i inc-i])
;;=> Syntax error macroexpanding for at (*cider-scratch*:555:1).
;;   Can't pop empty vector

Of course, in this case, we should have wrapped for in let. However, I'm curious whether making :let available only for second and subsequent elements is intended behavior as part of the public interface.

1 Answer

+1 vote
ago by
selected ago by
 
Best answer

Seems like it is working as intended per the docstring.

ago by
Agreed:

"Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers..."

:let is a modifier -- it has to be preceded by a binding-form/collection-expr pair.
ago by
Thanks both! I finally understand.
ago by
For beginners, couldn't a more informative error message be displayed?
ago by
Possibly, but the extra check on the vector would be a performance penalty that everyone would pay for every use of `for` in every program -- and Clojure rarely does that to its users.
...