This is the mail archive of the
kawa@sourceware.org
mailing list for the Kawa project.
Re: syntax-rules problem
- From: Per Bothner <per at bothner dot com>
- To: Sascha Ziemann <ceving at gmail dot com>, kawa mailing list <kawa at sourceware dot org>
- Date: Fri, 10 Mar 2017 11:04:21 -0800
- Subject: Re: syntax-rules problem
- Authentication-results: sourceware.org; auth=none
- References: <CAGUt3y5kG3x462cDKCH4VueT8HLZmcKTvyTZ3thWL-9dFpCvSQ@mail.gmail.com>
On 03/10/2017 01:35 AM, Sascha Ziemann wrote:
I have the following macro.
(define-syntax define-facts
(syntax-rules ()
((_ (name a0 a1 ...) ((v00 v01 ...) (v10 v11 ...) ...))
'(define (name a0 a1 ...)
(conde
((== a0 v00) (== a1 v01) ...)
((== a0 v10) (== a1 v11) ...)
...)))))
This got mangled a bit, but definition is clearly wrong.
I cleaned it up:
(define-syntax define-facts
(syntax-rules ()
((_ (name arg ...) ((value key ...) ...))
(define (name arg ...)
(cond
((and (equal? arg key) ...) value)
...)))))
However, this is still not valid R7RS Scheme:
Pattern variables that occur in subpatterns followed by one or more
instances of the identifier h<ellipsis> are allowed only in subtemplates
that are followed by as many instances of <ellipsis>.
The problem is that arg is singly-nested in the pattern, but
doubly-nested in the template.
Kawa does support an extension for different nesting levels, meant to support
things like (x (y ...) ...) => (((x y) ...) ...). However, in that case the x
varies by the outer "index":
((x0 (y00 y01)) (x1 (y10 y11 y12)))
==> (((x0 y00) (x0 y01)) ((x1 y10) (x1 y11) (x1 y12)))
But for define-facts the single-nested arg needs to vary with the
*inner* index. I.e. you would need Kawa to expand the example to:
==> (((x0 y00) (x1 y01)) ((x0 y10) (x1 y11) (x2 y12))) ; Oops no x2
But Kawa doesn't do that.
A solution that does work uses a list:
(define-syntax define-facts
(syntax-rules ()
((_ name ((value . keys) ...))
(define (name . args)
(cond ((equal? args 'keys) value) ...)))))
(define-facts father-of
(("Abraham" "Ismael")
("Abraham" "Isaac")
("Isaac" "Jacob")
("Jacob" "Benjamin")))
Obviously, Kawa should not throw ArrayIndexOutOfBoundsException,
but should instead report an error. So that is a Kawa bug.
--
--Per Bothner
per@bothner.com http://per.bothner.com/