Showing posts with label macros. Show all posts
Showing posts with label macros. Show all posts

Sunday, September 5, 2010

DrRacket: a dirt-simple exception handler

Exception-handling in Racket is very powerful - but a little overwhelming to me. Suppose you want to do some very very simple exception handling: try something, but if it fails, return an error-value. The way you do this is by using with-handlers:

(with-handlers ([exn:fail? (lambda (exn) 
put-specified-default-here)])
   try-something-here)

There's a lot of goo here, which can be tidied up with some macrology. I give this simple macro, and a couple of examples below:

(define-syntax catch-errors
  (syntax-rules ()
          ((_ error-value body ...)
           (with-handlers ([exn:fail? (lambda (exn) error-value)])
             body ...))))

(catch-errors "Oops" (/ 1 0)) ; "Oops"
(catch-errors "Oops" (/ 6 3)) ; 2
(catch-errors "Oops" (/ 6 3) (/ 16 2)) ; 8

Monday, June 7, 2010

Unhygenic macros in PLT Scheme

You need language "pretty big" for this to work. The following is a demonstration of "anaphoric if"

(defmacro aif (a b c)
`(let ((it ,a))
(if it ,b ,c)))

(aif #f 2 3) ; returns 3
You may need to
(require mzlib/defmacro)

Monday, March 15, 2010

block/return in scheme

Continuations in Scheme - they're not necessarily all that hard. You can use them to prematurely return from a function, as in the following example:

(call-with-current-continuation
(lambda (return)
(begin
(display "One ")
(return #t)
(display "Two ")
#f)))


In the above example, it would print "One ", and bail out by returning the value #t. The remainder of the lambda is never executed. Note that 'return' is a paramater, so you could choose whatever name you wanted to.

It is useful to have some syntactic sugar for the above. A standard name is 'let-cc', defined as follows:

(define-syntax let-cc
(syntax-rules ()
((let-cc variable . body)
(call-with-current-continuation
(lambda (variable) . body)))))


I can then type things more conveniently:

(let-cc return
(display "One ")
(return #t)
(display "Two ")
#f)


Note that my choice of use of the word 'return' is still arbitrary. It's very flexible, because I can have any number of 'named' blocked, and return to whatever part of the program I am interested in.

Suppose I want to give up some flexibility, and that I want 'return' to be part of my syntax. I want a block/return (similar to Lisp's block nil) construction. 'return' means that I want to return from the block. To put it in more concrete terms, I want to be able to write:

(block
(write-line "this is printed")
(return "this is returned")
(write-line "this is never printed"))


A macro which satisfies this is:

(define-syntax block
(lambda (x r c)
(let ((body (cdr x)))
`(call-with-current-continuation
(lambda (return) ,@body)))))


The above was written for Chicken Scheme. Other Schemes might not support it - it's certainly do-able in other schemes - but the implementation might be rather hairier (check out the cls link below, for example).

Further reading: