On Saturday, July 16, 2016 at 7:06:10 PM UTC-4, David K. Storrs wrote:
> So, if one should prefer functions, what is a good place to use
> macros?  When people talk about why LISP/Scheme/Racket are the most
> powerful languages, they inevitably mention macros and continuations.
> What is a good use case for macros?

You generally want macros for things that can't be done with functions period, 
for instance a static type checker, pattern matching, a class system with 
static method resolution, making your own language, etc.

Your use case can benefit from macros by having a function that accepts a 
procedure to test and making a macro that constructs the function from a series 
of body expressions. Consider an example of a slightly modified version of your 
throws function:

(throws "Should throw when frobnicating non-widgets"
  exn:fail:contract?
  (lambda ()
    (frobnicate (make-gizmo))))

Notice you have to wrap the "(frobnicate (make-gizmo))" expression in a thunk 
(a function that takes no arguments) so the throws function can control when 
the test expression is evaluated. If you didn't, throws would evaluate 
"(frobnicate (make-gizmo))" as its argument before doing anything and the 
exception would be thrown immediately. If you don't want to have to write the 
wrapper lambda all the time, you can make a macro version of throws that adds 
the lambda for you:

; define-simple-macro is basically define-syntax-rule but using syntax-parse
; instead of syntax-case
(define-simple-macro (throws-macro message:expr matcher:expr body:expr ...+)
  (throws message matcher (lambda () body ...)))

; expands to a call to the throws test function
(throws-macro "Should throw when frobnicating non-widgets"
  exn:fail:contract?
  (frobnicate (make-gizmo)))

The throws-macro *at compile time* transforms the body expression it's given 
into an expression with a wrapper lambda, but *at runtime* the throws function 
does all the actual testing and logic. It's common for macro-writers to keep as 
much logic as possible out of macros and in runtime functions, as that's what 
functions are best at.

One last note - this particular use case for macros can also be achieved with 
lazy evaluation, but macros and lazy evaluation in general have very different 
non-overlapping goals and it's best not to conflate them.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to