chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] possible lazy-let macro?


From: Thomas Chust
Subject: Re: [Chicken-users] possible lazy-let macro?
Date: Thu, 17 Nov 2005 17:31:06 -0000
User-agent: Opera M2/8.02 (MacPPC, build 2148)

Am 17.11.2005, 12:17 Uhr, schrieb Daishi Kato <address@hidden>:

[...]
Here is my solution, I hope someone review it.

(use srfi-1)

(define-macro (lazy-let vars . body)
  (let loop ([names (map car vars)] [xpr (cons 'begin body)])
    (cond
     ((list? xpr)
      (let* ([flat (map flatten xpr)]
             [cnt (lambda (x)
                    (length (filter (lambda (y) (memq x y)) flat)))])
        (let-values ([(nms1 nms2)
                      (partition (lambda (x) (> (cnt x) 1)) names)])
          (if (null? nms1)
              (map (lambda (x) (loop names x)) xpr)
              `(let ,(filter (lambda (x) (memq (car x) nms1)) vars)
                 ,(map (lambda (x) (loop nms2 x)) xpr))))))
     ((and (symbol? xpr) (memq xpr names))
      (cadr (assq xpr vars)))
     (else
      xpr))))
[...]

Hello,

this may usually get the job done, but it fails to work in cases where
simple scanning for the occurrence of an identifier is not enough to
see whether the variable is referenced.

For example
  (lazy-let ((a (get-a)))
    (let ((a (get-something-else)))
      (if (condition) a #f)))
always evaluates (get-a) even though it is never needed, because it
macroexpands into
  (begin
    (let ((a (get-a)))
      (let ((a (get-something-else)))
        (if (condition) a #f))))

A more academic example can also generate invalid code:
  (lazy-let ((a (get-a)))
    (let ((a (get-something-else)))
      (do-something-unrelated)))
transforms into
  (begin
    (let (((get-a) (get-something-else)))
      (do-something-unrelated)))

The same type of problem also occurs with this kind of expression:
  (lazy-let ((a (get-a)))
    (if (condition) a 'a))
transforming into
  (begin
    (let ((a (get-a)))
      (if (condition) a 'a)))
where we have evaluation in unnecessary cases again. Or even worse
with another academic example:
  (lazy-let ((a (get-a)))
    'a)
transforming into
  (begin
    '(get-a))

I cannot think of an easy way to fix this without having to make the
macro quite syntax-aware, though. Therefore I would rather suggest to
implement the whole thing for regular let forms in one of the compiler's
optimization passes ;)

cu,
Thomas




reply via email to

[Prev in Thread] Current Thread [Next in Thread]