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

Opaque thought experiment

To give due consideration to all options, I would like to consider what changes would be required to the API if one were to make syntax objects opaque, with the constraint that procedural-style programming with syntax objects remain easy.

First, an additional primitive a la R4RS appendix:

|  unwrap-syntax : syntax-object -> constant
|                                   | identifier
|                                   | pair-of syntax-objects
|                                   | vector-of syntax-objects

This only exposes the top pair, say. For example, syntax->list can be defined by applying unwrap-syntax recursively.

Issue:  Is wrap-syntax necessary or can we make do with datum->syntax-object?

To make a procedural style of accessing syntax-objects easy, I would require syntax versions of all the R5RS list primitives that make sense


Some of these could have been omitted in favour of just using syntax->list. However, I am not a big fan of the syntax->list style of programming - it incurs an extra code-walking step and it can expose too much if we use it to implement things like cadddr or member.

Issue: Should constructors syntax-cons, syntax-list, syntax-vector be specified and, if so, should they have an extra context argument like datum->syntax-object? or simply use an unspecified context?

Another issue is whether to follow the MzScheme and Psyntax practice of allowing constants, lists or vectors to stand for syntax in certain contexts, for example as an argument to syntax-case or with-syntax. I think this is probably morally wrong and am inclined to disallow it. For example,
the following would be wrong if generate-temporaries returns a list

|(define-syntax letrec0
|    (lambda (x)
|      (syntax-case x ()
|        ((_ ((i v) ...) e1 e2 ...)
|         (with-syntax (((t ...) (generate-temporaries (syntax (i ...)))))
|           (syntax (let ((i #f) ...)
|                     (let ((t v) ...)
|                       (set! i t) ...
|                       (let () e1 e2 ...)))))))))

instead, it should be written to return a syntax object or the conversion
(maybe using datum->syntax-object) should be explicitly written.