在clojure中解构地图 - 未使用的密钥

时间:2012-11-03 14:19:15

标签: clojure destructuring

我已经定义了一个采用地图的函数。我想用解构来访问这些值。但是,我还想检查是否有任何使用过的密钥。

所以,例如......

 (defun func1 [{:keys [a b c] :rest rest}]
    (println a b c)
    (println rest))

 (func1 {:a 1 :b 2 :c 3 :d 4})

会打印

 1 2 3
 4

我想要这个的原因是如果rest不为null,这可能是一个错误,我想发出信号。我知道:as,我可以使用。但后来我需要存储两次有效密钥列表。

我错过了什么吗?

菲尔

4 个答案:

答案 0 :(得分:6)

我真的不明白你为什么想知道你有什么事情不关心。如果您正在尝试执行类似“使用这些键执行某些操作,并对其他键执行某些操作”的操作,则可以执行以下操作:

(defn func [& {:keys [a b] :as args}]
  (println a b c)
  (println (dissoc args :a :b)))

(func :a 3 :b :c 5) =>
  3 4
  {:c 5}
  nil

如果你不得不两次提到这些关键词,你也可能会对此做些什么,但我无法想象它值得打扰。

  
    

我想要这个的原因是如果rest不为null,这可能是一个错误,我想发出信号。

  

如果你担心用户不是完全你想要的,那么地图可能不是正确的数据结构。

答案 1 :(得分:3)

如果您关心对给定地图强制执行结构,Schema可能是一个不错的选择(来自README的第一个示例):

(ns schema-examples
  (:require [schema.core :as s
             :include-macros true ;; cljs only
             ]))

(def Data
  "A schema for a nested data type"
  {:a {:b s/Str
       :c s/Int}
   :d [{:e s/Keyword
        :f [s/Num]}]})

(s/validate
  Data
  {:a {:b "abc"
       :c 123}
   :d [{:e :bc
        :f [12.2 13 100]}
       {:e :bc
        :f [-1]}]})
;; Success!

(s/validate
  Data
  {:a {:b 123
       :c "ABC"}})
;; Exception -- Value does not match schema:
;;  {:a {:b (not (instance? java.lang.String 123)),
;;       :c (not (integer? "ABC"))},
;;   :d missing-required-key}

答案 2 :(得分:0)

(Phil Lord,OP毫无疑问会转向其他问题,但对于有类似问题的人来说,这是一个可能的解决方案。)

您可以使用count来测试地图是否具有正确数量的键:

(count {:a 1 :b 2 :c 3 :d 4}) ;=> 4

返回键/值对的数量。只要您单独测试地图是否具有必需的键,就知道有太多的键会告诉您是否还有其他键。

答案 3 :(得分:0)

我喜欢plumbing的做法:

(use '[plumbing.core])
(defnk f1 [a b c & rest]
    (prn [a b c])
    (prn rest))
(f1 {:a 1 :b 2 :c 66 :z "fake"})

[1 2 66]
{:z "fake"}
=> nil