什么是Clojure?

Ert*_*tin 15 clojure

我无法理解Clojure 中reify函数的用法.它在clojure中用于什么?

你能提供一些例子吗?

Ada*_*Lee 43

reifydefrecord什么fndefn.
"啊,对啊......那是什么reify"

简而言之,协议是数据类型应该支持的函数列表,记录是数据类型,而reifications是匿名数据类型.

也许这是啰嗦,但是reify如果不理解协议和类型/记录就不能具体理解:协议是一种为函数使用相同名称的方法,例如conj在给定不同参数时实际行为不同((conj [:b :c] :a) => [:b :c :a]但是(conj '(:b :c) :a) => (:a :b :c)).记录就像对象或类型(但它们的行为就像地图一样令人敬畏).

更重要的是,目标是解决"表达式问题",即能够无缝添加与现有功能一起使用的新类型数据,以及与现有数据无缝协作的新功能.

所以有一天你会对自己说:"自我,你应该学会成为一只鸭子意味着什么!" 所以你写了一个协议:

(defprotocol Quacks
  (quack [_] "should say something in ducky fashion"))
Run Code Online (Sandbox Code Playgroud)

但是,这一切都太过抽象,所以你" 真正的 IFY"吧:

(def donald (reify Quacks
                   (quack [_] "Quacks and says I'm Donald")))
Run Code Online (Sandbox Code Playgroud)

现在终于可以体验到你的创作了:

(quack donald) => "Quacks and says I'm Donald"
Run Code Online (Sandbox Code Playgroud)

然后你还记得Daffy:

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

(quack daffy) => "Quacks and says I'm Daffy"
Run Code Online (Sandbox Code Playgroud)

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

(defrecord Duck [name]
  Quacks
  (quack [_] (str "Quacks and says I'm " name)))
Run Code Online (Sandbox Code Playgroud)

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

(def huey (->Duck "Huey"))
(def duey (Duck. "Duey"))
(def louie (new Duck "Louie"))

(quack huey) => "Quacks and says I'm Huey"
Run Code Online (Sandbox Code Playgroud)

请记住,记录就像地图一样(感谢协议!):

(:name huey) => "Huey"
Run Code Online (Sandbox Code Playgroud)

但你记住,鸭必须嘎嘎走路那么你写的另一种协议:

(defprotocol Walks
  (walk [_] "should walk like a duck"))
Run Code Online (Sandbox Code Playgroud)

并扩展鸭子的定义

(extend-type Duck
  Walks
  (walk [_] "waddle waddle"))

(walk louie) => "waddle waddle"
Run Code Online (Sandbox Code Playgroud)

现在我们可以扩展其他类型来实现相同的协议(教授相同的功能如何使用其他东西):

所以,让我们说我们希望程序员也嘎嘎叫:-)

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

(quack (Programmer.)) => "Monads are simply monoids in a category of endofunctors..."
Run Code Online (Sandbox Code Playgroud)

我推荐这个对协议的精彩解释,一个reify解释和一个关于"勇敢与真实的Clojure"协议章节.

免责声明:这只是为了初步了解协议是什么,而不是如何使用它们的最佳实践. "Psst!我回答这个问题很大程度上是为了自学,因为直到昨天我才真正编写自己的协议/界面!"

因此,虽然我希望它能增强别人的学习,但我会衷心欢迎批评或编辑建议!"

  • 我喜欢你的回答!既真实的解释又幽默。正如费曼曾经说过的,尝试向别人解释某些事情是学习自己的最好方法。 (3认同)

Pio*_*dyl 18

reifymacro允许创建一个匿名类扩展java.lang.Object类和/或实现指定的接口/协议.该API文档不明确说明的目的而提供的技术细节是什么呢宏.Java互操作文档提供了目的的简要说明:

从Clojure 1.2开始,reify也可用于实现接口.

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

虽然deftype和defrecord定义了命名类型,但reify定义了一个匿名类型并创建了该类型的实例.用例是您需要一次性实现一个或多个协议或接口,并希望利用本地上下文.在这方面,它是类似于代理的用例,或Java中的匿名内部类.

reify的方法体是词法闭包,可以参考周围的局部范围.reify与代理的不同之处在于:

仅支持协议或接口,不支持具体的超类.方法体是结果类的真实方法,而不是外部fns.在实例上调用方法是直接的,而不是使用地图查找.不支持方法映射中的方法的动态交换.结果是在构造和调用方面都比代理更好的性能.在其约束不受限制的所有情况下,reify优于代理.