9

I tried to find an answer to this seemingly simple question, but the swamp (internet) is a big place.

In the emacs init file in one case I use: (show-paren-mode t)

In another case I use: (set 'inhibit-startup-message t) or (setq inhibit-startup-message t)

Why do I need to use setq in one case to set a Boolean?

1

3 Answers 3

8

In the emacs init file in one case I use: (show-paren-mode t)

show-paren-mode is a function. It accepts t as an argument. Using C-h f show-paren-mode, the description says,

With a prefix argument ARG, enable Show Paren mode if ARG is positive, and disable it otherwise.

Behind the scenes, t is used as a toggle for a mode (some set of behaviors). This call is not setting a variable (explicitly, anyway).

In another case I use: (set 'inhibit-startup-message t) or (setq inhibit-startup-message t)

setq is a convenience function for set.

In Lisp, broadly speaking, there is code and there is data. However, code may be interpreted as data using quoting. The interpreter does not work directly with the source code but with Lisp objects. At a high level, the programmer writes the source code using symbols and lists as well as other data structures like vectors. At a low level, Emacs Lisp subroutines (a.k.a. built-in functions) generate and manage objects: data types and instructions.

To understand this, let's walk through how the statement (set 'inhibit-startup-message t) is interpreted. Note this is not exactly how it works; some details are omitted to avoid getting too far into the weeds.

Okay, let's go into the weeds a little bit. Lisp works with symbols. A symbol is kind of like a container for a variable part and a function part. A symbol has a name and when that name is referenced, depending on the context, the Lisp interpreter knows whether to use the variable part or the function part. To be clear, the symbol is the "word on the page" (the source code) whereas the meaning of the "word on the page" is the variable part (any Lisp object) or the function part (a Lisp function object).

                            +----------------+---------------+
 symbol (word on page) ---> | variable part  | function part |
                            +----------------+---------------+

                            +----------------+---------------+
 foo                   ---> | "bar"          | do some thing |
                            +----------------+---------------+

For example, we might have a symbol foo. The symbol is the "word on the page" f-o-o. As a variable, it contains the string "bar". As a function, it does some action like, printing a message or turning on the coffee maker.

Okay, that's enough of getting into the weeds. How does the Lisp interpreter understand (set 'inhibit-startup-message t)?

Say you put your cursor to the right of the right paren and press C-x C-e (eval-last-sexp). This evaluates the previous expression. The Lisp interpreter goes to the start of the expression, the left parens. It says, "Okay, I've got a list here. That's the beginning of a lisp statement." The interpreter will continue reading until the right paren, at which point it will try evaluating.

The interpreter then sees the set symbol. It says, "I see a symbol here, but what does it mean?" Since there is no quote preceding the set word, the interpreter understands it to be a function. Indeed, the first symbol in a list is interpreted as a function name. Looking at C-h f set, the set function accepts a SYMBOL and a NEWVAL.

The next item is 'inhibit-startup-message. Since this is preceded by a quote, the interpreter uses the same symbol inhibit-startup-message.

Therefore, the program can act on the symbol itself (the program can modify this object). The symbol can thus define its function (maybe void?) or its value in the code, e.g. a counter indicates a change in value. The quoted symbol can be passed as an argument to a function to create code at runtime (evaluated as a variable or a function). Otherwise, without the quote, the symbol is evaluated as a variable so the real argument is the variable's value. Keep in mind that a symbol is a kind of placeholder.

The t is then read. Since this is not quoted, t is understood to be a variable. In this case, t is a specific symbol that evaluates to itself (the evaluation returns the same object).

Finally, the right paren is met, and the whole statement is evaluated. Remember, the set function takes two arguments, SYMBOL and NEWVAL. The SYMBOL argument is inhibit-startup-message and the NEWVAL argument is t, which evaluates to t. The set function does its black-box behavior and the symbol inhibit-startup-message gets t for its variable part.

In the case of (setq inhibit-startup-message t), the interpreter knows that because setq is being used, the next symbol it encounters refers to the same "symbol object". No need to quote it! Now that's convenience!

9
  • My self-assessment is "advanced beginner", so I assumed there would be some errors. Thank you for pointing them out and for providing guidance, for @Daniel's sake and my own. Commented Mar 19, 2020 at 15:26
  • Please remove this, and incorporate what's needed into the answer itself: the following contains some inaccuracies. See comments. Comments can be removed at any time. Questions and answers should stand on their own, without needing comments.
    – Drew
    Commented Mar 19, 2020 at 16:09
  • Thank you. I put that there b/c I intend to update the answer, but can't at the moment. Commented Mar 19, 2020 at 17:54
  • 2
    @LoremIpsum: Thanks for the work. So in short one is a function call and the other is setting a variable. I also though that t stood for true, but that's incorrect and setting false is actually done by stating 'nil with the quote. LISP is a bit confusing, but you certainly pushed me into a direction.
    – Daniel
    Commented Mar 19, 2020 at 20:16
  • 1
    Note that the statement "setq is a convenience function for set" is deadly wrong. This is also documented in the doc strings I cited in my answer.
    – Tobias
    Commented Mar 21, 2020 at 6:16
7

As I understand it, Daniel's question was not only about the difference between set and setq, but also about why to use set/setq in some (and not all) cases. The fundamental difference between the two examples you provide is the following:

  1. To inhibit the startup message, you need to set the variable inhibit-startup-message to t. You can do this by using one of two equivalent instructions, as explained by Tobias:

    (setq inhibit-startup-message t)
    ;; or:
    (set 'inhibit-startup-message t)
    
  2. To activate the minor mode show-paren-mode, you need to activate the corresponding function show-paren-mode:

    (show-paren-mode t)
    

    In the latter case, you must not use an expression such as (setq show-paren-mode t), because show-paren-mode is not a variable you can set to a given value: it is a function.

In order to know whether you are dealing with a function or a variable, you have to read the corresponding help page.

1
  • I see .. Correct me if I am wrong, but if I understand this correctly then in one case I set a variable and in the other case I set a "functionality" which in this case is a minor mode. So the latter is basically an object or what others mentioned a symbol?
    – Daniel
    Commented Mar 19, 2020 at 18:39
6

Emacs comes with the Elisp manual. Try C-h i m Elisp RET. Type i setq RET to go to the place where the index topic setq is explained.

There you find the following info:

Special Form: (setq [symbol form]...) This special form is the most common method of changing a variable’s value. Each SYMBOL is given a new value, which is the result of evaluating the corresponding FORM. The current binding of the symbol is changed.

‘setq’ does not evaluate SYMBOL; it sets the symbol that you write. We say that this argument is “automatically quoted”. The ‘q’ in ‘setq’ stands for “quoted”.

There is mentioned that SYMBOL is not evaluated. Therefore, you do not need to quote it.

-- Function: (set symbol value) This function puts VALUE in the value cell of SYMBOL. Since it is a function rather than a special form, the expression written for SYMBOL is evaluated to obtain the symbol to set. The return value is VALUE.

When dynamic variable binding is in effect (the default), ‘set’ has the same effect as ‘setq’, apart from the fact that ‘set’ evaluates its SYMBOL argument whereas ‘setq’ does not. But when a variable is lexically bound, ‘set’ affects its dynamic value, whereas ‘setq’ affects its current (lexical) value. *Note Variable Scoping::.

set evaluates SYMBOL. This is useful if you have stored the actual symbol to be set, say SYM, in a variable, say VAR. Then you use

(set VAR VAL)

to store VAL in the value cell of SYM.

7
  • @Fólkvangr: I disagree, in general. There are new concepts, if one is a complete newbie. But there are references to the doc, where those are explained. However, the answer could be improved, I think, by adding a summary at the beginning: Use set if you need to evaluate an expression to get the symbol whose value as a variable you want to set. Use setq if you already know which variable to set.
    – Drew
    Commented Mar 19, 2020 at 16:07
  • @Tobias: Thanks a ton for pointing out the manual to me green-bean. Very useful to read on the difference on set and setq. It is only part of my question though. Where set/setq operate on a symbol, what is the show-paren-mode.
    – Daniel
    Commented Mar 19, 2020 at 18:54
  • @Tobias: would you say it is a bit like setting a variable directly or setting an object property where the object has to be fetched in the evaluation process? My background is PHP for the record.
    – Daniel
    Commented Mar 19, 2020 at 20:01
  • 3
    Perhaps referencing the Elisp intro manual would make more sense here. (eintr) Using setq
    – npostavs
    Commented Mar 20, 2020 at 9:25
  • @Fólkvangr: (1) Start with the Info manual, to learn about Info. (2) As this answer says explicitly, in the Elisp manual, i setq RET takes you directly to node Setting Variables.
    – Drew
    Commented Mar 20, 2020 at 15:56

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.