[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Choose-Your-Own-Ellipsis

This page is part of the web mail archives of SRFI 46 from before July 7th, 2015. The new archives for SRFI 46 contain all messages, not just those from before July 7th, 2015.



I think the better approach to the nested ellipsis problem is to have
syntax-rules take as an (optional) argument the identifier that you
wish to use to indicate sequences.  E.g.:

  (define-syntax generate-temporaries
    (syntax-rules ()
      ((_ ?origs ?k)
       (letrec-syntax
	   ((aux (syntax-rules ::: () ;; use ":::" as ellipsis
		   ((_ ?temps () ?k*)
		    (apply-syntax-cont ?k* ?temps))
		   ((_ (?temp :::) (?x ?more :::) ?k*)
		    (aux (?temp ::: new-temp)
			 (?more :::)
			 ?k*)))))
	 (aux () ?origs ?k)))))

Alternatively:

  (define-syntax generate-temporaries
    (syntax-rules this-ellipsis-id-is-not-used ()
      ((_ ?origs ?k)
       (letrec-syntax
	   ((aux (syntax-rules () ;; use default "..." ellipsis
		   ((_ ?temps () ?k*)
		    (apply-syntax-cont ?k* ?temps))
		   ((_ (?temp ...) (?x ?more ...) ?k*)
		    (aux (?temp ... new-temp)
			 (?more ...)
			 ?k*)))))
	 (aux () ?origs ?k)))))

This approach doesn't have any problem with matching an ellipsis as
part of a pattern, or with expanding into things like (x . ...), and
it doesn't lead to goofy constructions like ((... ...) (... ...)).  If
you want to nest three levels and be able to indicate a sequence at
any level, just choose three different ellipses.

Furthermore, there's no need to daintily pass ?k around in the example
above.  You can just do:

  (define-syntax generate-temporaries
    (syntax-rules ()
      ((_ ?origs ?k)
       (letrec-syntax
	   ((aux (syntax-rules ::: () ;; use ":::" as ellipsis
		   ((_ ?temps ())
		    (apply-syntax-cont ?k ?temps))
		   ((_ (?temp :::) (?x ?more :::))
		    (aux (?temp ::: new-temp)
			 (?more :::))))))
	 (aux () ?origs)))))

and rely on hygienic renaming to prevent any uses of ::: in ?k from
being confused with the ::: we introduced in the expansion of
generate-temporaries.

I don't know what the best exact syntax for this extension would be.
Here are several possibilities (using the conventions foo* == any
number of foo, and foo? == zero or one foo):

  -- Ellipsis choice before the literals, as above:
    (syntax-rules <ellipsis>? <literals> <rule>*)

  -- After the literals:
    (syntax-rules <literals> <ellipsis>? <rule>*)

  -- On a per-rule basis:
    (syntax-rules literals (<ellipsis>? <pattern> <template>) ...)

  -- After the literals, with an extra "noise word" (like cond's =>)
     to distinguish this from other syntax-rules extensions:
    (syntax-rules <literals> (ellipsis <ellipsis>)? <rule>*)

-al