reddit / emacs
How can it be that `(print var)` prints a (non-nil) string when `(bound-and-true-p var)` returns `nil`?
graduale · 2022-02-09 22:27
**UPDATED**: I have modified the example to remove any dependency on external packages.
I must be misunderstanding something quite basic here, so I'll ask this question in the hopes that someone can spot the error. I may have to dig deeper otherwise, but I'm somehow thinking the issue is fairly superficial and I'm just not seeing it.
Consider the following function:
```
(defun my/test-let-fun ()
(interactive)
(let* ((var "Hello"))
(print var)
(if (bound-and-true-p var)
(print "Yes.")
(print "No."))))
```
I add this to my config, and the following happens when I call the function.
- In the minibuffer, I see "Hello." followed by "No."
What I take from this is that `(bound-and-true-p var)` must be returning `nil`, since otherwise I should see "Yes." So, I conclude:
- The variable `var` must either be unbound or have a `nil` value during the evaluation of the body of the `let*` expression.
- The variable `var` is bound to a non-nil value, since otherwise, I couldn't get something other than `nil` as the output of `(print var)`.
But these two things cannot be true together!
Am I misinterpreting what's going on?
If I am not, how can this be? Is there some other way to check if the value of a variable is non-nil?
Puzzlingly, if I define the function after starting Emacs (by calling `eval-last-sexp`, say), it works as I expect. (I see "Hello" followed by "Yes.")
zhyang11 · 2022-02-09 22:38
You probably have lexical binding enabled in the init file?
The doc string on `boundp` (which is what `bound-and-true-p` relies on) says:
>(boundp SYMBOL)
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.
So that's probably the cause.
graduale · 2022-02-09 22:51
Thanks! That sounds quite plausible....
I'd still like to understand though why it matters whether the function is defined in my `init.el` or whether it is defined after Emacs initializes...
And, whether or not you can help with *that*, is there something like `boundp` that I can use to test whether 'var' has a value other than `nil`?
graduale · 2022-02-09 23:09
To answer my own question: https://yoo2080.wordpress.com/2013/09/11/emacs-lisp-lexical-binding-gotchas-and-related-best-practices/#sec-4-1
zhyang11 · 2022-02-09 23:11
if you have lexical scoping, the `file` variable will always be bound in that code location. You'll just need to test if the value is `nil`, so it goes like
(if file
(message "non-nil")
(message "nil"))
graduale · 2022-02-10 00:12
Thanks! (This is not the first time I get confused by the lexical vs. non-lexical scope issue. I should really read up on this some more.)
deaddyfreddy · 2022-02-10 11:18
what's the reason to use
>(bound-and-true-p var)
for local bindings?
7890yuiop · 2022-02-10 14:07
> I'd still like to understand though why it matters whether the function is defined in my init.el or whether it is defined after Emacs initializes... (by calling eval-last-sexp, say)
Are you using eval-last-sexp in the same file that has lexical-binding specified at the top?
Or are you using it on a copy of the function in some other buffer without lexical-binding?
If the former, which version of Emacs are you using?
Note also that if you *change* that file-local var, you need to revert the buffer for the change to take effect for subsequent evaluations.
graduale · 2022-02-10 15:29
Probably no good reason. I was looking to test if the variable had been assigned a value, since in the context I was looking to use something like this the `let` bound variable may have been assigned a nil value. So I mindlessly used what was suggested in [this answer](https://emacs.stackexchange.com/questions/3759/test-variable-is-bound-and-non-nil).
graduale · 2022-02-10 15:32
Oooh, I see. It’s another buffer! (*facepalm*). I really need to read up on the lexical/non-lexical distinction.
[deleted] · 2022-02-10 16:02
[deleted]
7890yuiop · 2022-02-10 22:05
Yes, it's a good idea to take the time to understand the distinction.
Nowadays (about a decade after its addition) lexical-binding is extremely prevalent in Emacs Lisp code and so the chances are high that, in any given library you look at, the code will contain both lexically-bound and dynamically-bound variables.
I'd say that if you're at least tinkering with elisp on a regular basis, this is something you want to have a basic understanding of.
In the manual you'd start reading at `C-h i g (elisp)Variable Scoping`. This quote is relevant to your original question:
> Note that unlike dynamic variables which are tied to the symbol
> object itself, the relationship between lexical variables and symbols is
> only present in the interpreter (or compiler). Therefore, functions
> which take a symbol argument (like ‘symbol-value’, ‘boundp’, and ‘set’)
> can only retrieve or modify a variable’s dynamic binding (i.e., the
> contents of its symbol’s value cell).
graduale · 2022-02-10 22:39
That's very helpful, thanks so much once again!