1

Suppose one of the customizable variables in a package is var, and its default value is a list, list. I understand I can change the value of var to mylist using

(setq var mylist)

in my init.el.

Suppose though that I have a function fun and I want the value of var to be the result of applying fun to list. Can I simply do this?

(setq var (fun var))

I've done it and it seems to work as intended, but I want to make sure this is a good idea.


EDIT: My question was not very clear, so let me clarify the sort of thing I was worried about (this may be redundant in light of my comment to this answer by Drew. Suppose I add

(setq var (fun var))

to my init.el. How do I ensure that the default value of var has already been set when that line gets evaluated? Should I put this inside a with-eval-after-load? And how do I ensure that M-x load-file ~/.emacs.d/init.el won't result in var being set to the value of (fun (fun var))? Should I instead add the above line to something like emacs-startup-hook or after-init-hook?

I'm currently using a line in my init.el like the above for setting a variable to a value as a function of its default value. I'm relying on use-package, and in order to ensure that the default value of the variable had been set I had to put that line in the :config section of the relevant package, rather than in the :custom section (without setq). Also, the function I am currently using has the nice feature that (fun (fun var)) yields the same output as (fun var). So I have managed to get around both of my concerns.

Still, this seemed like an opportunity to try to understand how to do what I'm trying to do even if I'm not using use-package and if I have a function that's not idempotent.

apc
  • 309
  • 2
  • 8
  • 1
    You might find the [Programming in Emacs Lisp](https://www.gnu.org/software/lispintro/) manual a useful introduction to Lisp in general and Emacs Lisp in particular. – NickD Sep 17 '20 at 21:59
  • 1
    `with-eval-after-load` is the right approach for ensuring that `var` has been defined before you try to use it. Ensuring that you're only ever manipulating its *default* value is harder. If it's a `defcustom` then [you do have access to its standard value](https://emacs.stackexchange.com/a/3024/454), but this is not the case for `defvar`, so you would need to capture and store that value yourself before you changed it (notwithstanding that something else might already have gotten in ahead of you). – phils Sep 19 '20 at 02:42
  • @phils That's exactly what I needed! Thanks very much. So, I could just do `(setq var (fun (eval (car (get 'var 'standard-value)))))` to accomplish what I want, as long as `var` is introduced with a `defcustom`. I will accept this if you want to put it as an answer. – apc Sep 20 '20 at 01:45

1 Answers1

1

Yes. setq sets a variable to whatever value is returned by the second argument.

(setq VAR VALUE) sets variable VAR to whatever VALUE is, and the second argument, VALUE is always evaluated.

(The first argument, VAR, is never evaluated. For a function that evaluates both args, see set.)

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Thanks (again!) for your helpful answer. One thing I was worried about was the fact that `var` may not yet have been assigned a value by the package. Another was that I didn't know whether e.g. reloading my `init.el` file would result in `var` being changed in a non-desirable way, since it might result in `var` having its value now be the result of applying `fun` to the result of applying `fun` to the default value of `var`. Does that make sense? Should I not worry about any of this? – apc Sep 18 '20 at 01:58
  • `C-h f defvar`. Use `defvar` to set a global variable once. Subsequent evaluation of `defvar`s for that variable have no effect. `setq` always updates an existing variable or initializes one that's never had a value. – Drew Sep 18 '20 at 02:28