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?

Scott Weldon
  • 2,695
  • 1
  • 17
  • 31
NVaughan
  • 1,481
  • 12
  • 27

2 Answers2

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.).

Omar
  • 4,732
  • 1
  • 17
  • 32
  • 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 Oct 13 '16 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 Oct 15 '16 at 04: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"))))
phils
  • 48,657
  • 3
  • 76
  • 115