简体   繁体   中英

Is there a short form for creating hash-map in Clojure?

Is there a short form/macro that allows me to do

(defn f [a b c]
  {a b c})

instead of

(defn f [a b c]
  {:a a :b b :c c})

This shows the steps. Remove the println's for actual use:

(ns clj.core
  (:gen-class))

(defmacro hasher [& args] 
  (let [keywords      (map keyword args)
        values        args
        keyvals-list  (interleave keywords values)
  ]
    (println "keywords     "  keywords)
    (println "values       "  values)
    (println "keyvals-list "  keyvals-list)
    `(hash-map ~@keyvals-list)
  )
)

(def a 1)
(def b 2)
(println \newline "result: " (hasher a b))

> lein run
keywords      (:a :b)
values        (a b)
keyvals-list  (:a a :b b)

result:  {:b 2, :a 1}
(defmacro as-map [& syms]
  (zipmap (map keyword syms) syms))

Usage:

(def a 42)
(def b :foo)

(as-map a b)
;;-> {:a 42 :b :foo}

Note that to support namespaced keywords, you'd have to drop support for ns aliases if you want to keep it as short:

(defmacro as-map [& syms]
  (zipmap (map keyword syms) (map (comp symbol name) syms)))

Usage:

(def a 42)
(def b :foo)

(as-map example/a foo-of/b)
;;-> {:example/a 42 :foo-of/b :foo}

Advice: Likely not a good idea, saves you a few keyboard hits at the cost of readability and expressivity and flexibility in naming local bindings.

This is an old snippet of mine I've had kicking around for a while.

(declare ^:private restructure*)

(defn ^:private restructure-1 [m [e k]]
  (cond
    (= :strs e) (reduce #(assoc %1 (name %2) %2) m k)
    (= :keys e) (reduce #(assoc %1 (keyword (namespace %2) (name %2)) %2) m k) 
    :else       (assoc m k (restructure* e))))

(defn ^:private restructure* [form]
  (if-not (map? form)
    form
    (as-> {} v
      (reduce restructure-1 v form)
      `(hash-map ~@(mapcat identity v)))))

(defmacro restructure [form]
  (restructure* form))

The idea is that it provides the complement of clojure.core/destructure which goes from a destructuring form to bindings, this captures bindings and constructs a datastructure.

(let [x 1 y 2 z 3]
  (restructure {:keys [x y z]}))
;; => {:x 1 :y 2 :z 3}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM