30

I have the below:

(setq some-variable "less")

I am confused why I have to use the single quote with boundp but not with bound-and-true-p.

Example 1:

(when (boundp 'some-variable) 
   (message "some-variable is %s" some-variable))

Result:

"some-variable is less"

Example 2a:

(when (bound-and-true-p some-variable) ;; Note that using single-quote causes error
   (message "some-variable is %s" some-variable))

Result:

"some-variable is less"

Example 2b:

(when (bound-and-true-p 'some-variable) ;; Note that using single-quote causes error
   (message "some-variable is %s" some-variable))

Result:

and: Wrong type argument: symbolp, (quote some-variable)

  • 5
    It's worth mentioning that setq stands for set quoted, and originally was a macro that expanded into (set 'some-variable "less"). In general, Elisp isn't terribly consistent about quoted vs. unquoted arguments, but any function (not macro) that needs to interact with a variable instead of a value will take its argument quoted (setq being a major exception). – shosti Oct 6 '14 at 16:20
  • 2
    FWIW, bound-and-true-p is a stupid macro. Or rather, its name is stupid. 99.99% of the time when you want to do (and (boundp 'FOO) FOO) you do it to use the value of FOO. You don't do it just to get a truth value. (1) The macro is not needed - the code it replaces is trivial and small. (2) The name is misleading - it is about the variable value, not just testing whether or not the variable value is nil. – Drew Oct 7 '14 at 1:07
23

Short answer

If you are trying to use the variable itself, then use 'some-variable. If you are trying to use the value stored in the variable, use some-variable.

  • boundp uses symbol so it will look at anything that can be bound, including functions. It only cares whether there is a symbol that matches, not what the value is.
  • bound-and-truep uses var and returns the value. In this case you need to provide the value of the symbol to the function. If no symbol var is bound, or the value is nil then it will return nil.

Explanation

For the manual definition please see the manual.

' and (quote ...) both perform the same purpose in emacs-lisp.

The purpose of this is to pass the unevaluated form to the surrounding environment rather than evaluate it.

In your example assume we had the following higher up

(setq some-variable "less") ;; Rather than just 't for clarity

Then the evaluation goes as follows:

(when (boundp 'some-variable) 
   (message "some-variable is %s" some-variable))
;; ==> (boundp 'some-variable) ; 't
;; ==> some-variable is "less"

Whereas without a quote:

(when (boundp some-variable) ;; Note that using single-quote causes error
   (message "some-variable is %s" some-variable))
;; ==> (boundp "less") ; "less" is not a variable. -> Error

Lisp evaluates forms as they are reached, by quoting the form you prevent evaluation so that the actual variable (or list, or function name) is passed.

  • Thanks! Your answer made me jump into the sources of both and helped me come up with the solution. I also updated my question with clear examples. – Kaushal Modi Oct 6 '14 at 13:00
  • 6
    I am glad this helped the op, but it does not actually answer the question (in a way useful for other people having the same question). You only explain that symbols have to be quoted or else they are evaluated. You don't explain why that is not the case for bound-and-truep and the question was why do I have to quote when using boundp but not when using bound-and-truep. – tarsius Oct 6 '14 at 14:45
  • @tarsius I actually include the distinction between boundp requiring a symbol (unevaluated) and bound-and-truep needing the value of the variable in the bullet points (edited in after the initial answer) – Jonathan Leech-Pepin Oct 6 '14 at 14:57
  • I think it is essential to mention why that is so (macros may choose not to evaluate) instead of just mentioning that the doc-string says so. I think this is a very good question and that boundp vs. bound-and-true-p is only an example. What the question really boils down to is the desire to learn about evaluation rules. – tarsius Oct 6 '14 at 15:03
  • @tarsius Aren't evaluation rules explained by this answer? At least basic ones involving only the quote... Your answer is definitely more complete, but it goes far beyond the topic, doesn't it? – T. Verron Oct 6 '14 at 18:03
16

A symbol which is in non-function position is treated as the name of a variable. In (function variable) function is in function-position (after the opening parenthesis) and variable is not. Unless explicitly quoted variables are replaced with their values.

If you were to write (boundp my-variable) that would mean "is the symbol which is stored in the value of variable my-variable bound as a variable" and not "is the symbol my-variable bound as a variable.

So why does bound-and-truep behave differently?

This is a macro and the normal (function) evaluation rules don't apply here, macros are free to decide if and when their arguments are evaluated. What macros actually do is somehow transform the arguments and return the result as a list, which is then evaluated. The transformation and the final evaluation happen at different times, called macro-expansion-time and evaluation-time.

This is what the definition of bound-and-true-p looks like:

(defmacro bound-and-true-p (var)
  "Return the value of symbol VAR if it is bound, else nil."
  `(and (boundp (quote ,var)) ,var))

This uses reader macros which are different from lisp macros (more on that below). To not complicate this further lets not use any reader macros:

(defmacro bound-and-true-p (var)
  "Return the value of symbol VAR if it is bound, else nil."
  (list 'and (list 'boundp (list 'quote var)) var))

If you write

(bound-and-true-p my-variable)

that is first "translated" to

(and (boundp 'my-variable) my-variable)

and then that is evaluated returning nil if my-variable is not boundp or else the value of my-variable (which of course can also be nil).


You might have noticed that the expansion wasn't

(and (boundp (quote my-variable)) my-variable)

as we could have expected. quote is a special form, not a macro or function. Like macros, special forms can do whatever with their arguments. This particular special form simply returns its argument, here a symbol, instead of the variable value of the symbol. That's actually the only purpose of this special form: preventing evaluation! Macros cannot do that on their own, they need to use quote to do so.

So what's up with '? It is a reader macro, which as mentioned above isn't the same as a lisp macro. While macros are used to transform code/data, reader macros are used earlier when reading text in order to transform that text into code/data.

'something

is a short form for

(quote something)

` used in the actual definition of bound-and-true-p also is a reader macro. If it quotes a symbol as in `symbol it is equivalent to 'symbol, but when is used to quote a list as in `(foo bar ,baz) it behaves differently in that forms that are prefixed with , are evaluated.

`(constant ,variable)

is equivalent to

(list (quote constant) variable))

This should answer the question why unquoted symbols are sometimes evaluated (replaced with their values) and sometimes not; macros can use quote to prevent a symbol from being evaluated.

But why is bound-and-true-p a macro while boundp is not? We have to be able to determine if arbitrary symbols, which are not known until run-time, are bound as symbols. This would not be possible if boundp argument was automatically quoted.

bound-and-true-p is used to determine whether a known variable is defined and if so use its value. This is useful if a library has an optional dependency on a third-party library as in:

(defun foo-get-value ()
  (or (bound-and-true-p bar-value)
      ;; we have to calculate the value ourselves
      (our own inefficient or otherwise undesirable variant)))

bound-and-true-p could be defined as a function and require the argument to be quoted but because it is intended for cases where you know upfront what variable you care about a macro was used to save you from having to type the '.

2

From the source code of boundp:

DEFUN ("boundp", Fboundp, Sboundp, 1, 1, 0,
      doc: /* Return t if SYMBOL's value is not void.
Note that if `lexical-binding' is in effect, this refers to the
global value outside of any lexical scope.  */)

boundp expects a symbol as the input. 'some-variable is a symbol to the variable some-variable.

From the source code of bound-and-true-p:

(defmacro bound-and-true-p (var)
  "Return the value of symbol VAR if it is bound, else nil."
  `(and (boundp (quote ,var)) ,var))

bound-and-true-p expects a variable as the input.

Inside the bound-and-true-p macro, it gets the symbol by doing (quote ,var). So if the input is some-variable, (quote ,var) will results in 'some-variable.

But when I give the input 'some-variable to bound-and-true-p, I get the error: and: Wrong type argument: symbolp, (quote some-variable) because the macro is NOT expecting a symbol ('some-variable) at the input.

  • Just a heads-up. ''symbol does make sense. It means (quote (quote symbol)). The reason you get an error is that it’s not a valid argument to boundp. – Malabarba Oct 6 '14 at 13:04
  • @Malabarba Thanks. I have made the correction. – Kaushal Modi Oct 6 '14 at 13:06

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.