suggestion: a shorter convenience form Per Bothner (22 Jun 2006 19:42 UTC)
Re: suggestion: a shorter convenience form Jens Axel Søgaard (25 Jun 2006 08:14 UTC)
Re: suggestion: a shorter convenience form Per Bothner (25 Jun 2006 14:27 UTC)
Re: suggestion: a shorter convenience form Jens Axel Søgaard (25 Jun 2006 15:49 UTC)
Re: suggestion: a shorter convenience form Per Bothner (26 Jun 2006 23:56 UTC)
Re: suggestion: a shorter convenience form Jens Axel Søgaard (27 Jun 2006 09:00 UTC)
Re: suggestion: a shorter convenience form Per Bothner (27 Jun 2006 14:55 UTC)

Re: suggestion: a shorter convenience form Jens Axel Søgaard 24 Jun 2006 15:48 UTC

Per Bothner skrev:

> This has one extra longish keyword, an extra parameter name
> mentioned twice, and an extra level of nesting/indentation.

I need that parameter (at least once) for error reporting.

>> and at
>> the same time still makes it possible to refer to the original
>> input syntax-object of the transformer.
>
> This seems to work:
>
> (define-syntax-case name literals
>   (form expression))
>
> For example:
>
> (define-syntax-case foo ()
>   (form #`(quote form)))
>
> Of course this isn't any better than your "common extension",
> but it's not noticeably worse.  And it does allow convenient
> pattern-matching, about as convenient and compact as Common Lisp's
> defmacro, but allowing multiple "cases".

Consider Kent's implementation of cond in the reference
implementation using the common extension:

   (define-syntax (cond x)
     (syntax-case x ()
       [(_ c1 c2 ...)
        (let f ([c1 #'c1] [c2* #'(c2 ...)])
          (syntax-case c2* ()
            [()
             (syntax-case c1 (else =>)
               [(else e1 e2 ...) #'(begin e1 e2 ...)]
               [(e0) #'(let ([t e0]) (if t t))]
               [(e0 => e1) #'(let ([t e0]) (if t (e1 t)))]
               [(e0 e1 e2 ...) #'(if e0 (begin e1 e2 ...))]
               [_ (syntax-error x)])]
            [(c2 c3 ...)
             (with-syntax ([rest (f #'c2 #'(c3 ...))])
               (syntax-case c1 (else =>)
                 [(e0) #'(let ([t e0]) (if t t rest))]
                 [(e0 => e1) #'(let ([t e0]) (if t (e1 t) rest))]
                 [(e0 e1 e2 ...) #'(if e0 (begin e1 e2 ...) rest)]
                 [_ (syntax-error x)]))]))]))

With define-syntax-case (at least if I understand you correctly)
it becomes:

(define-syntax-case cond ()
   (x (syntax-case x ()
       [(_ c1 c2 ...)
        (let f ([c1 #'c1] [c2* #'(c2 ...)])
          (syntax-case c2* ()
            [()
             (syntax-case c1 (else =>)
               [(else e1 e2 ...) #'(begin e1 e2 ...)]
               [(e0) #'(let ([t e0]) (if t t))]
               [(e0 => e1) #'(let ([t e0]) (if t (e1 t)))]
               [(e0 e1 e2 ...) #'(if e0 (begin e1 e2 ...))]
               [_ (syntax-error x)])]
            [(c2 c3 ...)
             (with-syntax ([rest (f #'c2 #'(c3 ...))])
               (syntax-case c1 (else =>)
                 [(e0) #'(let ([t e0]) (if t t rest))]
                 [(e0 => e1) #'(let ([t e0]) (if t (e1 t) rest))]
                 [(e0 e1 e2 ...) #'(if e0 (begin e1 e2 ...) rest)]
                 [_ (syntax-error x)]))]))]))

>> Refering to the
>> original piece of syntax is often neccessary in order to give
>> error messages in terms of user written syntax.
>
>> I agree with you that the common case should be convenient
>> to write, in this case I'm not sure I think it is worth
>> introducing an extra binding form in order to save relatively
>> few key strokes.
>
> It's not the number of keystrokes that matter, it's the number
> of tokens.  Each token adds to the cognitive load required to
> read a definition.  A programmer familiar with the idiom can
> abstract way the boiler-plate fairly easily, but it is still
> an extra required but useless mental step.

Adding an extra binding form also adds to the cognitive load
for those learning the macro system. For the experienced
macro writer it hardly matters which is used.

--
Jens Axel Søgaard