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