1

Is it possible to set a symbol that is the value of target symbol within the let bind form? because I am not setting a target symbol, I am not sure how to use let.

I am doing this because I am passing in a string that represents a library's name to generate a function for the library. look at the following link to see how I am using it https://github.com/natask/sexp-string/blob/6b748c133da51a129a465a426ae43b06c3a1331d/sexp-string.el#L189.

starting point, The following is a valid let form

(setq boolean 'dynamic-value)
(print boolean) ;; prints 'dynamic-value
(let ((boolean 'lexical-value))
   (print boolean)) ;; prints 'lexical-value

I am looking to modify lexically the variable boolean from a variable boolean-variable that contains the symbol boolean. boolean-variable is like a pointer to the pointer boolean.

(setq boolean 'first-value)
(setq boolean-variable 'boolean)
(print (symbol-value boolean-variable)) ;; prints 'first-value
(set  boolean-variable 'second-value)
(print boolean) ;; prints 'second-value

what I have,

(setq boolean 'dynamic-value)
(setq boolean-variable (intern-soft "boolean"))
(print boolean-variable) ;; prints 'boolean
(print (symbol-value boolean-variable)) ;; prints 'dynamic-value
(let ((old-boolean-variable (symbol-value boolean-variable)))
          (set boolean-variable 'lexical-value)
          ;; use boolean-variable in a function
          (print (symbol-value boolean-variable)) ;; prints 'lexical-value
          ;; set the value of variable back to previous value
          (set boolean-variable old-boolean-variable))
(print (symbol-value boolean-variable))  ;; prints 'dynamic-value

what I am looking for ,

(setq boolean 'dynamic-value)
(setq boolean-variable (intern-soft "boolean"))
(print boolean-variable) ;; prints 'boolean
(print (symbol-value boolean-variable)) ;; prints 'dynamic-value
(let (((symbol-content boolean-variable) 'lexical-value))) ;; creates a lexical binding to symbol 'boolean
    (print (access-symbol-lexically boolean-variable)) ;; prints 'lexical-value
)
(print (symbol-value boolean-variable)) ;; prints 'dynamic-value

I am not using the variable boolean directly but through a symbol because I am passing in a string something like the following.

(setq boolean-1 'dynamic-value)
(setq boolean-2 'dynamic-value)
(defun my-fun (library)
(setq boolean-variable1 (intern-soft (concat library "-1")))
(setq boolean-variable2 (intern-soft (concat library "-2")))
;;utilize variables
)
(my-fun "boolean")
7
  • emacs.stackexchange.com/tags/elisp/info
    – Drew
    Commented Aug 31, 2021 at 2:25
  • 1
    (1) The question isn't clear to me at all - but that might just be me. I have no idea what you're trying to do or asking. (2) symbol-value is explicitly for dynamically scoped variables. See C-h f symbol-value and (elisp) Accessing Variables.
    – Drew
    Commented Aug 31, 2021 at 2:32
  • 2
    Your example let form is strange/confusing. The whole "save the current value, do a thing, restore the original value" process is robustly taken care of by let -- you don't need to manually save and restore the value; it will be restored once the let-binding ends. Following (let ((foo newvalue)) do-a-thing) the symbol foo will have its original value again.
    – phils
    Commented Aug 31, 2021 at 5:06
  • @drew, I have added more context. In short, lexically utilize a variable behind a variable as supposed to lexically utilizing a variable. Commented Sep 1, 2021 at 21:01
  • I don't see any edit with additional context. The question is still not clear to me.
    – Drew
    Commented Sep 1, 2021 at 23:05

3 Answers 3

1

@phils comment on his answer lead me to think of the following.

(setq boolean 'dynamic-value)
(setq boolean-variable (intern-soft "boolean"))
(print boolean-variable) ;; prints 'boolean
(print (symbol-value boolean-variable)) ;; prints 'dynamic-value
(eval `(let ((,boolean-variable 'lexical-value)) ;; creates a lexical binding
    (print ,boolean-variable) ;; prints 'lexical-value
    (print boolean) ;;prints 'lexical-value
))
(print (symbol-value boolean-variable)) ;; prints 'dynamic-value

strangely, I had to pass environment variables to eval in my case. I had thought eval captures environment variables automatically. https://github.com/natask/sexp-string/blob/9fbacdf620d9077b60270c63eaa6267be75fd855/sexp-string.el#L200

                    (eval
                     `(let ((,boolean-variable (or boolean ,boolean-variable)))
                     (pcase parsed-sexp
                        (`(,_) (->> `,(backquote ,(car parsed-sexp))
                                    backquote
                                    eval
                                    sexp-string-collapse-list))
                        (_ nil))) (list (cons 'boolean boolean) (cons 'parsed-sexp parsed-sexp))))))))
1
  • Just posting this here for posterity/in case anyone arrives here from a search, the likely macro we want here is progv (which is essentially what this answer is doing) with a potential minor bit of wrapping: see emacs.stackexchange.com/questions/8156/… and stackoverflow.com/questions/39377820/… for additional details. Granted, it's mostly to do with dynamically bound variables and not lexical ones, but it should work for what the overall context of this question is about.
    – David
    Commented Sep 27 at 22:35
0

To my knowledge, if you have lexical-binding enabled in your library, then it cannot treat a given name as both dynamic and lexical. If you have declared a variable as dynamic by using defvar, then it will not be treated as lexically-bound. You must pick one or the other. This shouldn't be a problem because, by definition, all of the code which can access a lexically-bound variable is right there in that same block of code (within the scope of the lexical binding), where you can edit it -- so there's absolutely no reason to be using the same name as a dynamic variable.

Alternatively (but again, I don't see why you might need this) you can utilise the fake lexical binding macro lexical-let from the cl library, which was typically used to imitate lexical binding back when Emacs only supported dynamic binding.


I am looking to modify lexically the variable boolean from a variable boolean-variable that contains the symbol boolean. boolean-variable is like a pointer to the pointer boolean.

No, if you are using lexical-binding then this is not possible at all. There's no way of taking a symbol name and using it to find a lexical variable of that name, because the lexical variable isn't associated with the symbol at all.

C-hig (elisp)Lexical Binding explains:

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).

Within the scope of a lexical-binding the only code which can access a given lexical variable is the code which directly references the variable name.

3
  • do you think there is a better way to use variables of a symbol as symbols themselves than creating a backup and reverting as above? Commented Sep 2, 2021 at 5:47
  • I'm still not entirely sure what you're doing, but one option would be to write a lisp macro which generates let bindings for the actual variable names (i.e. the ones generated from the strings) and evaluates the body code within that.
    – phils
    Commented Sep 2, 2021 at 5:58
  • Hi @phils , do you have any comments on my answer below?
    – Ruy
    Commented Dec 2, 2023 at 2:00
0

Experimenting with defmacro I think I found a way of taking a symbol name and using it to find the lexical value of the variable by that name under lexical-binding.

This makes a somewhat unconventional use of defmacro and I cannot say that I fully understand what is going on but I think this might contradict phils's statement in his answer above according to which:

No, if you are using lexical-binding then this is not possible at all. There's no way of taking a symbol name and using it to find a lexical variable of that name, because the lexical variable isn't associated with the symbol at all.

 ;; -*- lexical-binding: t; -*-

 (defmacro access-symbol-lexically (symbol)
   (eval symbol))

 (setq my-var "Dynamical")

 (let ((my-var "Lexical"))
   (print (access-symbol-lexically (intern "my-var")))  ;; prints "Lexical"
   )

The example discussed by the OP is mostly related to accessing a lexical variable but the question itself also mentions setting such variables. Here is a similar trick that does it:

 ;; -*- lexical-binding: t; -*-

 (defmacro set-symbol-lexically (symbol val)
   `(setq ,(eval symbol) ,val))

 (setq my-var "Dynamical")

 (let (my-var)
   (set-symbol-lexically (intern "my-var") "Lexical")
   (print my-var)  ;; prints "Lexical"
   )

Applying this to the question posed by the OP, we have:

 ;; -*- lexical-binding: t; -*-

 (defmacro access-symbol-lexically (symbol)
   (eval symbol))


 (setq boolean 'dynamic-value)
 (setq boolean-variable (intern-soft "boolean"))
 (print boolean-variable) ;; prints 'boolean
 (print (symbol-value boolean-variable)) ;; prints 'dynamic-value

 (let ((boolean 'lexical-value)) ;; creates a lexical binding to symbol 'boolean
 (print (access-symbol-lexically boolean-variable)) ;; prints 'lexical-value
 )
 (print (symbol-value boolean-variable)) ;; prints 'dynamic-value

EDIT: Here are some further examples of the above defmacro trick.

;; -*- lexical-binding: t; -*-

(defmacro access-symbol-lexically (symbol)
  (eval symbol))

(setq my-var "Dynamical")

(let ((my-var "Lexical"))
  (print (access-symbol-lexically (intern "my-var"))) ;; Prints "Lexical" (same as above example)
  (print (access-symbol-lexically 'my-var)) ;; Prints "Lexical"
  (setq s 'my-var)
  (print (access-symbol-lexically s)) ;; Prints "Lexical"
  (let ((s 'my-var) (my-var "Doubly Lexical")) (print (access-symbol-lexically s))) ;; Prints "Doubly Lexical"
  (let ((s 'my-var) ) (print (access-symbol-lexically s))) ;; Prints "Lexical"
  ;; From now on commands do not use above defmacro trick
  (print (eval 'my-var)) ;; Prints "Dynamical"
  (print (eval s)) ;; Prints "Dynamical"
  )
1
  • For sure, macro expansion happens before evaluation, and (let ((my-var "Lexical")) (print (access-symbol-lexically (intern "my-var")))) expands to (let ((my-var "Lexical")) (print my-var)). Remember that macro expansion happens "at some unknown point in the past" compared to evaluation time, so any macro code/usage needs to be doing the right thing at expansion time for its evaluation at some unknown point in the future.
    – phils
    Commented Dec 2, 2023 at 6:34

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.