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?

Drew
  • 75,699
  • 9
  • 109
  • 225
Daniel
  • 201
  • 2
  • 7
  • The following section and subsections of the Elisp Intro manual may be helpful: [`(info "(eintr) set & setq")`](https://www.gnu.org/software/emacs/manual/html_node/eintr/set-_0026-setq.html). – Basil Mar 20 '20 at 13:01

3 Answers3

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!

Lorem Ipsum
  • 4,327
  • 2
  • 14
  • 35
  • 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. – Lorem Ipsum Mar 19 '20 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 Mar 19 '20 at 16:09
  • Thank you. I put that there b/c I intend to update the answer, but can't at the moment. – Lorem Ipsum Mar 19 '20 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 Mar 19 '20 at 20:16
  • @Daniel, yes, in short, one is a function call, the other sets a variable. I'm not sure what you mean by "but that's incorrect". Can you please say a little more about what you mean? `t` does mean true; evaluate `(if t (message "True!"))`. Everything but `nil` also evaluates as true (try putting different things in place of `t`). `nil` is indeed used for false. Quoting `nil` "returns its single argument, as written, without evaluating it", so `'nil` returns `nil`. (See the links in @Fólkvangr's comment) – Lorem Ipsum Mar 20 '20 at 01:48
  • @LoremIpsum: I see ... My bad. I was playing in the init file and am learning. I found about `nil` and `'nil` and also `t` being true and not really being `toggle`. I got my nose now buried in learning Lisp. Again thank you! :-) – Daniel Mar 20 '20 at 05:42
  • 1
    Note that the statement "`setq` is a convenience function for `set`" is [deadly wrong](https://emacs.stackexchange.com/q/27581/2370). This is also documented in the doc strings I cited in my answer. – Tobias Mar 21 '20 at 06:16
  • @Fólkvangr I didn't want to demote `setq` with my previous comment. I rather wanted to promote it. In programs it does more often the right thing than `(set '... ...)` since `setq` is the right method to set local `let`-bound variables to a new value when lexical binding is active. On the other hand `(set '... ...)` always dynamically binds the value buffer locally. That is almost always wrong. The assigned new value is not visible within the `let` if the dynamical binding is shadowed by a lexical one. The right way to define such a variable is `(defvar-local ...)` on file-global scope. – Tobias Mar 21 '20 at 23:36
  • @Fólkvangr I tested yesterday and was surprised to see that the value of a variable set by `(set '... ...)` was void when tested in a different buffer. Don't know what the heck happened yesterday. My test today proved me wrong. Thanks for the correction. I'll delete my comment and write it anew without the fault. I'll just replace *buffer locally* with *global*. Nevertheless the main statement that with lexical-binding `setq` does more often the right thing because it sets the value of the uninterned symbol remains the same. – Tobias Mar 23 '20 at 20:10
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.

Philopolis
  • 1,094
  • 8
  • 14
  • 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 Mar 19 '20 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.

Tobias
  • 32,569
  • 1
  • 34
  • 75
  • @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 Mar 19 '20 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 Mar 19 '20 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 Mar 19 '20 at 20:01
  • 3
    Perhaps referencing the Elisp intro manual would make more sense here. [(eintr) Using setq](https://www.gnu.org/software/emacs/manual/html_node/eintr/Using-setq.html) – npostavs Mar 20 '20 at 09: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](https://www.gnu.org/software/emacs/manual/html_node/elisp/Setting-Variables.html). – Drew Mar 20 '20 at 15:56
  • @npostavs I plan to improve the answer when I am back from work tonight. I just had not enough time... Maybe, I should have left the field to others from the beginning. – Tobias Mar 20 '20 at 16:38
  • @npostavs I considered referencing `(eintr) set & setq`. Pityingly there is a misleading sentence in the sub-page [Using setq](https://www.gnu.org/software/emacs/manual/html_node/eintr/Using-setq.html): "This is exactly the same as using ‘set’ except the first argument is automatically quoted by ‘setq’." My discussion with LoremIpsum [starting with my first comment to his answer](https://emacs.stackexchange.com/questions/56230/when-use-setq-or-set#comment88225_56245) explains why I think it is misleading. So, I didn't want to promote that info page in my answer. – Tobias Mar 22 '20 at 00:16