[racket] Lesson from the macro exercise
Syntax/parse looks great!
I haven't played with it before, but it I like the approach.
Two questions:
1. What does the error
pattern: attribute has wrong depth (expected 0, found 1) in: d
mean? The program belows gives this error.
2. Why is datum not a pre-defined syntax-class?
/Jens Axel
#lang racket
(require (for-syntax syntax/parse))
;;; SYNTAX
;; <cas-cad-e> ::= (cas-cad-e <val-expr> <case-clause> ...+)
;; <case-clause> ::= [(<datum> ...) <then-expr> ...+]
(define-syntax-parameter break
(λ (stx) (raise-syntax-error 'break "The keywork break was used of
context." stx)))
(define-syntax (casc stx)
(define-syntax-class datum
#:attributes (d)
(pattern d:expr))
(define-syntax-class case-clause
#:attributes (d te)
(pattern [(d:datum ...) te:expr ...+]))
(syntax-parse stx
[(_ value-expr:expr clause:case-clause ... last-clause:case-clause)
(with-syntax ([(label ...) (generate-temporaries #'(clause ...))]
[last-label (generate-temporary)]
[(next ...) (stx-cdr #'(label ... last-label))])
#'(let/ec break1
(syntax-parameterize ([break (make-rename-transformer #'break1)])
(letrec ([label (λ () clause.te ... (next))]
...
[last-label (λ () last-clause.te ...)])
(case ve
[(clause.d ...) (label)]
...
[(last-clause.d ...) (last-label)]
[else (void)])))))]))
2010/10/12 Robby Findler <robby at eecs.northwestern.edu>:
> syntax/parse! :)
>
> Robby
>
> On Tue, Oct 12, 2010 at 3:46 AM, Jens Axel Søgaard
> <jensaxel at soegaard.net> wrote:
>> There have now been several solutions to the macro exercise.
>> Is there a systematic approach of deriving a solution?
>>
>> Here are some steps that could be included in a macro writing recipe.
>>
>> 1. Write some examples with their expected results.
>> Remember corner cases
>> (Get to know the semantics. Are all cases made explicit?)
>> 2. Write some examples of errorneous usage of the macro.
>> (Get to know the syntax. Write down a BNF if it is missing.)
>> Write down the corresponding error messages. Word them
>> in terms of the macro construct.
>> 3. Manually write your examples in code without using
>> the construct you are about to define. If a construct
>> with a similar behavior already exists, use it.
>> 4. Look for a pattern to determine how the macro expands.
>> (It helps to name the various subexpressions.)
>> 5. Implement the macro
>> 5a. Use syntax-case and with-syntax to give names to
>> parts of your input.
>> 5b. Use generate-temporaries to generate new names.
>> 5c. Use define-syntax-parameter and syntax-parameterize if your
>> macro uses a new keyword.
>> 5d. Use raise-syntax-error to signal syntax errors.
>> Use the 3rd argument of raise-syntax-error to make the error
>> location precise.
>> 5e. Use define-for-syntax to define helper functions.
>> 6. Test your macro.
>> Use all examples from 1.
>> Test the case where your macro is used in the output of another macro.
>>
>>
>> Note: syntax-rules macros are not the best choice for informative
>> error messages.
>>
>> --
>> Jens Axel Søgaard
>> _________________________________________________
>> For list-related administrative tasks:
>> http://lists.racket-lang.org/listinfo/users
>
--
--
Jens Axel Søgaard