I wrote the following function to convert nested hash-tables to an a-list:
(defun hash-table->alist* (ht)
(loop for k being the hash-keys in ht using (hash-value v)
collect (cons k
(etypecase v
(integer v)
(hash-table (hash-table->alist* v))))))
It works fine for non nested hash-tables:
> (hash-table->alist* (dict :a 1 :b 23 :c 4))
((:A . 1) (:B . 23) (:C . 4))
But when I use it on nested hash-tables I loose the dotted-pairs on the way:
> (hash-table->alist* (dict :session (dict :user (dict :fullname 23))))
((:SESSION (:USER (:FULLNAME . 23))))
How can I ensure the creation of a dotted pair instead of appending to the front of a list?
I guess you expected:
((:SESSION . ((:USER . ((:FULLNAME . 23))))))
However, if the cdr of a cons cell contains a list, this implies a list structure, which is printed without dot and without nested parentheses. This is how lists are defined: (A . (B))
is (A B)
. So, this is exactly the same structure:
((:SESSION (:USER (:FULLNAME . 23))))
This confusion is unavoidable, because the fact that a given list structure is meant as an alist is not possible to discern from the structure itself.