2016-01-17 2 views
2

Я пишу реализацию структуры данных Trie в Clojure и полагал, что было бы лучше использовать defrecord для создания моего собственного типа, который может перегружать функции, которые работают с коллекциями. Как я могу определить название протокола для расширения, чтобы я мог реализовать функции conj и другие подобные функции для моего нового типа Trie?Какой протокол распространяется для типа Trie?

ответ

4

Если вы хотите внедрить новую структуру данных, вы захотите использовать deftype вместо defrecord, так как последняя проделает определенную реализацию поведения карты для результирующих типов.

Что касается clojure.core функций коллекции, большинство из них основаны на интерфейсах, а не на протоколах. (ClojureScript делает протоколы использования, однако.) Самый простой способ узнать, какие интерфейсы могут иметь отношение к новой структуре данных для изучения подобных структур данных, которые уже существуют:

;; all superclasses and interfaces of the class of {}, that is, 
;; clojure.lang.PersistentArrayMap 
(ancestors (class {})) 

;; interfaces only 
(filter #(.isInterface %) (ancestors (class {}))) 

Поскольку вы планируете внедрение синтаксического дерева , Я предполагаю, что вы хотите реализовать карту или установить. Если это так, data.avl реализует все соответствующие интерфейсы (и все соответствующие протоколы в версии ClojureScript) - вы могли бы взглянуть на источник.

+0

Отлично, спасибо! У меня есть еще одна проблема, как бы я определил имя и порядок аргументов функций для расширения? Например, я знаю, что 'empty?' Является частью установленного интерфейса, но в java-коде он выглядит как 'empty'. Кроме того, 'cons' принимает последовательность как второй аргумент, но при определении функций в протоколах список аргументов ожидает вместо этого' this' как первого аргумента. Как мне обойти это? – MONODA43

+0

Для интерфейсов 'clojure.lang' вы можете посмотреть исходный код либо самого Clojure, либо библиотеки, которая реализует эти интерфейсы (например, вышеупомянутые data.avl). Для интерфейсов, предоставляемых JDK, имеет смысл читать Javadoc - [вот страница о java.util.Map в JDK 8] (https://docs.oracle.com/javase/8/docs/api/java/ util/Map.html), другие легко доступны. Не имеет значения, в каком порядке пользовательские функции принимают свои аргументы; вам необходимо реализовать методы, объявленные в соответствующих интерфейсах, а функции из 'clojure.core' будут заботиться о их вызове. –

+0

Кроме того, 'empty?' Не соответствует непосредственно любому методу в любом встроенном интерфейсе. Вместо этого он построен из 'not' и' seq' - см. '(Source empty?)'. Метод 'empty', объявленный' clojure.lang.IPersistentCollection', вместо этого соответствует функции 'clojure.core/empty' - см.' (Doc empty) 'для описания того, что он делает. –

Смежные вопросы