2012-01-25 3 views
7

В Clojure, я могу destructure карту, как это:реструктуризации Карта

(let [{:keys [key1 key2]} {:key1 1 :key2 2}] 
    ...) 

, который аналогичен методу CoffeeScript в:

{key1, key2} = {key1: 1, key2: 2} 

CoffeeScript может также сделать это:

a = 1 
b = 2 
obj = {a, b} // just like writing {a: a, b: b} 

Есть ли такой ярлык в Clojure?

ответ

10

Это не предусмотрено, но может быть реализован с помощью довольно простого макроса:

 
(defmacro rmap [& ks]    
`(let [keys# (quote ~ks) 
     keys# (map keyword keys#) 
     vals# (list [email protected])] 
    (zipmap keys# vals#))) 
 
user=> (def x 1) 
#'user/x 
user=> (def y 2) 
#'user/y 
user=> (def z 3) 
#'user/z 
user=> (rmap x y z) 
{:z 3, :y 2, :x 1} 
1

Короткий ответ: нет.

Основная причина в том, что в Clojure не только ключевые слова, но и любое значение могут использоваться в качестве ключа на карте. Кроме того, запятые являются пробелами в Clojure. Таким образом, {a, b} - это то же самое, что и {a b}, и результатом будет карта с одной парой ключ-значение, где ключ - это то, что a оценивает.

Вы могли бы написать макрос, который принимает список символов и строит карту с именами символов (преобразованных в ключевые слова) в качестве ключей и оценками символов в качестве значений.

2

Я написал простой макрос для этого в useful, который позволяет вам написать это как (keyed [a b]). Или вы можете параллельно: strs и: syms поведение деструктуризации карты с (keyed :strs [a b]), которая расширяется до {"a" a, "b" b}.

+0

Полезно действительно полезно! Есть документация в любом месте? – benekastah

+0

@benekastah Не совсем. Вы можете прочитать исходный код и посмотреть на тесты - большинство функций тестируются таким образом, чтобы было понятно, как они должны использоваться. – amalloy

0

Я не думаю, что обеспечивается из коробки в Clojure .. но эй это сюсюкать и мы можем использовать макросы, чтобы иметь что-то вроде этого:

(defmacro my-map [& s] 
    (let [e (flatten (map (fn [i] [(keyword (str i)) i]) s))] 
    `(apply hash-map [[email protected]])) 
) 

Использование:

(def a 10) 
(def b 11) 

(def result (my-map a b)) 

результат будет вашей картой