list and association list cracking macros

Notices and updates
Locked
jsmall
Posts: 26
Joined: Mon Sep 20, 2004 1:44 am

list and association list cracking macros

Post by jsmall »

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.

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")

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.

Locked