Clojure中的reify是什么?

What is reify in Clojure?

我无法理解Clojure中reify函数的用法。
Clojure有什么用?

你能提供例子吗?


reify对应defrecordfn对应defn
"哦,对了……reify是什么?"

简而言之,协议是数据类型应支持的功能列表,记录是数据类型,而修正是匿名数据类型。

也许这很费劲,但是如果不了解协议和类型/记录,就无法具体理解reify:协议是对诸如conj之类的函数使用相同名称的一种方法,当给定不同的参数时,它们实际上会以不同的方式起作用((conj [:b :c] :a) => [:b :c :a](conj '(:b :c) :a) => (:a :b :c))。记录就像对象或类型(但它们的行为就像地图一样,使它们变得很棒)。

从根本上讲,目标是解决"表达式问题",即能够无缝添加与现有功能配合使用的新型数据以及与现有数据无缝配合使用的新功能。

因此,有一天你对自己说:"自我,你应该学习成为鸭子的意义!"所以你写一个协议:

1
2
(defprotocol Quacks
  (quack [_]"should say something in ducky fashion"))

但这太抽象了,所以您要"意识到"它:

1
2
(def donald (reify Quacks
                   (quack [_]"Quacks and says I'm Donald")))

现在,您终于可以体验自己的创作了:

1
(quack donald) =>"Quacks and says I'm Donald"

然后,您会记得有关Daffy的信息:

1
2
3
4
(def daffy (reify Quacks
                  (quack [_] (str"Quacks and says I'm Daffy"))))

(quack daffy) =>"Quacks and says I'm Daffy"

但是,当您记得Huey时,您意识到了自己的错误并以可重复使用的方式定义了鸭子是什么:

1
2
3
(defrecord Duck [name]
  Quacks
  (quack [_] (str"Quacks and says I'm" name)))

并制作new鸭子(有几种方法可以做到):

1
2
3
4
5
(def huey (->Duck"Huey"))
(def duey (Duck."Duey"))
(def louie (new Duck"Louie"))

(quack huey) =>"Quacks and says I'm Huey"

请记住,记录的行为就像地图(感谢协议!):

1
(:name huey) =>"Huey"

但是后来您记住鸭子必须嘎嘎走路,所以您编写了另一个协议:

1
2
(defprotocol Walks
  (walk [_]"should walk like a duck"))

并扩展了鸭子的定义

1
2
3
4
5
(extend-type Duck
  Walks
  (walk [_]"waddle waddle"))

(walk louie) =>"waddle waddle"

现在,我们可以扩展其他类型来实现相同的协议(教相同的功能如何与其他事物配合使用):

因此,假设我们也希望程序员也惊:-)

1
2
3
4
(defrecord Programmer [] Quacks
  (quack [_]"Monads are simply monoids in a category of endofunctors..."))

(quack (Programmer.)) =>"Monads are simply monoids in a category of endofunctors..."

我建议对协议进行出色的解释,对reify进行解释,并在"勇敢与真实的Clojure"中介绍协议。

免责声明:这仅是为了初步了解什么协议,而不是如何使用它们的最佳实践。"抱歉!我回答这个问题主要是为了自学,因为直到昨天我才真正写过自己的协议/接口!"

因此,尽管我希望它能促进其他人的学习,但我也衷心欢迎批评或编辑建议!"


reify宏允许创建扩展java.lang.Object类的匿名类和/或实现指定的接口/协议。 API文档并未明确描述目的,而是提供了该宏的功能的技术细节。 Java interop文档提供了有关目的的简短描述:

As of Clojure 1.2, reify is also available for implementing
interfaces.

甚至可以在数据类型文档中找到更多信息,在其中可以找到非常详细的描述以及它与proxy的比较:

While deftype and defrecord define named types, reify defines both an
anonymous type and creates an instance of that type. The use case is
where you need a one-off implementation of one or more protocols or
interfaces and would like to take advantage of the local context. In
this respect it is use case similar to proxy, or anonymous inner
classes in Java.

The method bodies of reify are lexical closures, and can refer to the
surrounding local scope. reify differs from proxy in that:

Only protocols or interfaces are supported, no concrete superclass.
The method bodies are true methods of the resulting class, not
external fns. Invocation of methods on the instance is direct, not
using map lookup. No support for dynamic swapping of methods in the
method map. The result is better performance than proxy, both in
construction and invocation. reify is preferable to proxy in all cases
where its constraints are not prohibitive.