如何确定类型实现什么协议? [英] How to figure out what protocols the type implements?

查看:123
本文介绍了如何确定类型实现什么协议?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一些类型或记录,如何获得它实现的所有协议?

Given some type or record, how can I get all the protocols it implements?

让我们假设我们有以下代码:

Let's say we have the following code:

(defprotocol P1
  (op1 [this]))

(defprotocol P2
  (op2 [this]))

(defrecord R []
  P1
  (op1 [_] 1)
  P2
  (op2 [_] 2))

我需要的是一个类似这样的函数:

And what I need is a function that does something like this:

(all-protocols-for-type R) ;; => (P1 P2)

如果有后端拦截功能,有一个Clojure和ClojureScript的机制。

It will be good if there's something backend-agnosting, because I'd like to have a mechanism for both Clojure and ClojureScript.

UPD:这是为了内省什么功能的特定类型提供。让我们说,通过这样做:

UPD: the intention for this is to introspect what functionality the particular type provides. Let's say, by doing this:

user> (supers (type {}))
#{clojure.lang.AFn clojure.lang.ILookup java.lang.Object java.util.Map clojure.lang.Seqable java.lang.Runnable clojure.lang.IPersistentCollection java.io.Serializable clojure.lang.IFn clojure.lang.APersistentMap clojure.lang.Associative java.util.concurrent.Callable clojure.lang.IKVReduce clojure.lang.Counted clojure.lang.IMeta clojure.lang.IMapIterable java.lang.Iterable clojure.lang.IPersistentMap clojure.lang.IEditableCollection clojure.lang.IObj clojure.lang.MapEquivalence clojure.lang.IHashEq}

我知道我可以使用map作为函数( IFn ),通过键查找值( Associative ),甚至在它上面 reduce-kv IKVReduce )。

I will know that I can use map as a function (IFn), lookup a value by key there (Associative) and even do reduce-kv on it (IKVReduce).

推荐答案

这是在Clojure中最接近的,没有做任何疯狂的事情:

This is the closest you can get in Clojure without doing something crazy:

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

(deftype EmptyType [])

(defrecord EmptyRecord [])

(defn all-protocols-for-type [t]
  (map (comp symbol (memfn getSimpleName))
       (set/difference (supers t)
                       (set/union (supers EmptyType)
                                  (supers EmptyRecord)))))

map 只是为了得到一个与您在问题中给出的格式相同的输出;你应该按照你的想法修改映射函数。

I used that specific map just to get an output with the same format you gave in your question; you should modify the mapping function as you see fit.

基本上,你要求的是硬币的另一面。使用 deftype defrecord 扩展协议使用 extend-type extend-protocol 存储协议的信息。

Basically, what you're asking is the other side of the coin to this. Extension of a protocol using deftype or defrecord stores the information on the type, and extension using extend-type or extend-protocol stores the information on the protocol.

如果您的所有扩展都直接在 deftype defrecord 中完成,您可以使用方法。如果所有的扩展都是通过 extend-type extend-protocol 完成的,你可以得到给定的所有类型协议使用亚历克斯在他的答案该方法的另一个问题的方法。但是在所有情况下都没有一个很好的方法。

So if all your extensions are done directly in deftype or defrecord, you can get all the protocols for a given type using the method I gave above. If all your extensions are done with extend-type or extend-protocol, you can get all the types for a given protocol using the method Alex gave in his answer to that other question. But there isn't a nice way to do both in all cases.

这篇关于如何确定类型实现什么协议?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆