[racket] Define-type language form, and macros

From: Jeremy Kun (kun.jeremy at gmail.com)
Date: Sun Sep 11 13:44:16 EDT 2011

Is there an existing Racket analogue for the "define-type" language form
from the PLAI text? Is there a quick way for me to just (require-syntax
define-type) so I can use it in my otherwise purely-Racket programs? Or
perhaps, is there a way for me to look at the original syntax definitions so
I can puzzle over how it's done?

Assuming there isn't, I've been trying to write a macro to just implement
define-type (or something like it) myself, and I've run into a question
about macros.

So say I want to write a macro to expand the following:

(define-type expr
  [num (val) (integer?)]
  [sum (lhs rhs) (expr? expr?)])

; expands into
  (struct expr ())
  (struct num expr (val) #:guard <*some guard function*>)
  (struct sum expr (lhs rhs) #:guard <some* guard function*>))

I have two define-syntaxes that look like

(define-syntax define-type
  (syntax-rules ()
    [(define-type id subtypes ...)
       (struct id ())
       (define-subtypes id subtypes ...))]))

(define-syntax define-subtypes
  (syntax-rules ()
    [(define-subtypes supertype-id) #t] ; base case
    [(define-subtypes supertype-id type1 type2 ...)
         (define-subtype type1 supertype-id) ; define-subtype is defined
elsewhere, and works
         (define-subtypes supertype-id type2 ...))]))

I get an interesting error along the lines of

define-values: illegal use (not at top-level) in: (define-values...

I'm guessing it has something to do with the rule that a define-syntax isn't
allowed to change the surrounding lexical scope, and hence the use of values is
not allowed (even though here it was invoked by another define-syntax...).
But seeing as this is my first foray into macro territory, I can't be too
sure. Can someone verify or deny my suspicion?

Admittedly, my desire to use  values instead of further nesting  begin is
arbitrary, but it would help for me to understand why Racket dislikes the
use of values there, and whether there is a way for me to expand it to a
single begin expression. Perhaps some trickery with turning a list
into a values
expression, and then doing that outside of the (define-syntax
define-subtype) expression? Is there a "safe" way to ensure that only
define-type may call define-subtype, and then the nested define-subtype is
free to break the normal restrictions on syntax definitions?

On another note, is there a nice way for me to print out the literal
expansion performed by define-syntax?

I appreciate the knowledge!

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20110911/f6271d59/attachment.html>

Posted on the users mailing list.