0

In a related thread https://emacs.stackexchange.com/a/34336/2287, a string (containing JSON data) is converted using json-read-from-string. The value returned in that example looks like this:

    ((1 . [((id . 2)
            (attribute . salutation)
            (displayName . Salutation)
            (category . 1))
           ((id . 4)
            (attribute . middlename)
            (displayName . Middle Name)
            (category . 1))
           ((id . 6)
            (attribute . suffix)
            (displayName . Suffix)
            (category . 1))
           ((id . 8)
            (attribute . city)
            (displayName . City)
            (category . 1))
           ((id . 9)
            (attribute . state)
            (displayName . State)
            (category . 1))
           ((id . 11)
            (attribute . email)
            (displayName . Email)
            (category . 1))
           ((id . 12)
            (attribute . telephone)
            (displayName . Telephone)
            (category . 1))
           ((id . 10)
            (attribute . zipCode)
            (displayName . Zip Code)
            (category . 1))
           ((id . 13)
            (attribute . telephoneExtension)
            (displayName . Telephone Extension)
            (category . 1))
           ((id . 7)
            (attribute . streetAddress)
            (displayName . Street Address)
            (category . 1))
           ((id . 3)
            (attribute . firstName)
            (displayName . First Name)
            (category . 1))
           ((id . 1)
            (attribute . fullName)
            (displayName . Full Name)
            (category . 1))
           ((id . 5)
            (attribute . lastName)
            (displayName . Last Name)
            (category . 1))
           ((id . 14)
            (attribute . notes)
            (displayName . Notes)
            (category . 1))])
     (2 . [((id . 15)
            (attribute . name)
            (displayName . Name)
            (category . 2))
           ((id . 16)
            (attribute . address)
            (displayName . Address)
            (category . 2))
           ((id . 17)
            (attribute . phone)
            (displayName . Phone)
            (category . 2))
           ((id . 18)
            (attribute . email)
            (displayName . email)
            (category . 2))
           ((id . 19)
            (attribute . url)
            (displayName . URL)
            (category . 2))])
    (3 . [((id . 20)
           (attribute . name)
           (displayName . Name)
           (category . 3))
          ((id . 21)
           (attribute . address)
           (displayName . address)
           (category . 3))
          ((id . 22)
           (attribute . county)
           (displayName . County)
           (category . 3))
          ((id . 23)
           (attribute . state)
           (displayName . State)
           (category . 3))
          ((id . 24)
           (attribute . zipcode)
           (displayName . Zip Code)
           (category . 3))
          ((id . 25)
           (attribute . pin)
           (displayName . PIN)
           (category . 3))
          ((id . 26)
           (attribute . longitude)
           (displayName . Longitude)
           (category . 3))
          ((id . 27)
           (attribute . latitude)
           (displayName . Latitude)
           (category . 3))]))

Evaluating the above-mentioned return value with (assoc '\1 ...) produces a cell, the car of which is a symbol whose name is the string "1". The O.P. in that related thread (like myself) experiences difficulty printing the symbol using message [(void-function \,)], and in the comments a solution to accomplish that objective is to use setq: (setq id '\1).

I would like to convert the symbol 1 to a number without using a global variable. I have tried storing that symbol as a let-bound variable and then attempted to change it with setq, however, this does not work (presumably because the variable is only let-bound).


EDIT: To include a minimal working example below:

EXAMPLE:

(let* ((string
"{
  \"access_token\" : \"1234\",
  \"scope\" : \"PlaceTrades AccountAccess MoveMoney\",
  \"expires_in\" : 1800,
  \"token_type\" : \"Bearer\"
}")
       (json (progn (require 'json)
                    (json-read-from-string string)))
       (token-type (cdr (assq 'token_type json)))
       (expires-in (cdr (assq 'expires_in json)))
       (scope (cdr (assq 'scope json)))
       (access-token (cdr (assq 'access_token json))))
  (message "token-type: %s\nexpires-in: %s\nscope: %s\naccess-token: %s"
           token-type, expires_in, scope, access-token)
  access-token)

DEBUGGER:

Debugger entered--Lisp error: (void-function \,)
  ,expires_in
  (message "token-type: %s\nexpires-in: %s\nscope: %s\naccess-tok..." token-type ,expires_in ,scope ,access-token)
  (let* ((string "{\n  \"access_token\" : \"1234\",\n  \"scope\" : \"PlaceTra...") (json (progn (require 'json) (json-read-from-string string))) (token-type (cdr (assq 'token_type json))) (expires-in (cdr (assq 'expires_in json))) (scope (cdr (assq 'scope json))) (access-token (cdr (assq 'access_token json)))) (message "token-type: %s\nexpires-in: %s\nscope: %s\naccess-tok..." token-type ,expires_in ,scope ,access-token) access-token)
  (progn (let* ((string "{\n  \"access_token\" : \"1234\",\n  \"scope\" : \"PlaceTra...") (json (progn (require 'json) (json-read-from-string string))) (token-type (cdr (assq 'token_type json))) (expires-in (cdr (assq 'expires_in json))) (scope (cdr (assq 'scope json))) (access-token (cdr (assq 'access_token json)))) (message "token-type: %s\nexpires-in: %s\nscope: %s\naccess-tok..." token-type ,expires_in ,scope ,access-token) access-token))
  eval((progn (let* ((string "{\n  \"access_token\" : \"1234\",\n  \"scope\" : \"PlaceTra...") (json (progn (require 'json) (json-read-from-string string))) (token-type (cdr (assq 'token_type json))) (expires-in (cdr (assq 'expires_in json))) (scope (cdr (assq 'scope json))) (access-token (cdr (assq 'access_token json)))) (message "token-type: %s\nexpires-in: %s\nscope: %s\naccess-tok..." token-type ,expires_in ,scope ,access-token) access-token)) t)
  elisp--eval-last-sexp(nil)
  eval-last-sexp(nil)
  funcall-interactively(eval-last-sexp nil)
  call-interactively(eval-last-sexp nil nil)
  command-execute(eval-last-sexp)
7
  • What does the JSON string look like? The return value you've posted does not seem to be a legal elisp object.
    – NickD
    Commented Dec 27, 2021 at 21:13
  • ... and when I try to apply json-read-from-string to the JSON string from the linked question, I get: Debugger entered--Lisp error: (json-object-format "," 0) signal(json-object-format ("," 0)) json-read-object() json-read()....
    – NickD
    Commented Dec 27, 2021 at 21:25
  • I corrected your question. There is no backslash in the symbol name. The symbol name is a numeric string (a numeral), such as "1".
    – Drew
    Commented Dec 27, 2021 at 21:40
  • Thank you -- I edited the question to include a minimal working example underneath the original question.
    – lawlist
    Commented Dec 27, 2021 at 22:20
  • I didn't notice @phils's answer. I checked your "minimal working example" and noticed the same thing he did. Went to write it up and saw he already had. Keith, I think you should have been able to figure this one out. ;-) That's what comes from mixing languages - comma-vs-space separators and hyphen-vs-underscore separators.
    – Drew
    Commented Dec 28, 2021 at 3:26

3 Answers 3

1
(message "token-type: %s\nexpires-in: %s\nscope: %s\naccess-token: %s"
         token-type, expires_in, scope, access-token)

You've accidentally added commas as list separators.

As the backtrace shows, the error is because of that:

Debugger entered--Lisp error: (void-function \,)
  ,expires_in
  (message "token-type: %s\nexpires-in: %s\nscope: %s\naccess-tok..."
            token-type ,expires_in ,scope ,access-token)
                       ^^^^^^^^^^^

The commas will be treated as attempts to unquote list elements, as if it were a backquoted list. In that syntax the comma needn't be attached to the form in question; it just says "evaluate the following form" so there can be intervening whitespace. The spacing is then being adjusted to the normal formatting when the debugger prints it back to you; hence token-type, expires_in becoming token-type ,expires_in.

The error is (void-function \,) because the reader internally converts this syntax to (\, expires_in), but as the list was not backquoted it never gets processed in the way that the reader expected it to, and winds up being evaluated as a function call.

(read ",foo")
=> (\, foo)

(read ", foo")
=> (\, foo)
2

You can get the symbol name with symbol-name, which returns a string, and then convert the string to a number:

(string-to-number (symbol-name '\1))
==> 1
5
  • Thank you for idea ... In this particular context, however, I get: (wrong-type-argument symbolp 1)
    – lawlist
    Commented Dec 27, 2021 at 21:00
  • I'm not sure what context you are talking about: if you evaluate the expression in my answer, do you not get the number 1? If that's not what you meant, then showing what expression generated the error message would help.
    – NickD
    Commented Dec 27, 2021 at 21:03
  • FWIW, I get 0, not 1, when I evaluate your sexp. The symbol-name sexp itself returns the string "`1". If I remove your backquote then I get 1.
    – Drew
    Commented Dec 27, 2021 at 21:14
  • Ugh, typo: there should be no backquote.
    – NickD
    Commented Dec 27, 2021 at 21:18
  • Thank you @NickD -- I edited the question to include a minimal working example underneath the original question.
    – lawlist
    Commented Dec 27, 2021 at 22:20
2

I probably don't understand your problem. Your question isn't very clear (what calls to message are you using?).

But if I do understand what you're trying to do, it pretty much amounts to this: You have symbols whose names are numeric strings. E.g. the symbol 1 has name "1". (In Lisp, you can refer to such a symbol literally, using \1, but the backslash is not part of the name.)

(setq foo '((\1 . one) (\2 . two)))

(message "FOO: %S" foo)
(message "FOO: %s" foo)

Neither call to message is a problem. They show this, respectively:

FOO: ((\1 . one) (\2 . two))
FOO: ((1 . one) (2 . two))

If I understand correctly, the second is what you want: to see numbers, not symbols whose names are numeric strings.

And there's no need for any variable, such as foo:

(message "%s" '((\1 . one) (\2 . two)))
2
  • Thank you @Drew -- I edited the question to include a minimal working example underneath the original question.
    – lawlist
    Commented Dec 27, 2021 at 22:21
  • And ... the goal is to not use a global variable, if possible. I.e., only using let-bound variables ...
    – lawlist
    Commented Dec 27, 2021 at 22:25

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.