Glad that the title got your attention :D
I have this little snippet that's driving me crazy:
(defvar cache '(nil . nil))
(defun init-cache ()
(setq cache '(nil . nil)))
(defun save (value)
(nconc cache (list value)))
It's the minimum reproducible example out of a cache I'm trying to implement. I would expect the save
to add elements to the list, and the init-cache
to reset the cache.
Instead:
(init-cache) ; cache is (nil)
(save "foo") ; cache is (nil "foo"). So far, so good
(init-cache) ; cache should be (nil), and it's all downward from here…
(save "bar") ; (nil "foo" "bar") damn you, "foo"! Why are you here? Why are you doing this to me?!?!
So from my un-educated point of view, it looks like setq
isn't working! I'm just changing the cdr of cache with nconc
, why can't I change the cache
symbol's value???
So my questions are:
- what's happening?
- the code looks awkward as hell: is there a more idiomatic way (one that works, if possible =) )
Thank you!
push
and then usingnreverse
on it when returning it to reverse the order back to being correct? Assuming the list itself is generated in that function and nothing touches said list before the function is done with it, I see no problem with usingnreverse
. I think there are some cases where destructive functions can be used safely without much reasoning. – Nov 01 '18 at 13:07nconc
probably stems from the fact thatnconc
doesn't alter thecar
of a cons cell; that's why you normally see(setq list-var (nconc list-var other-list)
. – Oliver Scholz Nov 01 '18 at 17:39lexical-binding
file-locally to t and do something with closures, like in Scheme. As to whether that handling of constants is a particulairy of Elisp: I honestly don't remember. Elisp is the only Lisp I've been touching for a long while. But I would think that this is common to most major dialects: It's understandable to be surprised by this, but when you think about it, it's logical:(cons 'x 'y)
is a function call, but(quote (x . y))
is a special form. – Oliver Scholz Nov 01 '18 at 17:43