I want to define a trash directory in my user-init-file but I don't know which way to do this is best or most correct. I currently have something like this:

(defvar my-trash-dir
  (expand-file-name ".trash" user-emacs-directory))
(if (not (file-exists-p my-trash-dir))
    (make-directory my-trash-dir))
(setq trash-directory my-trash-dir)

Is this correct? Is there a better way to do this, maybe by using setq or defconst?


If the sole purpose of defining my-trash-dir is to use its value to set the user option trash-directory, then you should just write

(setq trash-directory (expand-file-name ".trash" user-emacs-directory))

or (if you don't mind wasting a millisecond or two at startup) even

(setq trash-directory (locate-user-emacs-file ".trash"))

This is because trash-directory is automatically created for you when the command move-file-to-trash is invoked. Deferring the creation of trash-directory until it is actually needed will even improve your startup time.

If, however, you want to use my-trash-dir as a variable for other purposes, there is nothing wrong with using a plain setq to define it:

(setq my-trash-dir (locate-user-emacs-file ".trash"))
(setq trash-directory my-trash-dir)
(unless (file-exists-p my-trash-dir)
  (make-directory my-trash-dir))

There is almost never a need for users to use defconst, especially given the Emacs philosophy centred around customisability. But there are several advantages to using a defvar:

(defvar my-trash-dir (locate-user-emacs-file ".trash")
  "Personal Emacs trash directory.")

(setq trash-directory my-trash-dir)
(unless (file-exists-p my-trash-dir)
  (make-directory my-trash-dir))
  1. You can associate a docstring with it which will be presented by C-hvmy-trash-dirRET and reduces the need for comments in your code.

  2. Emacs notes the file in which the variable was defined. You can then jump to this location via M-xfind-variableRET or the hyperlinked button in the *Help* buffer.

  3. The byte-compiler is made aware of the variable so that it does not complain, should you want to byte-compile your code. The variable also satisfies special-variable-p, should you ever care about this.

  4. You will be one step closer to achieving Emacs zen[1]. In other words, it is more idiomatic and elegant to define variables prior to their use.

    [1]: This claim is provided "as-is", without warranty of any kind.


I think Basil gave you the best answer, but just for completeness, you can also use let in your example:

(let ((my-trash-dir
       (expand-file-name ".trash" user-emacs-directory))
  (if (not (file-exists-p my-trash-dir))
      (make-directory my-trash-dir))
  (setq trash-directory my-trash-dir))

That will work just fine, but you can simplify it:

(setq trash-dir (expand-file-name ".trash" user-emacs-directory))
(if (not (file-exists-p trash-dir))
    (make-directory trash-dir))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.