6

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?

10

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

  • 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 4:32
4

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, privacy policy and cookie policy

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