Skip to content

Instantly share code, notes, and snippets.

@skeeto
Last active October 9, 2015 10:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skeeto/7edbedfdec3444925451 to your computer and use it in GitHub Desktop.
Save skeeto/7edbedfdec3444925451 to your computer and use it in GitHub Desktop.
A better alist macro
;;; with-alist-access.el --- a better alist macro
;; This is free and unencumbered software released into the public domain.
;;; Commentary:
;; Usage example:
;; (let ((student '((id . 1332412)
;; (name . ((first . "Student")
;; (last . "Example")))))
;; (teacher '((subject . math)
;; (full-name . "Teacher Example"))))
;; (with-alist-access
;; (list student.name.first teacher.full-name)))
;; Result:
;; => ("Student" "Teacher Example")
;;; Code:
(require 'cl-lib)
(defun with-alist-access--transform-symbol (symbol)
"Convert a symbol containing dots into an alist lookup."
(let ((split (mapcar #'intern (split-string (symbol-name symbol) "\\."))))
(if (= 1 (length split))
symbol
(cl-reduce (lambda (object key)
`(cdr (assq ',key ,object))) split))))
(defun with-alist-access--transform-sexp (sexp)
"Transform a single s-expression for `with-alist-access'."
(cons (car sexp)
(cl-loop for arg in (cdr sexp) collect
(cl-typecase arg
(list (with-alist-access--transform-sexp arg))
(symbol (with-alist-access--transform-symbol arg))
(otherwise arg)))))
(defmacro with-alist-access (&rest body)
"Convert all variables of the form foo.bar into an alist lookup on foo.
This macro works on nested"
(declare (indent 0))
`(progn
,@(mapcar #'with-alist-access--transform-sexp body)))
(provide 'with-alist-access)
;;; with-alist-access.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment