list and association list cracking macros

Started by jsmall, October 10, 2004, 02:45:46 PM

Previous topic - Next topic

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.




(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.




(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.