Opened 7 months ago

Last modified 6 months ago

#1351 new defect

syntax-rules has difficulty handling ellipsis in some cases?

Reported by: sjamaan Owned by: sjamaan
Priority: not urgent at all Milestone: someday
Component: expander Version: 5.0
Keywords: syntax-rules Cc:
Estimated difficulty: easy

Description (last modified by sjamaan)

As reported by Sascha Ziemann, this macro application fails while it ought to succeed:

(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) ...)
          ...)))))

The failing application:

(define-facts (fathero f c)
  (("Abraham" "Ismael")
   ("Abraham" "Isaac")
   ("Isaac"   "Jacob")
   ("Jacob"   "Benjamin")))

A few other Schemes have difficulty with it, notably Chibi, Gauche, Scheme48 and Gambit (the former two returning the wrong result and the latter two giving an error). Racket, MIT, Ikarus and Guile work fine.

Change History (3)

comment:1 Changed 7 months ago by sjamaan

  • Description modified (diff)

comment:2 Changed 7 months ago by sjamaan

Here's a slightly different but simpler case that exhibits the same error:

(define-syntax foo
  (syntax-rules ()
    ((_ (x ...) ((y ...) ...))
     '(print (x y ...) ...))))

(foo (1 2 3) ((a b) (c d)))

Error: (map) during expansion of (foo ...) - lists are not of same length: (())

Another invocation of the same macro for which we should also give an error, but we silently return the wrong result:

(foo (1 2) ((a b) (c d) (e f))) => (print (1 a b) (2 c d))

Racket and Guile give an error when you try to invoke this macro with unbalanced argument counts, Chibi and Gauche always stop early.

It looks like this is due to how "map" works: It doesn't (always) check the list lengths, it either stops on the shortest list (giving this comment's problematic behaviour) or it gives an error that the lists aren't the same length (giving the error in the ticket body).

Before walking the macro's invocation expression the lists should be checked for length, so we can give a nicer error, and avoid silently dropping lists. However, that won't solve the problem in the ticket body that it is generating the "wrong" expression, for some value of wrong.

Last edited 7 months ago by sjamaan (previous) (diff)

comment:3 Changed 6 months ago by sjamaan

  • Estimated difficulty changed from hard to easy
  • Priority changed from major to not urgent at all
  • Version changed from 4.12.0 to 5.0

Alex Shinn pointed out on chicken-users that the macro itself is disallowed by the spec.

So it appears that we only need to improve error detection and handling in this case.

Note: See TracTickets for help on using tickets.