Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

defn vs. let with regards to decomposition

Tags:

clojure

I define a function, which takes two parameters - map and a key. The key is referenced from the map parameter decomposition

(defn myfunc [{v k} k]
   v)

when I call:

  (myfunc {:a 10} :a)

It surprisingly produces expected result: 10

Similar thing in the let:

(let [{v k} {:a 10} k :a] v)

fails, because k is not defined at the moment, when first part is evaluated.

My question is: why decomposition inside function parameters behaves differently compared to decomposition in let expressions?

like image 761
aav Avatar asked Oct 24 '22 21:10

aav


1 Answers

Macroexpanding the defn form I get the equivalent of this (removed .withMeta stuff and reformatted):

(def myfunc
  (fn* myfunc
       ([p__11393 k]
          (let* [map__11394 p__11393
                 map__11394 (if (seq? map__11394)
                              (apply hash-map map__11394)
                              map__11394)
                 v          (get map__11394 k)]
                v))))

So here we can see that the {v k} map is in fact first assigned to a local variable p__11393. Then the if statement tests if that variable is in fact a sequence and turns it into a hash-map if so, otherwise leaves it as it is. Importantly, the value assigned to k is looked up in the map after all of this happens, thus this works without error (and also would if :a wasn't in the map, get returns nil in that case).

On the other hand macroexpanding the let form I get

(let*
    [map__11431
  {:a 10}
  map__11431
  (if (seq? map__11431) (apply hash-map map__11431) map__11431)
  v
  (get map__11431 k)
  k
  :a]
  v)

and here we can see that v gets the result of (get map__11431 k), but k isn't defined at this point yet, hence the error.

like image 108
Paul Avatar answered Oct 30 '22 16:10

Paul