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!