8

I have the following code which doesn't work:

(eval-when-compile (require 'cl)) 
(setq mymachine (system-name))
(case mymachine
  ("HP" (setq package-user-dir (concat user-emacs-directory "packages/hp")))
  ("DELL" (setq package-user-dir (concat user-emacs-directory "packages/dell")))
  ("MBP.local" (setq package-user-dir (concat user-emacs-directory "packages/mbp")))
)

There's something happening in the key comparison between the variable mymachine and its three possible values. The following does work, however:

(when (string= system-name "HP")
  (setq package-user-dir (concat user-emacs-directory "packages/hp")))
(when (string= system-name "DELL")
  (setq package-user-dir (concat user-emacs-directory "packages/dell")))
(when (string= system-name "MBP.local")
  (setq package-user-dir (concat user-emacs-directory "packages/mbp")))

But I would prefer, for the sake of legibility, to use the case key selection.

What's happening here?

2 Answers 2

12

cl-case uses eql for comparisons, so string get tested for identity not for equality in the sense of string=. You can fix this by just switching to pcase (or, if you really want to use case, convert to symbols instead: match (intern mymachine) against 'HP, etc.).

2
  • 1
    Thanks. Could you please explain me the difference between case and pcase (the info I've found is a bit technical for me)?
    – NVaughan
    Commented Oct 13, 2016 at 22:23
  • 1
    case uses eql to test equality, whereas pcase will use a variety of different predicates, depending on the data. When a pattern is a string, pcase tests with equal. As well as the respective docstrings, also see C-h i g (cl) Conditionals and (elisp) Pattern matching case statement. Note that pcase provides rather flexible pattern-matching functionality; it's not simply a case alternative.
    – phils
    Commented Oct 15, 2016 at 4:32
5

Your second version would more typically be written as a cond form:

(cond ((string= system-name "HP")
       (setq package-user-dir (concat user-emacs-directory "packages/hp")))
      ((string= system-name "DELL")
       (setq package-user-dir (concat user-emacs-directory "packages/dell")))
      ((string= system-name "MBP.local")
       (setq package-user-dir (concat user-emacs-directory "packages/mbp"))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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