سؤال

Consider this form:

(def v [42 "foo" 99.2 [5 12]])

I've read that if I have to declare some unused variables in a let form I should denote them with _ like in this destructuring form:

(let [[x _ _ [y z]] v]
  (+ x y z))

My question is how does the assignment to _ happens? Since this do not throw an exception I assume that the 2nd _ overrides the first one but I'm not sure. So how do this work?

هل كانت مفيدة؟

المحلول

This use of _ is purely conventional: from Clojure's point of view, it's just a regular symbol which can be used to name a local. So, you can simply check the value of _ directly to confirm your understanding:

(let [[x _ _ [y z]] v]
  _)
;= 99.2

As for what goes on under the hood, the simplest way to check that is to macroexpand the let form:

(macroexpand-1 '(let [[x _ _ [y z]] v] _))

The result of the above, reformatted for clarity, looks like this:

(let* [vec__7 v
       x (clojure.core/nth vec__7 0 nil)
       _ (clojure.core/nth vec__7 1 nil)
       _ (clojure.core/nth vec__7 2 nil)
       vec__8 (clojure.core/nth vec__7 3 nil)
       y (clojure.core/nth vec__8 0 nil)
       z (clojure.core/nth vec__8 1 nil)]
  _)

So the second _ simply shadows the first one.

let* is the implementation detail behind let; it is a special form directly understood by the compiler, to which the let macro adds destructuring support.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top