list and association list cracking macros
Posted: Sun Oct 10, 2004 9:45 pm
I find the following macros useful for working
with symbolic data structures.
The "list-let" macro below allows you to map
the elements of a list to "let" bindings.
The "alist-let" macro below allows you to map association
list values to let-bindings. The key name can be aliased
optionally along with a default value if the association is
not present.
Notice that the lookup returns a singleton value as is otherwise
a list is returned (see ("John Doe")).
While you can use context objects for synthesizing structures
these two macros allow you to to "crack" list structures
conveniently.
with symbolic data structures.
The "list-let" macro below allows you to map
the elements of a list to "let" bindings.
Code: Select all
(define-macro (list-let _values _vars)
(let ((bindings (map (fn (_var _value) (list _var _value))
_vars (eval _values)))
(body (rest (rest (args)))))
(eval (cons 'let (cons bindings body)))))
(list-let '("John Doe" "Acme Widgets" "1-800-123-4567")
(name company phone)
(list company phone name))
;; => ("Acme Widgets" "1-800-123-4567" "John Doe")
The "alist-let" macro below allows you to map association
list values to let-bindings. The key name can be aliased
optionally along with a default value if the association is
not present.
Code: Select all
(define-macro (alist-let _alist _var-alias-defaults)
(let ((_alist (eval _alist)))
(let ((bindings
(map (fn (_var-alias-default , _value _alias _default)
(if (list? _var-alias-default)
(begin
(set '_value (assoc (first _var-alias-default) _alist))
(set '_alias (first (rest _var-alias-default)))
(set '_default (rest (rest _var-alias-default))))
(begin
(set '_alias _var-alias-default)
(set '_value (assoc _var-alias-default _alist))))
(if (list? _value)
(if (> (length _value) 2)
(list _alias (cons 'list (rest _value)))
(list _alias (first (rest _value))))
(list _alias _value)))
_var-alias-defaults))
(body (rest (rest (args)))))
(eval (cons 'let (cons bindings body))))))
(alist-let '((name "John" "Doe") (company "Acme Widgets") (phone "1-800-123-4567"))
(phone (name name1) (country country1 "USA") (company company1))
(list company1 phone name1 country1))
;; => ("Acme Widgets" "1-800-123-4567" ("John" "Doe") "USA")
a list is returned (see ("John Doe")).
While you can use context objects for synthesizing structures
these two macros allow you to to "crack" list structures
conveniently.