Я думаю, что deftype
может быть подходящим вариантом, однако я бы хотел воспользоваться методами доступа. Вместо этого посмотрите на clojure.lang.ILookup
и clojure.lang.Associative
; это интерфейсы, которые, если вы реализуете их для своего типа, позволят вам использовать get
/ get-in
и assoc
/ assoc-in
, что делает их гораздо более универсальным решением (не только вы сможете изменить базовая реализация, но, возможно, также использовать функции, созданные поверх стандартной библиотеки коллекций Clojure, для управления вашими структурами).
Несколько замечаний:
Вы, вероятно, должны начать с defrecord
, используя get
, assoc
& Co. со стандартными defrecord
реализациями ILookup
, Associative
, IPersistentMap
и java.util.Map
. Возможно, вам удастся пройти довольно долгий путь.
Если / когда этого уже недостаточно, взгляните на источники для emit-defrecord
(закрытая функция, определенная в core_deftype.clj
в источниках Clojure). Это довольно сложно, но даст вам представление о том, что вам может понадобиться реализовать.
Ни deftype
, ни defrecord
в настоящее время не определяют какие-либо заводские функции для вас, но вам, вероятно, следует сделать это самостоятельно. Проверка работоспособности выполняется внутри этих функций (и / или соответствующих тестов).
Более концептуально сложные операции, безусловно, идеально подходят для протокольных функций, построенных на основе get
& Co.
Да, и посмотрите на gvec.clj
в источниках Clojure для примера того, как может выглядеть какой-то серьезный код структуры данных, написанный с использованием deftype
. Сложность здесь отличается от того, что вы описываете в этом вопросе, но все же это один из немногих примеров программирования пользовательских структур данных в Clojure, доступных в настоящее время для общего пользования (и, конечно, это код отличного качества).
Конечно, это именно то, что говорит мне моя интуиция в это время. Я не уверен, что на данном этапе есть много способов установить идиомы, что с deftype
на самом деле не было выпущено и все. : -)