什么是Clojure?

时间:2016-05-05 18:59:31

标签: clojure

我无法理解Clojure中 reify 功能的用法。 它在clojure中的用途是什么?

你能提供一些例子吗?

2 个答案:

答案 0 :(得分:39)

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"))

但它太抽象了所以你真实 ify'它:

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

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

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

然后你还记得Daffy:

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

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

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

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

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

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

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

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

(:name huey) => "Huey"

但是你记得鸭子必须嘎嘎走路才能写下另一个协议:

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

并扩展duck

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

(walk louie) => "waddle waddle"

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

所以让我们说程序员也要嘎嘎叫: - )

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

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

我推荐这个很棒的explanation of protocolsexplanation of reifychapter on protocols in "Clojure for the Brave and True"

免责声明:这只是为了初步了解哪些协议是如何使用它们的最佳做法。 “Psst!我回答这个问题很大程度上是为了自学,因为直到昨天我才真正编写自己的协议/接口!”

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

答案 1 :(得分:18)

reify宏允许创建扩展java.lang.Object类和/或实现指定接口/协议的匿名类。 API docs没有明确描述目的,而是提供宏所做的技术细节。 Java interop documentation提供了目的的简要说明:

  

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

datatypes documentatio n中可以找到更多信息,您可以在其中找到非常详细的说明,以及与proxy的比较:

  

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

     

reify的方法体是词法闭包,可以参考   围绕当地范围。 reify与代理的不同之处在于:

     

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