Dueling beings on a grid I'm remaking an old program of mine in Clojure. It involves "Beings" (generic entities capable of attacking and breeding) let loose in a confined space.

I've noticed a pattern of taking a record, creating a modified version of one of its fields, then "overwriting" the field.

It generally seems to look like:

(defn map-pts [p1 p2 f]
  (let [[x1 y1] p1
        [x2 y2] p2]
    [(f x1 x2) (f y1 y2)]))

(defn add-pts [p1 p2]
  (map-pts p1 p2 +))

(defrecord Being [position, health])

(defn hurt [being damage]
  (let [newHealth (- (:health being) damage)]           ;&lt;&lt;&lt;
    (assoc being :health newHealth)))                   ;&lt;&lt;&lt;

(defn move-by2 [being x y]
  (let [new-position (add-pts (:position being) [x y])] ; &lt;&lt;&lt;
    (assoc being :position new-position)))              ; &lt;&lt;&lt;


(I'm only including the first 2 functions so it's complete).

I decided to write a function to try and limit the boilerplate.

(defn update-with [m k k1-&gt;k2]
  (let [oldValue (get m k)]
    (assoc m k (k1-&gt;k2 oldValue))))


which can be used like:

(defn hurt2 [being damage]
  (update-with being :health
                 #(- % damage)))

(defn move-by [being x y]
  (g/update-with being :position
                 #(add-pts % [x y])))


which I find to be significantly cleaner.

What I want comments on:


Am I thinking about this is the right way? Is this something I should be worrying about, or is this an xy problem?
Is k1-&gt;k2 an appropriate name? It seems like a very self-documenting way of indicating what type of function is needed, but is also "Hungarian", which I know is frowned upon.
This seems like something that would be included in the langage given its simplicity. Does this function already exist?




An example of how it will be used (non-functioning code, since some components aren't yet defined):

(def beings ['(all the beings in the world)])

(map (fn [being]
       (do
         (if (is-contacting-other? being beings)
           (hurt being 20)                        ; &lt;&lt;---
           being))))


In reality, I'll be giving the job of calling hurt to a helper function attack that will decide how much damage to do. This same loop will also handle other things, so it will be a little more complex. This is just a stripped-down example.
I don't think trying to cut down boilerplate like that is too much of an issue.
Normally I would have no problem with using something-&gt;somethingelse for the name of a function that converts from something to something else.  I'm not sure in this case though.  For one thing, I'd assume k means key.  k1-&gt;k2 kind of suggests it's acting on the key, but it's not.  In this case I'd probably just follow the example of the stdlib and call it f.  Makes it obvious it is the function that does the updating.  (Semi-related: you might want to check out the sample chapter of elements of clojure - it goes into naming things in clojure in some depth)
If you're running clojure 1.7+, you've got the update function that does this.