Ответ Роба, конечно, правильный;Я публикую это в ответ на комментарий ОП к нему - возможно, это может быть полезно для реализации требуемой функциональности с deftype
.
. Я однажды написал реализацию «карты по умолчанию» дляClojure, который действует как обычная карта, за исключением того, что он возвращает фиксированное значение по умолчанию, когда его спрашивают о ключе, отсутствующем внутри него.Код находится в этом Gist .
Я не уверен, что он подойдет для вашего варианта использования напрямую, хотя вы можете использовать его для таких вещей, как
user> (:earth (assoc (DefaultMap. 0 {}) :earth 8000000000))
8000000000
user> (:mars (assoc (DefaultMap. 0 {}) :earth 8000000000))
0
Что еще более важно, он должен дать вам представление о том, что связано с написанием такого рода вещей с помощью deftype
.
С другой стороны, он основан на clojure.core/emit-defrecord
, так что вы можете посмотреть на эту часть источников Clojure.вместо этого ... Он делает много вещей, которые вам не понадобятся (потому что это функция для подготовки расширений макросов - в нем много цитат и тому подобного, которые вы должны удалить из него, чтобы использоватьнепосредственно), но это, безусловно, источник информации самого высокого качества. Здесь - прямая ссылка на эту точку в источнике для релиза Clojure 1.2.0.
Обновление:
Еще одна вещь, которую японял, может быть важно.Если вы используете специальный тип карты для реализации такого рода вещей, клиент может merge
превратить его в обычную карту и потерять «дефолтную» функциональность (и даже любую другую специальную функциональность) в процессе.Пока иллюзия "сходства с картой", поддерживаемая вашим типом, является достаточно полной, чтобы ее можно было использовать в качестве обычной карты, передавать в стандартную функцию Clojure и т. Д., Я думаю, что этого не может быть.
Итак, на каком-то уровне клиент, вероятно, должен будет знать, что в этом есть какая-то «магия»;если они получат правильные ответы на запросы, такие как (:mars {...})
(без :mars
в {...}
), им придется помнить, чтобы не merge
это в регулярную карту (merge
- наоборот)будет работать нормально).