Что такое Clojure эквивалент Overriding "равно" в Java? - PullRequest
5 голосов
/ 06 октября 2011

Я недавно спрашивал о составных ключах в картах в clojure: Как реализовать составные ключи в clojure? ...

Ответ был таков: они работают аналогично ключам Java - есличто-то переопределяет «равно», тогда это может быть эффективно использовано в качестве ключа.

Мне было интересно: существуют ли макросы, которые позволяют нам переопределять «равно» для пользовательских структур данных?Например, скажем, я хотел использовать карту в качестве ключа и определить уникальность как «если эта карта содержит 2 или более элементов, общих с другой картой, они равны».Как я могу переопределить поведение карты по умолчанию?

В java я считаю, что это средство достаточно мощное при создании высокоскоростных карт с тысячами бинов в качестве ключей.

Ответы [ 3 ]

5 голосов
/ 07 октября 2011

Надеюсь, чтобы внести некоторую ясность в это обсуждение, в Java принято переопределять hashCode и equals. Например, вы пытаетесь отслеживать сотрудников, которые имеют имена, но могут также иметь псевдоним. Цель состоит в том, чтобы убедиться, что эти сотрудники не дублируются. В этом случае я бы переопределил equals и hashCode, чтобы посмотреть только идентификатор сотрудника. Когда эти сотрудники вводятся в структуру данных Set, они не дублируются. В Clojure вы можете сделать:

(deftype Employee [name id]
  Object
  (equals [a b] (= (.id a) (.id b)))
  (hashCode [this] (.hashCode (.id this)))
  (toString [this] (.name this)))

(def vince (Employee. "Vince" 42))

(def vincent (Employee. "Vincent" 42))

(def tony (Employee. "Tony" 2))

(into #{} [vince vincent tony])

Но вы, возможно, захотите воспользоваться решением для структуры данных "чисто Clojure", а не использовать хеш-код, равнозначный пути взаимодействия Java.

4 голосов
/ 07 октября 2011

Дело не в том, что коллекции clojure override равно;Переопределение равенства происходит почти везде, где вы делаете что-то интересное.Типы Clojure предоставляют реализацию equals, которая должна быть согласованной для всего языка (возможно, так, как Java предполагалось использовать).Это означает, что вещи, которые «равны», должны быть единичными элементами в наборах и единичными ключами на картах, всегда, везде .Языковой дизайн зависит от этого.В Clojure 1.3 были внесены некоторые явные не обратно совместимые изменения, чтобы приблизиться к этому идеалу.

Если идти вразрез с ожидаемым поведением равных, то, скорее всего, где-то возникнет проблема.И не так уж сложно использовать собственные композитные наборы, когда они вам действительно нужны, в любом случае не навязывая свою волю ядру equals.если ты действительно хочешь.См. http://clojure.org/datatypes в качестве отправной точки.

1 голос
/ 06 октября 2011

Это безумие как в Clojure, так и на Java. Не делай этого . Вы нарушаете контракт класса Object и интерфейса Map; все виды вещей полностью развалились бы, если бы они использовали ваш класс карты. Если вы укажете, что два объекта equal, то их хеш-коды должны быть идентичны, иначе HashMap, удерживающий их, не сможет справиться. Конечно, вы можете сделать все хэшировать до 0, но ваша высокопроизводительная карта - это теперь связанный список.

Тем не менее, вы можете сделать что-то подобное в Clojure или Java, используя sorted-map (или SortedMap соответственно) с пользовательским компаратором. Тем не менее, существуют миллионы ловушек, если вы выбираете Comparator, который не на самом деле реализует равенство, а вместо этого является своего рода "нечетким равенством".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...