Search code examples
data-bindingfunctional-programmingclojurepattern-matchingdestructuring

Is the `:as` binding useful only when the argument to a function is a temporary?


The first usage of :as shown in Clojure Programming is the following

(let [[x _ z :as original-vector] v]
  (conj original-vector (+ x z)))
;= [42 foo 99.2 [5 12] 141.2]

However, by experimenting a bit on https://rextester.com/l/clojure_online_compiler, I see that v is visible in the body of let, so I can just skip the :as destructuring and use v instead of original-vector, and the result is the same

(let [[x _ z] v]
  (conj v (+ x z)))
;= [42 foo 99.2 [5 12] 141.2]

This is clearly not doable if I have a more complex expression instead of v (in C++ I'd say a temporary/rvalue, whereas v would be an lvalue).

So my question is: is the :as syntax useful only when we destructure a temporary, whereas it is totally redundant when we destructure a named entity? I mean in the example above it seems the only difference in using :as is that we refer to v via another name, but I don't see how this can be advantageous in any way...


The example assumes

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

Solution

  • You are correct that the :as destructuring technique can be redundant. However, :as in a destructuring form is almost always used with a function's argument vector, rather than with a let form:

    (ns tst.demo.core
      (:use tupelo.core tupelo.test))
    
    (defn myfun
      [[x _ z :as original-vector]]
      (conj original-vector (+ x z)))
    
    (dotest
      (is= [1 2 3 4]
        (myfun [1 2 3])))
    
    

    However, it is well worth noting that the full power of destructuring is available for both function arguments and let forms.


    The example is built using my favorite template project.