Why no destructing in def form?

后端 未结 4 2120
北恋
北恋 2021-02-18 20:10

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

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

where svd

相关标签:
4条回答
  • 2021-02-18 20:50

    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.

    0 讨论(0)
  • 2021-02-18 21:04

    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.

    0 讨论(0)
  • 2021-02-18 21:07

    def is basically the constructor for Vars. The first argument is the symbol that names the Var. It takes that symbol and returns a Var for that symbol. Destructuring would change these semantics.

    You could write a macro that does it, though.

    0 讨论(0)
  • 2021-02-18 21:10

    What follows are some philosophical justifications.

    Clojure favors immutability over mutability, and all sources of mutability should be carefully considered and named. def creates mutable vars. Idiomatic Clojure therefore both doesn't use them much anyway, and also would not want it to be too easy to create many mutable vars without care (e.g. by destructuring). let and function argument destructuring, however, creates immutable bindings, so Clojure makes those bindings easy to create.

    Vars created by def have global scope. Therefore you should name defed vars carefully and keep them few in number. Destructuring def would make it too easy to create many defs without care. let and function argument destructuring, on the other hand, creates local, lexically-scoped bindings, so the convenience of destructuring does not cause name pollution.

    0 讨论(0)
提交回复
热议问题