What is the purpose of ~' or '~ in Clojure?

后端 未结 2 1510
情深已故
情深已故 2021-02-01 17:35

I am learning about Clojure macros, and the code examples will sometimes have the constructs \'~symbol or alternately ~\'symbol. I know that (quo

2条回答
  •  说谎
    说谎 (楼主)
    2021-02-01 18:28

    ~ is a reader macro for the unquote function. within a quoted list it causes a symbol to be evaluated rather then used as a literal symbol

    user> (def unquoted 4)
    user>`(this is an ~unquoted list)
    (user/this user/is user/an 4 clojure.core/list)
    user> 
    

    everything except the symbol unquoted was used just as a symbol where unquoted was resolved to its value of 4. this is most often used in writing macros. The repl also prints the namespace (user) infront of the names when it is printing the resulting list.

    many macros, are basically just templates designed to do a bunch of slight variations on something that can't be done in a function. In this contrived example a template macro defines a function by producing a call to def. syntax-quote with unquoting makes this much easier to read:

    user> (defmacro def-map-reducer [name mapper reducer] 
             `(defn ~name [& args#] 
                  (reduce ~reducer (map ~mapper args#))))
    
    #'user/def-map-reducer
    user> (def-map-reducer add-incs inc +)
    #'user/add-incs
    user> (add-incs 1 2 3 4 5)
    20
    

    compared to:

    user> (defmacro def-map-reducer [name mapper reducer] 
              (let [args-name (gensym)] 
                  (list `defn name [`& args-name] 
                       (list `reduce reducer (list `map mapper args-name)))))
    
    #'user/def-map-reducer
    user> (def-map-reducer add-decs dec +)
    #'user/add-decs
    user> (add-decs 1 2 3 4 5)
    10
    user> 
    

    in the second example I also don't use the auto-gensyms feature because I'm not in a syntax-quote

提交回复
热议问题