推荐使用宏向 Clojure 的 defrecord 构造函数添加功能吗?

发布于 2024-09-26 04:27:01 字数 504 浏览 6 评论 0原文

clojure 中的 defrecord 允许使用自定义字段定义简单的数据容器。

例如,

user=> (defrecord Book [author title ISBN])
user.Book

结果的最小构造函数仅采用位置参数,没有附加功能,例如字段默认、字段验证等。

user=> (Book. "J.R.R Tolkien" "The Lord of the Rings" 9780618517657)
#:user.Book{:author "J.R.R Tolkien", :title "The Lord of the Rings", :ISBN 9780618517657}

始终可以编写包装默认构造函数的函数以获得更复杂的构造语义 - 使用关键字参数、提供默认值等在。

这似乎是宏提供扩展语义的理想场景。人们编写和/或推荐哪些宏来实现更丰富的 defrecord 构造?

defrecord in clojure allows for defining simple data containers with custom fields.

e.g.

user=> (defrecord Book [author title ISBN])
user.Book

The minimal constructor that results takes only positional arguments with no additional functionality such as defaulting of fields, field validation etc.

user=> (Book. "J.R.R Tolkien" "The Lord of the Rings" 9780618517657)
#:user.Book{:author "J.R.R Tolkien", :title "The Lord of the Rings", :ISBN 9780618517657}

It is always possible to write functions wrapping the default constructor to get more complex construction semantics - using keyword arguments, supplying defaults and so on.

This seems like the ideal scenario for a macro to provide expanded semantics. What macros have people written and/or recommend for richer defrecord construction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不交电费瞎发啥光 2024-10-03 04:27:01

支持完整和部分记录构造函数以及支持可评估打印和 pprint 表单的示例:

David 是我的一位同事,我们在项目中广泛使用这个 defrecord2。我认为这样的东西确实应该成为 Clojure 核心的一部分(当然细节可能会有很大差异)。

我们发现重要的事情是:

  • 能够使用命名(可能是部分)参数构造记录:(new-foo {:a 1})
  • 能够通过复制现有记录并进行修改来构造记录:(new -foo old-foo {:a 10})
  • 字段验证 - 如果您传递声明的记录字段之外的字段,则会抛出错误。当然,这实际上是合法的并且可能有用,因此有一些方法可以使其成为可选的。由于它在我们的使用中很少见,因此它更有可能是一个错误。
  • 默认值 - 这些将非常有用,但我们还没有实现它。 Chas Emerick 在此处撰写了有关添加对默认值的支持的文章:http://cemerick。 com/2010/08/02/defrecord-slot-defaults/
  • 打印和 pprint 支持 - 我们发现以可评估返回原始记录的形式打印和 pprint 记录非常有用。例如,这允许您运行测试、滑动实际输出、验证它并将其用作预期输出。或者从调试跟踪中滑动输出并获得真正的可评估形式。

Examples of support for full and partial record constructor functions and support for eval-able print and pprint forms:

David is a colleague of mine and we are using this defrecord2 extensively in our project. I think something like this should really be part of Clojure core (details might vary considerably of course).

The things we've found to be important are:

  • Ability to construct a record with named (possibly partial) parameters: (new-foo {:a 1})
  • Ability to construct a record by copying an existing record and making modifications: (new-foo old-foo {:a 10})
  • Field validation - if you pass a field outside the declared record fields, throw an error. Of course, this is actually legal and potentially useful, so there are ways to make it optional. Since it would be rare in our usage, it's far more likely to be an error.
  • Default values - these would be very useful but we haven't implemented it. Chas Emerick has written about adding support for default values here: http://cemerick.com/2010/08/02/defrecord-slot-defaults/
  • Print and pprint support - we find it very useful to have records print and pprint in a form that is eval-able back to the original record. For example, this allows you to run a test, swipe the actual output, verify it, and use it as the expected output. Or to swipe output from a debug trace and get a real eval-able form.
╰◇生如夏花灿烂 2024-10-03 04:27:01

这是一个定义记录的具有默认值和不变量。它创建一个可以使用关键字参数来设置字段值的构造函数。

(defconstrainedrecord Foo [a 1 b 2]
  [(every? number? [a b])])

(new-Foo)
;=> #user.Foo{:a 1, :b 2}

(new-Foo :a 42)
; #user.Foo{:a 42, :b 2}

就像我说的......不变量:

(new-Foo :a "bad")
; AssertionError

但它们只有在 Trammel 的上下文中才有意义。

Here is one that defines a record with default values and invariants. It creates a ctor that can take keyword args to set the values of the fields.

(defconstrainedrecord Foo [a 1 b 2]
  [(every? number? [a b])])

(new-Foo)
;=> #user.Foo{:a 1, :b 2}

(new-Foo :a 42)
; #user.Foo{:a 42, :b 2}

And like I said... invariants:

(new-Foo :a "bad")
; AssertionError

But they only make sense in the context of Trammel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文