4

I work with ELisp hash-table and I would like to have a better printed representation of it. I'm on Emacs version 24.5.1. When I create a hash-table

(setq table (make-hash-table))
(puthash :name "john" table)
(puthash :age 31 table)

I get something like:

#s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data
          (:name "john" :age 31))

But I just want to have the content (i.e. data) of my hash-table.

(:name "john" :age 31)

I know that you can have a specific printed representation in Common Lisp thanks to the print-object method. Even the pretty printer pp displays the hash-table metadata. Any idea?

Thanks

4
  • If you just want to print it, you could use something like: (json-encode #s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data (:name "john" :age 31))).
    – wvxvw
    Oct 12, 2016 at 20:59
  • See this emacs-devel thread.
    – Drew
    Oct 12, 2016 at 21:25
  • There is no way to change the printed representation of a type in Emacs Lisp. Unless of course, you implement a language on top of it with your own reader and printer and stuff...
    – wasamasa
    Oct 13, 2016 at 7:32
  • Thanks for your answers. json-encode is a pretty good idea. In order to get a more readable ELisp structure, I can do (json-read-from-string (json-encode table)). It works well, even if this is not the most effective way. I also take a look to ht.el and I can have a nice list of pairs (:name "john") thanks to a (ht-items table).
    – dag
    Oct 13, 2016 at 9:04

3 Answers 3

2

Note: this solution is just for pretty visualization of a complex hash-table and can't really be read back

Another option would be to use the yaml.el package (https://melpa.org/#/yaml) which provides the function yaml-encode. Here is an example of its usage:

(let ((h (make-hash-table :test 'equal))
      (nested (make-hash-table :test 'equal)))
  (puthash 'a [1 2 3] nested)
  (puthash 'b [3 4 5] nested)
  (puthash [7 8] 'x nested)
  (puthash 'nested-map nested h)
  (puthash 'another-key 7 h)
  (puthash 'favorite-numbers '(1 2 12 29 40) h)
  (puthash 'state "Arizona" h)
  (yaml-encode h))

produces the following YAML:

nested-map: 
  a: [1, 2, 3]
  b: [3, 4, 5]
  [7, 8]: x
another-key: 7
favorite-numbers: [1, 2, 12, 29, 40]
state: Arizona

Disclaimer: I'm the author of yaml.el

2

EDIT

An even easier/more straightforward alternative to my original answer is to just use maphash:

(let (plist)
  (maphash (lambda (k v)
             (push k plist)
             (push v plist))
           table)
  (pp (nreverse plist)))

END EDIT

I would suggest to just reformat the pp output yourself, e.g. using:

(defun pp-hash (table)
  (let ((data (nthcdr 2 (nbutlast
                         (split-string (pp-to-string table) "[()]")
                         2))))
    (princ (concat "(" (car data) ")"))))

You can now print your table using (pp-hash table).

NOTE that the Emacs manual defines the printed representation of an object as the output generated by the Lisp printer (the function prin1) for that object (i.e. a syntax that is accepted by the Lisp reader, read. See also @wasamama's comment)

1
  • Or similar to the comment by @dag you could replace the princ by read. Aug 9, 2021 at 20:03
-1

I was able to pretty print a hash table by executing the following

ELISP> (json-read-from-string (json-encode org-id-locations))
((40a4d409-c922-4cc6-875f-15a711bf7f78 . "~/e/main.org")
 (f7d35e36-8485-41bb-b499-af9371b240c1 . "~/e/main.org")
 (71205b41-0d40-4846-adb8-8ada7381160e . "~/e/main.org"))

Where ord-id-locations is a hash table (as can be seen below)

ELISP> (type-of org-id-locations)
hash-table

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.