Hacker News new | past | comments | ask | show | jobs | submit | zeroyzeroa's comments login

Extracting keys from maps into a definition, with common-lisp (using my macro defk)

(defk login (user pass) (and (string= user "Bob") (string= pass "secret")))

(login (list-to-hash '(user "Bob" pass "secret")) (list-to-hash '(user "Bob" pass "secret"))

Given the following definitions:

(defmacro defk(name h-list &rest body) `(defun ,name (h) (let ,h-list ,@(loop for k in h-list collect `(setq ,k (gethash (quote ,k) h))) ,@body)))

(defun list-to-hash(list) (let ((h (make-hash-table))) (loop for (k v) on list by #'cddr do (setf (gethash k h) v)) h))


It's probably more idiomatic to implement something similar to the with-slots macro by using symbol-macrolet:

  (defmacro with-keys (keys table &body body)
    (let ((gtable (gensym)))
      `(let ((,gtable ,table))
         (symbol-macrolet ,(loop for k in keys
                                 collect `(,k (gethash ',k ,gtable)))
           ,@body))))
This way you can both access and set the keys:

  CL-USER> (defparameter *table* (make-hash-table))
  *TABLE*
  CL-USER> (setf (gethash 'a *table*) 10
                 (gethash 'b *table*) 20)
  20
  CL-USER> (with-keys (a b) *table*
             (list a b))
  (10 20)
  CL-USER> (with-keys (a b) *table*
             (setf a 100
                   b 200))
  200
  CL-USER> (list (gethash 'a *table*)
                 (gethash 'b *table*))
  (100 200)
If you really want to destructure a hash-table when its an argument, it is not much harder to write a new version of defun on top of with-keys or zeroyzeroa's solution (his/hers only takes a single argument).


Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: