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

dag
  • 141
  • 2
  • 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 '16 at 20:59
  • See [this](http://lists.gnu.org/archive/html/emacs-devel/2011-04/msg00251.html) emacs-devel thread. – Drew Oct 12 '16 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 '16 at 07: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](https://github.com/Wilfred/ht.el) and I can have a nice list of pairs `(:name "john")` thanks to a `(ht-items table)`. – dag Oct 13 '16 at 09:04

3 Answers3

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)

dalanicolai
  • 6,108
  • 7
  • 23
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

Zac Romero
  • 175
  • 5
-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
rdrg109
  • 386
  • 1
  • 10