0

Context

In notmuch there is the a function that reads the :search-type property from a list and compares it to a symbol. This comparison is always nil for 'tree' / 'unthreaded, even though saved-search is set correctly (or not - that is the question).

A reduced problem follows below.

; ...
            (cond
             ((eq (plist-get saved-search :search-type) 'tree)
              `(lambda () (notmuch-tree ',query)))
             ((eq (plist-get saved-search :search-type) 'unthreaded)
              `(lambda () (notmuch-unthreaded ',query)))
             (t
              `(lambda () (notmuch-search ',query ',oldest-first)))))
; ...

Reduced Problem

The following minimal test shows the problem. I would expect that this sexp evaluates to 't though it evaluates to nil.

(eq (plist-get `(:search-type 'tree) :search-type) 'tree)

This can be reduced to

(eq (car '('tree)) 'tree)    ; => nil
(eq 'tree 'tree)             ; => t

Work Around

Using intern to create the item in the list works:

(eq (car `(,(intern "tree"))) 'tree)    ; => t

Question

According to my understanding of the eq documentation both 'tree instances in (eq (car '('tree)) 'tree) should be the same object.

Why is this not the case?

Emacs Version

I am using doom (if that is relevant) which compiles the elisp to native code (if that is of any help).

"GNU Emacs 28.0.91 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.20, cairo version 1.16.0) of 2022-01-18"
2

1 Answer 1

3

Short story, you have one extra ' in there which is confusing you.

Long story: The single–quote character precedes any expression which is to be treated literally. The reader turns it into a cons containing the symbole quote and whatever it reads afterwards. So '42 would be read as (quote 42). Later, when what you have read in gets evaluated, the evaluator looks for this quote symbol and removes it, but doesn’t evaluate whatever was left. So if you type tree, it gets read as the symbol tree and the evaluator looks for a variable named tree to find the value. On the other hand, if you typed 'tree then the reader returns (quote tree) and the evaluator unpacks it to just the symbol tree, and then doesn’t do anything else; it doesn’t look for a variable called tree.

Ok, so '('tree) is read as (quote ((quote tree)). The evaluator then unpacks it to just be ((quote tree)). It is a list with one element, and that element is a list with two elements, quote and tree. Now you call car on this list, which gives you the first element. That element is the list (quote tree), which is indeed not eq to the symbol tree that you wanted.

Part of the confusion is that if you evaluate (car '('tree)) in the scratch buffer, it will print out 'tree. It is easy to overlook the extra ' there! It might be easier if it printed out (quote tree) instead, but maybe that would be confusing for other reasons.

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.