Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why no destructing in def form?

Tags:

In a let form (Clojure here) I can doing something like

(let [[u s v] (svd A)] 
   (do-something-with u v))

where svd returns a list of length three. This is a very natural sort of thing to do, so why isn't that we don't we have

(def [u s v] (svd A))

and its various generalizations as the default behavior of the def form? I don't see how this would interfere with anything that def is already doing. Can someone who understands the Zen of Lisp or Clojure explain why def does not support binding (with destructuring) as powerful as let?

like image 598
Gabriel Mitchell Avatar asked Nov 19 '11 21:11

Gabriel Mitchell


2 Answers

def is a special form at the compiler level: it makes a Var. def has to be available and usable before destructuring is available. You see something similar with let*, a compiler primitive that supports no destructuring: then after several thousand lines in clojure/core.clj the language is finally powerful enough to provide a version of let with destructuring, as a macro on top of let*.

If you want, you can write a macro (say, def+) that does this for you. Personally I think it's kinda gross and wouldn't use it, but using a Lisp means getting to use a language that suits you personally.

like image 61
amalloy Avatar answered Sep 19 '22 18:09

amalloy


This is not perfect but it is start on writing a def+ https://clojuredocs.org/clojure.core/destructure

(defmacro def+
  "binding => binding-form
  internalizes binding-forms as if by def."
  {:added "1.9", :special-form true, :forms '[(def+ [bindings*])]}
  [& bindings]
  (let [bings (partition 2 (destructure bindings))]
    (sequence cat 
      ['(do) 
       (map (fn [[var value]] `(def ~var ~value)) bings)
       [(mapv (fn [[var _]] (str var)) bings)]])))

With that you can do...

(def+ [u s v] [1 5 9], foo "bar")

...while not compromising the simplicity of def...

(def+ foo "bar")

...which is what was requested and suggested. This does still have the issue of introducing gensym variables into the global namespace. The gensym problem could be handled but given the use case (use in repl) the additional variables are probably acceptable.

like image 44
phreed Avatar answered Sep 20 '22 18:09

phreed