Правильный способ изменить значение на карте на clojure - PullRequest
1 голос
/ 07 марта 2019

Хорошо, я новичок в clojure, это должно быть легко, но для жизни я не могу найти ответ

Допустим, у меня есть эта карта

(def mymap {:a 10 :b 15})

Теперь я хочу изменить значение: a на 5. Я не знаю, как это сделать правильно

Я знаю, update и assoc могут вносить изменения, но они оба получают функцию в качестве последнего аргумента, который относится к значению.Я не хочу этого, я не хочу, чтобы какая-либо функция запускалась, я просто хочу установить: a в 5.

Я думаю, что могу передать анонимную функцию, которая просто возвращает 5 и игнорирует аргумент, но это правильный путь?Не выглядит хорошо для меня

(update mymap :a (fn [arg] 5))

Ответы [ 2 ]

5 голосов
/ 07 марта 2019

assoc не принимает функцию в качестве последнего аргумента;если вы не хотели связать функцию с ключом на карте.(assoc mymap :a 5) делает то, что вы хотите.

Я добавлю, однако, update, который принимает функцию, может использоваться и здесь, в сочетании с constantly или простодругая функция (хотя нет смысла использовать ее над assoc):

; constantly returns a function that throws away any arguments given to it,
; and "constantly" returns the given value
(update mymap :a (constantly 5))

; Basically the same as above
(update mymap :a (fn [_] 5))
0 голосов
/ 21 марта 2019

Имейте в виду, что, поскольку mymap является неизменным, поэтому вызов (update mymap :a (constantly 5)) или (assoc mymap :a 5) вернет карту {:a 5 :b 15}, дальнейшие ссылки на mymap продолжат возвращать исходное значение {:a 10 :b 15}.

Если вы хотите обновить значение для последующих вызовов, вы можете посмотреть на использование атомов.

(defonce mymap (atom {:a 10 :b 15}))

(defn change-mymap [value]
  (swap! mymap #(assoc % :a value)))

Просто убедитесь, что когда вы хотите сослаться на значение атома, вы разыменовываете его символом @. Например: (clojure.pprint/pprint @mymap)

Когда вы вызываете (change-mymap 5), это обновит сохраненное значение mymap, чтобы установить :a на новое значение, оставив любые другие пары ключ-значение на вашей карте в одиночку. Это может быть полезно при отображении обновленного состояния в коде клиент / сервер при ответе на входы из другой системы.

Также обратите внимание, что для вложенных карт, таких как

(defonce nested (atom {:a "a value"
                       :b {:inner "Another value"
                           :count 3
                           :another {:value 5}}}))

Вы можете адресовать конкретное значение в вашей карте с помощью вектора пути. Вы можете использовать функцию get-in для получения значения (get-in @nested [:b :another :value]) и вы можете использовать assoc-in или update-in с путем для обновления значений. Это также позволяет расширить карту. Например, с указанным выше значением вложенности вы можете добавить целый раздел в дерево: (swap! nested #(assoc-in % [:a :b :c :d] "foo")) обновит исходную карту, чтобы она выглядела так:

{:a {:b {:c {:d "foo"}}}
 :b {:inner "Another value"
     :count 3
     :another {:value 5}}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...