简体   繁体   中英

What's the equivalent of Java's computeIfAbsent or putIfAbsent in Clojure?

With a map in Java you can write map.computeIfAbsent(key, f) that checks whether the key exists in the map already, and if not calls f on the key to generate a value, and enters that in the map. You also have map.putIfAbsent(key, value) which only puts the value in the map if the key does not already exist in the map.

Ignoring the fact the Java methods also return the value, and instead wanting the new map returned, what would be the equivalent code in Clojure?

The best I've come up with so far is to roll my own with something like

(defn compute-if-absent [map key f]
  (if (key map)
    map
    (assoc map key (f key))))

Is there an alternative to rolling my own?

Clojure maps are immutable so you will always return a new map with updated contents - thus your functions will be always thread safe. It also means that you can't have a global variable holding your map and mutate them in place.

Your implementation of compute-if-absent is almost correct. It will fail for keys that are falsey, for example {false 1} . You need to change your if condition and use contains? instead of key :

(defn compute-if-absent [m k f]
  (if (contains? m k)
    m
    (assoc m key (f k))))

If you do need to have the same behaviour as ConcurrentMap you can just use them using Java interop in Clojure.

Even simpler solution would be to use merge , for put-if-absent :

(merge {key val} m)

Although the end result would be the same for compute-if-absent , the following code would of course compute (f key) regardless of the contents of m :

(merge {key (f key)} m)

If you are trying to implement some form of caching, then you can use clojure's great memoize function.

Example: (def fast-inc (memoize inc))

See: http://clojuredocs.org/clojure.core/memoize

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM