1

I have a question about how to use interactive to allow the user to identify a desired list element to output.

Let's say I have a variable x assigned to a list structured like this:

(setq x '((y ("y1")
             ("y2")
             ("y3"))
          (z ("z1")
             ("z2")
             ("z3"))))

If I want to retrieve the text "(y1)" from this structure and show it to the user, I know that I can do so by using:

(message (format "%s" (nth 1 (assoc 'y x))))

The problem comes when I try to do the same thing interactively. Let's say I want to write a function that asks the user for the variable name and the desired list (y or z), then retrieves the first associated element:

(defun find-first-associated-value (varname listname)
  (interactive
   "sWhich variable? :
sWhich list? :")
  (message (format "%s" (nth 1 (assoc listname varname)))))

If I try to call this function and fill in the right values, I get the error Wrong type argument: listp, "y".

I can tell the reason this isn't working is that I'm passing strings (varname and listname) to assoc, which expects a KEY and then VALUE. The problem is that I can't figure out how to convert the user-inputted strings collected by interactive to those forms so that they can be understood by assoc. How can I fix this? I'd be very grateful for any help, and I apologize if the question is poorly worded--I'm new to programming in Lisp.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • The problem is that the user inputs the string "y", but your list is using the *symbol* `y`. You could try to convert the user inputted string with its symbol via [`make-symbol`](https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Symbols.html). – Dan May 21 '20 at 13:34
  • 1
    @Dan I expect you meant `intern` ? – phils May 21 '20 at 13:47
  • 1
    elisp tag doesn't apply here. Please, read [elisp tag](https://emacs.stackexchange.com/tags/elisp/info) – Muihlinn May 21 '20 at 15:26

1 Answers1

1

You can use (interactive "S") to obtain a symbol instead of a string.

Regarding your general question, (intern STRING) returns the canonical symbol with the given name.

(eq 'foo (intern "foo"))
=> t

For more information, see C-hig (elisp)Creating Symbols

phils
  • 48,657
  • 3
  • 76
  • 115
  • https://emacs.stackexchange.com/q/39351/454 might be helpful as well. – phils May 21 '20 at 14:06
  • Although this isn't the case, using `make-symbol` (uninterned symbols) helps to avoid name collision. It's implicit in the previous comment link and Dan's original comment but only briefly mentioned in the docs (AFAIK). – Muihlinn May 21 '20 at 15:53
  • Thank you so much for this - it's great to know about `format` (and `make-symbol`). I've tried to incorporate your recommendations into my code, but I must have misunderstood something, because I'm still getting the same error - whether I use `"S"` instead of `"s"` in `interactive` or `(nth 1 (assoc (intern listname) varname)))`, it comes out as `Wrong type argument: listp.` I'm going to keep reading and experimenting and see if I can ask a pertinent question. – olivierestsage May 21 '20 at 16:56
  • I think you need to intern `varname` as well. – Fran Burstall May 21 '20 at 19:17