6

I'm confused by the interpretation of ' in the context of lists of symbols.

The problem is that I'd like to check whether a buffer is in one a list of modes, and I'll use the scratch buffer as my example.

(with-current-buffer "*scratch*" major-mode) ;; lisp-interaction-mode
(equal (with-current-buffer "*scratch*" major-mode) 'lisp-interaction-mode) ;; t

So far so good.

(member (with-current-buffer "*scratch*" major-mode)
        '('lisp-interaction-mode) ;; nil

Huh? Trying to simplify this, I ended up with

(member 1 '( 1)) ;; (1) - okay, my list syntax seems correct
(member '1 '( '1)) ;; nil - Why doesn't this work? I think this is the issue

So how can I make a list of symbols, and then check whether a symbol is in there?

Drew
  • 75,699
  • 9
  • 109
  • 225
Squidly
  • 1,499
  • 14
  • 17
  • 1
    You may wish to look at `eq` ["*Return t if the two args are the same Lisp object.*"] as compared to `equal`. And, also have a look at `memq` ["*Return non-nil if ELT is an element of LIST. Comparison done with ‘eq’. The value is actually the tail of LIST whose car is ELT.*"] versus `member`. – lawlist Jul 27 '16 at 16:12

1 Answers1

11

Short version: remove the inner quote.

When you quote a list, it leaves the list's contents unevaluated:

'(a-symbol "a string" (+ 1 1)) => (a-symbol "a string" (+ 1 1))

So: if the list includes symbols, a quoted list will return a list of symbols. Here's the rub: because quoting is so common, there's a special reader syntax for it: '. So:

'kittens        => kittens
(quote kittens) => kittens

So, when you quote a list that includes a quoted symbol, what you're actually producing is:

'('kittens) => ((quote kittens))

when what you really want is:

'(kittens)  => kittens

So your comparison looks like:

(memq 'kittens '(puppies kittens otters))    => (kittens otters)
(memq 'kittens '('puppies 'kittens 'otters)) => nil
Dan
  • 32,584
  • 6
  • 98
  • 168