Search code examples
emacsstructureelisp

How to set a single field of a structure (of another structure) efficently?


(cl-defstruct cache
  (owner (make-person))
  (folder (make-hash-table)))

(cl-defstruct person
  (name "")
  (phone ""))

(setq foo (make-cache))

(setf (cache-owner foo) (make-person :name "me" :phone "00000000"))
(let ((folder (cache-folder foo)))
  (puthash "/foo/" "20160201" folder)
  (puthash "/download/foo/" "20160101" folder)
  (setf (cache-folder foo) folder))

This is a minimal example. In this example cache contains two elements. One is another structure and one is a hash table. This is how I change the the individual element currently.

However, I feel that it is super inefficient.

First I need to make a new person even if I just want to change the phone number. It is fine for small structure. However, if person is a bulk structure with many other fields besides name and phone, there will be considerable overhead.

Another way I used is to create a local variable to hold a structure temporarily. Then it is written back to the structure. It seems better but still inefficient as it involves copying the whole structure and writing back the whole structure.

Is there a better way doing the job?


Solution

  • First I need to make a new person even if I just want to change the phone number. It is fine for small structure. However, if person is a bulk structure with many other fields besides name and phone, there will be considerable overhead.

    You don't need to make a new "person" structure just to change the phone number. You can change it with setf:

    (setf (person-phone p) "111111")
    

    Another way I used is to create a local variable to hold a structure temporarily. Then it is written back to the structure. It seems better but still inefficient as it involves copying the whole structure and writing back the whole structure.

    In general, in Emacs Lisp nothing is copied unless you ask for it to be copied. In particular, in the code sample above, the puthash calls manipulate the hash table inside the cache struct, and the final (setf (cache-folder foo) folder) is superfluous.