Если вы взаимодействуете с кодом Java, вам, возможно, придется стиснуть зубы и сделать это способом Java, используя .put
. Это не обязательно смертный грех; Clojure предоставляет вам такие вещи, как do
и .
, специально для того, чтобы вы могли легко работать с кодом Java.
assoc
работает только со структурами данных Clojure, потому что много работы ушло на то, чтобы сделать создание новых (неизменяемых) копий с небольшими изменениями очень дешевым. Java HashMaps не предназначены для работы таким же образом. Вам придется клонировать их каждый раз, когда вы вносите изменения, что может быть дорогостоящим.
Если вы действительно хотите выбраться из страны мутаций Java (например, вы храните эти HashMaps в течение длительного времени и не хотите, чтобы вызовы Java были повсюду, или вам нужно сериализовать их через print
и read
, или вы хотите работать с ними потокобезопасным способом с помощью Clojure STM), вы можете достаточно легко конвертировать между Java HashMaps и хэш-картами Clojure, потому что структуры данных Clojure реализуют правильные интерфейсы Java, поэтому они могут взаимодействовать друг с другом.
user> (java.util.HashMap. {:foo :bar})
#<HashMap {:foo=:bar}>
user> (into {} (java.util.HashMap. {:foo :bar}))
{:foo :bar}
Если вам нужна вещь, похожая на do
, которая возвращает объект, над которым вы работаете, когда вы закончили работу над ним, вы можете использовать doto
. Фактически, Java HashMap используется в качестве примера в официальной документации для этой функции, что является еще одним признаком того, что это не конец света, если вы используете объекты Java (разумно).
clojure.core/doto
([x & forms])
Macro
Evaluates x then calls all of the methods and functions with the
value of x supplied at the front of the given arguments. The forms
are evaluated in order. Returns x.
(doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))
Некоторые возможные стратегии:
Ограничьте свои мутации и побочные эффекты одной функцией, если можете. Если ваша функция всегда возвращает одно и то же значение при одних и тех же входных данных, внутри она может делать все, что захочет. Иногда изменение массива или карты является наиболее эффективным или простым способом реализации алгоритма. Вы по-прежнему будете пользоваться преимуществами функционального программирования до тех пор, пока вы не "сливаете" побочные эффекты остальному миру.
Если ваши объекты будут использоваться какое-то время или они должны хорошо сочетаться с другим кодом Clojure, постарайтесь поместить их в структуры данных Clojure как можно скорее и в последнюю секунду преобразовать их обратно в Java HashMaps (при подаче их обратно на Java).
person
Brian Carper
schedule
03.11.2009