Wednesday, February 23, 2011

An easy puzzle

Suppose I have some code like this:
(defun foo (x)
  (wrapper-macro
    (bar 42 x)))
Where wrapper-macro simply prints ‘Normal exit’ or ‘Throw’ as control returns from bar through foo. (If bar returns normally, all the return values are returned from foo after wrapper-macro prints. If bar exits via a throw, then the throw continues after wrapper-macro prints.)

The challenge: Implement wrapper-macro.

(If you wish, imagine that wrapper-macro simply expands to this:
(defun foo (x)
  (wrapper-function
    (lambda ()
      (bar 42 x))))
and the challenge is to implement wrapper-function.)

4 comments:

Steli said...

(defun wrapper-function (thunk)
(let ((return? nil))
(unwind-protect
(multiple-value-prog1
(funcall thunk)
(setf return? t))
(if return?
(print "Return")
(print "Non-local exit")))))

Btw, if possible, please allow the use of PRE tags in comments in order to display code fragments properly

Jrm said...

I wish I could turn on PRE tags.

If you untabify and replace the spaces with  , you get this:

(defun wrapper-function (thunk)
  (let ((return? nil))
    (unwind-protect
        (multiple-value-prog1
         (funcall thunk)
         (setf return? t))
      (if return?
          (print "Return")
        (print "Non-local exit")))))

ohw0w said...

I might be wrong, but can't you just do it with call/cc and modifying bar function to use continuations?

Jrm said...

ohw0w said...

Can't you just do it with call/cc and modifying bar function to use continuations?

Yikes! I don't think you need to haul out the heavy machinery!