【问题标题】:How to define a user defined data type in clojure?如何在 clojure 中定义用户定义的数据类型?
【发布时间】:2022-08-16 11:04:50
【问题描述】:

我想使用用户定义的正则表达式模式来定义 edn 文件中的日期,以使用 malli 进行验证。 我如何在 core.clojure 中定义这个模式,以便我可以在 edn 文件中使用它。

这就是我的 edn 文件以前的样子。

(def reading-schema
  [:map
   [:readingDate :re #\"\\d{4}-\\d{2}-\\d{2}\"]
   [:readingType string?]
   [:readingPrecision string?]
   [:readingEstimate string?]])

(def readingDetails-schema
  [:map
   [:readingCode string?]
   [:readingNumber string?]
   [:readingCheck string?]
   [:readings [:vector reading-schema]]])

但我无法将其加载到 core.clj。如何解决这个问题?一种方法是在 clojure 中定义。但我不知道该怎么做。

假设这就是我如何将我的 /edn 文件定义为将所有模式放在一个位置。

  {
   :reading-schema [:map
                     [:readingDate :re #\"\\d{4}-\\d{2}-\\d{2}\"]
                     [:readingType string?]
                     [:readingPrecision string?]
                     [:readingEstimate string?]]
    
    :readingDetails-schema [:map
                            [:readingCode string?]
                            [:readingNumber string?]
                            [:readingCheck string?]
                            [:readings [:vector reading-schema]]]
}

在 core.clj 中,我使用 malli 用来调用任何 edn 文件的 aero 库来调用它。


编辑: 这是我面临的错误:

Execution error at aero.core/read-pr-into-tagged-literal (core.cljc:180).
No dispatch macro for: \"
  • \“但我无法加载这个\” - 请添加你得到的错误。你也真的想要有def 吗?你真的想加载这个文件吗?代码并且您的应用程序的用户应该是 apbel 来提供此文件?在这种情况下,你可以告诉用户创建这个文件,把它放在类路径上,然后你 require 它。
  • 是的,我现在添加了错误。我正在使用 def 进行检查,因为我想签入 repl。因此,我在旅途中定义方案并进行检查。现在我想将所有模式存储在一个 edn 文件中。

标签: validation clojure schema malli


【解决方案1】:

EDN 不支持 clojure 阅读器支持的所有阅读器宏(或“功能”)(see the built-in tagged elements)。但是你可以很容易地添加你自己的读者(见:readers of opts):

user=> (doc clojure.edn/read)
-------------------------
clojure.edn/read
([] [stream] [opts stream])
  Reads the next object from stream, which must be an instance of
  java.io.PushbackReader or some derivee.  stream defaults to the
  current value of *in*.

  Reads data in the edn format (subset of Clojure data):
  http://edn-format.org

  opts is a map that can include the following keys:
  :eof - value to return on end-of-file. When not supplied, eof throws an exception.
  :readers  - a map of tag symbols to data-reader functions to be considered before default-data-readers.
              When not supplied, only the default-data-readers will be used.
  :default - A function of two args, that will, if present and no reader is found for a tag,
             be called with the tag and the value.

例如:为re 添加一个阅读器,然后可以使用它在您的EDN 文件中将#re 放在字符串之前。

(require '[clojure.edn :as edn])

(let [re (edn/read-string
           {:readers {'re re-pattern}} ; XXX
           (slurp "schema.edn"))]
  (assert (re-matches re "2022-01-01")))

使用这个schema.edn

#re "\\d{4}-\\d{2}-\\d{2}"

(注意原始正则表达式中的 \ - 在字符串中您需要转义它们)

【讨论】:

    【解决方案2】:

    也可以使用 clj-time 来完成。你可以从https://github.com/clj-time/clj-time试试这个

    在 project.clj 中添加依赖项并将其添加到您的命名空间。 然后您可以定义“日期”类型的变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-12
      • 2011-04-10
      • 2014-12-31
      相关资源
      最近更新 更多