7

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

所以,例如像......

 (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 不为空,这可能是一个错误,我想发出信号。我知道 :as,我可以使用它。但是我需要将有效密钥列表存储两次。

我错过了什么吗?

菲尔

4

4 回答 4

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 不为空,这可能是一个错误,我想发出信号。

如果您担心用户传入的数据不完全符合您的要求,那么地图可能不是正确使用的数据结构。

于 2012-11-03T14:40:08.733 回答
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}
于 2015-10-30T16:40:22.273 回答
0

(菲尔勋爵,毫无疑问,OP 已经转向了其他问题,但对于任何有类似问题的人来说,这是一个可能的解决方案。)

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

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

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

于 2017-03-17T18:47:53.563 回答
0

我喜欢管道如何做到这一点:

(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
于 2019-03-10T11:18:22.543 回答