Recursive Assoc and Subst
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hey all, I've learned a lot from this forum, hoping to learn just a bit more. I've been working on some general routines for drilling into nested association lists of indeterminate complexity, and it seemed like a good excuse to learn a bit about recursion. So far I've gotten a recursive (assoc) to work:
; given a list of keys ordered from the "outside" of a nested assoc list to the "inside", return the (assoc) of the last given key (defun jc:assocr (keys lst / nxt nxtkeys) (if (setq nxt (assoc (car keys) lst)) (if (setq nxtkeys (cdr keys)) (jc:assocr nxtkeys (cdr nxt)) nxt)) )
Now I'd like to get a recursive subst to work, and I'm close, but not quite there.
; subst-r performs a subst on a nested association list. ; given a list of keys, a new value, and a list, it will walk along the tree until runs out of keys, then it will assign the last key the new value, and return the whole list with the new substitution. (defun subst-r (keys val lst) (defun subst-f (keys val lst / nxt nxtkeys newsub) (if (setq nxt (assoc (setq key (car keys)) lst)) (if (setq keys (cdr keys)) (cons key (subst-f keys val (cdr nxt))) (subst (cons key val) nxt lst)))) (subst (subst-f keys val lst) (assoc (car keys) lst) lst) )
As you can see, I was able to get a recursive function to return all but the top level of the list, with the new value substituted in the appropriate level, but I had to wrap the recursive function in order to get the rest of it. I think it could be done by using a global variable to determine whether it's the first level of recursion and rearranging the logic slightly to get that highest-level (subst) into a conditional in subst-f, but that seems inelegant.
The idea is to use nested lists to store and modify per-layout data, i.e., a list of sheet names, each associated with a list of properties I'm using elsewhere in my routines, so that I can e.g. find the manual override for the number assigned to new rev clouds on layout E-100 with a quick (cdr (jc:assocr '("E-100" "RevCloudOverride") *layout_data_list*)), or change its value to "3" with (setq *layout_data_list* (subst-r '("E-100" "RevCloudOverride") "3" *layout_data_list*)).
Thanks!