Is this a good way to implement let-with?
JavaScript's with statement allows one to modify object members.  This may not be possible for certain types of values (such as strings) using the let-with macro as defined above.



One could generalize let-with to bind values from several association lists.  It could have the form:

(let-with
    ((alist0 (key00 key01 key02...))
     (alist1 (key10 key11 key12...)))
  expr0
  expr1
  ...)


Aside from being more general, the above form closely resembles the let form.  I prefer this over the simpler form, though I would understand if your taste and needs differ.

Here's my implementation of the general form--it uses two auxiliary macros, one to generate two lists (alists and their corresponding keys) and the other to emit the actual code (which looks almost exactly like your definition above):

(define-syntax let-with
  (syntax-rules ()
    ((let-with bindings . body)
     (gen-let-with bindings () () body))))

(define-syntax gen-let-with
  (syntax-rules ()
    ((gen-let-with () alists keys body)
     (emit-let-with-code alists keys body))
    ((gen-let-with ((alist (key)) . rest-bindings) alists keys body)
     (gen-let-with
      rest-bindings
      (alist . alists)
      (key . keys)
      body))
    ((gen-let-with ((alist (key . rest-keys)) . rest-bindings) alists keys body)
     (gen-let-with
      ((alist rest-keys) . rest-bindings)
      (alist . alists)
      (key . keys)
      body))))

(define-syntax emit-let-with-code
  (syntax-rules ()
    ((emit-let-with-code (alist ...) (key ...) (expr ...))
     (let ((key (cond ((assq 'key alist) =&gt; cdr))) ...) expr ...))))


Perhaps there is a simpler definition.  I haven't played with macros in a while. =)



Here are some examples:

(define alist '((first . "Jane") (middle . "Q") (last . "Doe")))
(define blist '((first . "John") (middle . "R") (last . "Lee")))
(define clist '((first . "Jose") (middle . "S") (last . "Paz")))
(define first '((title . "Ms") (suffix . "Esq")))

(let-with
    ()
  "Hello, world!")    ;    =&gt; "Hello, world!"

(let-with
    ((alist (first middle last)))
  (string-append first " " middle ". " last))    ;    =&gt; "Jane Q. Doe"

(let-with
    ((alist (first))
     (blist (middle last)))
  (string-append first " " middle ". " last))    ;    =&gt; "Jane R. Lee"

(let-with
    ((alist (first))
     (blist (middle))
     (clist (last)))
  (string-append first " " middle ". " last))    ;    =&gt; "Jane R. Paz"

(let-with
    ((first (title))
     (alist (first))
     (blist (middle))
     (clist (last))
     (first (suffix)))
  (string-append first " " middle ". " last))    ;    =&gt; "Jane R. Paz"

(let-with
    ((alist (first middle last)))
  (set! first "Rose")
  (string-append first " " middle ". " last))    ;    =&gt; "Rose Q. Doe"

(let-with
    ((alist (first middle last)))
  (string-append first " " middle ". " last))    ;    =&gt; "Jane Q. Doe"


Since let-with expands into a single let, the third-to-last example works.

The last two examples demonstrate the inability to modify a value in its corresponding association list.