【问题标题】:Clojure: hash-map and array-map type conflicts in defined schemaClojure:定义模式中的哈希映射和数组映射类型冲突
【发布时间】:2018-07-17 18:39:47
【问题描述】:

我正在开发一个 Clojure API,但是当地图中的项目数量发生变化时,我遇到了关于 Clojure 在 HashMapArrayMap 之间自动“类型切换”的问题。

阅读文档:https://clojuredocs.org/clojure.core/array-map#example-57392e25e4b071da7d6cfd0c

假设我有一个这样的 POST 请求:

  (POST "/" []
    :body [foo FooSchema]
    (create-response ok {:message "foo!"}))

FooSchema 定义如下:

(def ArrayMap clojure.lang.PersistentArrayMap)

(def Bar ArrayMap)

(s/defschema FooSchema
  {:id    s/Str
   :bar   Bar})

:bar 以 javascript 对象的形式发送,其结构如下:

{
  id: 1,
  fh: 1,
  rdstr: "flying"
}

如文档中所述,如果 :bar 对象在 body 中返回少于 9 个项目,那么它将产生 ArrayMap,它可以正常工作。不管怎样,当:bar对象缩放并返回超过9个项目时,请求失败,返回错误:

(not (instance? clojure.lang.PersistentArrayMap a-clojure.lang.PersistentHashMap))

因为:bar 自动(神奇地)切换为HashMap

反之亦然,如果我将 :bar 的架构类型设置为 HashMap,那么少于 9 个项目的对象也不起作用。

无论如何我们总是可以强制类型为HashMap

【问题讨论】:

    标签: java clojure hashmap compojure


    【解决方案1】:

    我假设您使用的是Plumatic Schema

    您可以定义一个谓词来捕获像这样的所有类型的地图

    (ns your.schema.namespace
      (:require [schema.core :as s]))
    
    (def Map (s/pred map?))
    
    (defschema FooSchema
      {:id s/Str
       :bar Map})
    

    map? 为 Clojure 中的任何类型的地图返回 true

    => (map? (array-map))
    => true
    => (map? (hash-map))
    => true
    

    【讨论】:

      【解决方案2】:

      这两种类型都太具体了。您应该使用更通用的类型,表示任何类似地图的内容。显而易见的选择是clojure.lang.IPersistentMap

      【讨论】:

      • 对我来说看起来很合理。我们采用了这个解决方案:)
      猜你喜欢
      • 2017-12-18
      • 2015-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多