## 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 &nbsp;, 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!