0

I want to do this.

(let ((myvar "my/variable")
      (myval "Some Value"))
  (setq myvar myval))

The manual method is:

(setq "my/variable" "Some Value")

Here is the full code: As you can see the values are shown in the messages area but they are not set as variables.

(define-error 'my-own-errors   "My Errors")
(define-error 'wrong-arguments "Wrong Arguments" 'my-own-errors)
(define-error 'file-missing    "File Missing"    'my-own-errors)
(define-error 'unknown         "Unknown Error"   'my-own-errors)

(defun my/map--nested-alist (callback NLIST)
  "Call CALLBACK with key value pairs."
  (cond ((stringp NLIST)
         (unless (file-exists-p NLIST)
           (error (signal 'file-missing '(NLIST "was not found.")))))
        ((not (listp NLIST))
         (error (signal 'wrong-arguments '(NLIST "is not a list"))))
        ((listp NLIST) ; Ideally check the list for (dot . notation)
         t)
        (t
         (error (signal 'unknown '(NLIST "was not found.")))))
  (dotimes (x (length NLIST))
    (let* ((group (nth x NLIST))
           (cl (nth 0 (cdr group))) ; cons or list
           (key (car group))
           ;; if list use nth if cons (foo . bar) use cdr
           (val1 (if (consp cl)
                     (car cl)
                   (nth 0 cl)))
           ;; TODO: I could not figure out how to account for cons (dot . notation)
           ;; for now don’t use a '.' in the file, will look at it later.
           (val2 (if (consp cl)
                     (nth 1 cl)
                   (cdr cl))))
      (funcall callback
               `(:key ,key :val1 ,val1 :val2 ,val2)))))

(my/map--nested-alist (lambda (x)
                        (let* ((key   (format "%s" (plist-get x :key)))
                               (myvar (format "%s" (plist-get x :val1))))
                          (progn
                            (message "key is: %s val: %s" key myvar)
                            (setq key myvar))))
                      (with-temp-buffer (insert-file-contents "~/.config/emacs/.data/fakefile")
                                        (read (buffer-string))))

Here is the file in ~/.config/emacs/.data/fakefile

(("my/website"  ("~/Documents/website"  "Website stuff Comment"))
 ("my/journals" ("~/Documents/journals"                     nil))
 ("my/example"  ("~/Documents/example"        "Example Comment")))
ritchie
  • 151
  • 6

2 Answers2

2

intern turns a string into a symbol, then you can use set on that symbol:

(set (intern "var") "some value")
var
⇒ "some value"

or

(setq varname "var")
(set (intern varname) "some value")
var
⇒ "some value"

(setq NAME VALUE) is a contraction of (set 'NAME VALUE) (notice the quote, hence the "q"). setq suppresses the evaluation of its first argument (think about it, most Elisp function would expand NAME to its value as a variable, e.g. (concat var "some string"). In fact, setq isn't a function, it is a special form). You don't need this when you invoke intern, that's why you use set.

Arch Stanton
  • 1,525
  • 9
  • 22
1

The variable needs to be a symbol, not a string: my/variable, not "my/variable".

(let ((myvar 'my/variable)
      (myval "Some Value"))
  (set myvar myval)
  (message "MYVAR: %S" myvar))

Of course, if you want to change a global (i.e., dynamically bound) variable named my/variable then you need to declare it as such:

(defvar my/variable "Some Value")

Or

(defvar my/variable)

(let ((myval "Some Value"))
  (setq my/variable myval))

Or even just this (not inside a let):

(setq my/variable "Some Value")

It all depends on what you want to do. What that is isn't clear.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • That does not work. – ritchie Feb 20 '23 at 00:07
  • @ritchie It *does* work, so... please update your question to show precisely what you're doing (including precisely how you're testing it). – phils Feb 20 '23 at 03:07
  • @phils I updated it with the full example to show how it does not work in my code. Thanks – ritchie Feb 20 '23 at 06:59
  • 1
    It looks like you're still using `setq` rather than `set` as Drew showed you. – phils Feb 20 '23 at 09:44
  • @phils Removing the 'q' and using set only gives me "Wrong type argument: symbolp, "my/website". I understand that set needs the first argument to be a SYMBOL. I don't understand how I can make this work. – ritchie Feb 20 '23 at 18:36
  • 1
    The answer to your question is nevertheless to use `set`. With a variable `VAR` set to a symbol value, `(set VAR VALUE)` will assign `VALUE` to that symbol. Which is what you asked how to do. Anything else is just debugging (in your case `"my/website"` is a string and you need to use a symbol -- Drew *also* pointed this out in the answer). – phils Feb 20 '23 at 21:28
  • @phils set alone was not working I ended up using `intern`, which made the code work as Arch Stanton suggested. Thanks for your help. – ritchie Feb 20 '23 at 21:36
  • 1
    Sure (and that's a very good thing to know), but you can also *not use a string in the first place* if you don't need to be doing that. Is there anywhere that you need the value `"my/website"` as a string? If not, make it a symbol and then you won't need to intern it. – phils Feb 20 '23 at 21:44