This site is a static rendering of the Trac instance that was used by R7RS-WG1 for its work on R7RS-small (PDF), which was ratified in 2013. For more information, see Home.

Ticket 83: Auxiliary Keywords

2012-10-05 06:29:45
WG1 - Core
keyword,auxilary
alexshinn
major
arcfide
fixed
source
closed
2010-10-16 00:12:57
task

R6RS and R5RS have different behaviors for auxiliary keywords. Do we use symbolic keywords as in R5RS or do we use auxiliary keywords identifiers and implicit keywords as in R6RS?

Syntaxes like COND and CASE have what are called auxiliary keywords, or auxiliary syntax. TSPL4 calles them keywords, R6RS calls them a combination of literal identifiers and auxiliary syntax depending on what the context of the discussion is. In terms of SYNTAX-RULES, the form has something like this syntax:

(syntax-rules (<literal> ...) <clause> <clause> ...)

Now, in the above, the literals are auxiliary syntax keywords. The rules for matching literals in a SYNTAX pattern are as follows, quoted from the R6RS document:

A literal identifier matches an input subform if and only if the input subform is an identifier and either both its occurrence in the input expression and its occurrence in the list of literals have the same lexical binding, or the two identifiers have the same name and both have no lexical binding.

Now, the TSPL4 has some more to say about this:

Literals serve as auxiliary keywords, such as else in case and cond expressions.

[...]

An input form F matches a pattern P if and only if [...] P is a literal identifier and F is an identifier with the same binding as determined by the predicate free-identifier=?.

This is further described in Section 8.3.

free-identifier=? is used to determine whether two identifiers would be equivalent if they were to appear as free identifiers in the output of a transformer. Because identifier references are lexically scoped, this means (free-identifier=? id1 id2) is true if and only if the identifiers id1 and id2 refer to the same binding. (For this comparison, two like-named identifiers are assumed to have the same binding if neither is bound.) Literal identifiers (auxiliary keywords) appearing in syntax-case patterns (such as else in case and cond) are matched with free-identifier=?.

R6RS further goes on to export, explicitly, the auxilary keywords ELSE and others. This gives some benefits which are actually quite nice in some cases. What this permits is for you to have a number of additiona bindings for that auxiliary keyword, and it also allows you to use keywords internally that are not visible outside of a module or library form. In general, I'm in favor of this form, having used it a bit.

What isn't as fortunate, or what some people don't like, is that it makes the forms of COND and CASE, for example, sensitive to to their lexical environments. So, something like this isn't going to work in the way that some people expect:

(let ([else #f]) (cond [else 'a]))

This will actually evaluate to an unspecified value, because the else there is not the same else as what COND expects. In something like R5RS, this could have returned 'a.

One place where you can use this is if you want to use a different word for else. You can name it to the Chinese word for else, if you so feel like it.

The ticket is basically, do we use the lexical keywords, or symbolic ones? My vote is for the lexical ones.

summaryAuxilary KeywordsAuxiliary Keywords
descriptionR6RS and R5RS have different behaviors for auxilary keywords. Do we use symbolic keywords as in R5RS or do we use auxiliary keywords identifiers and implicit keywords as in R6RS?R6RS and R5RS have different behaviors for auxiliary keywords. Do we use symbolic keywords as in R5RS or do we use auxiliary keywords identifiers and implicit keywords as in R6RS? Syntaxes like COND and CASE have what are called auxiliary keywords, or auxiliary syntax. TSPL4 calles them keywords, R6RS calls them a combination of literal identifiers and auxiliary syntax depending on what the context of the discussion is. In terms of SYNTAX-RULES, the form has something like this syntax: (syntax-rules (<literal> ...) <clause> <clause> ...) Now, in the above, the literals are auxiliary syntax keywords. The rules for matching literals in a SYNTAX pattern are as follows, quoted from the R6RS document: A literal identifier matches an input subform if and only if the input subform is an identifier and either both its occurrence in the input expression and its occurrence in the list of literals have the same lexical binding, or the two identifiers have the same name and both have no lexical binding. Now, the TSPL4 has some more to say about this: Literals serve as auxiliary keywords, such as else in case and cond expressions. [...] An input form F matches a pattern P if and only if [...] P is a literal identifier and F is an identifier with the same binding as determined by the predicate free-identifier=?. This is further described in Section 8.3. free-identifier=? is used to determine whether two identifiers would be equivalent if they were to appear as free identifiers in the output of a transformer. Because identifier references are lexically scoped, this means (free-identifier=? id1 id2) is true if and only if the identifiers id1 and id2 refer to the same binding. (For this comparison, two like-named identifiers are assumed to have the same binding if neither is bound.) Literal identifiers (auxiliary keywords) appearing in syntax-case patterns (such as else in case and cond) are matched with free-identifier=?. R6RS further goes on to export, explicitly, the auxilary keywords ELSE and others. This gives some benefits which are actually quite nice in some cases. What this permits is for you to have a number of additiona bindings for that auxiliary keyword, and it also allows you to use keywords internally that are not visible outside of a module or library form. In general, I'm in favor of this form, having used it a bit. What isn't as fortunate, or what some people don't like, is that it makes the forms of COND and CASE, for example, sensitive to to their lexical environments. So, something like this isn't going to work in the way that some people expect: (let ([else #f]) (cond [else 'a])) This will actually evaluate to an unspecified value, because the else there is not the same else as what COND expects. In something like R5RS, this could have returned 'a. One place where you can use this is if you want to use a different word for else. You can name it to the Chinese word for else, if you so feel like it. The ticket is basically, do we use the lexical keywords, or symbolic ones? My vote is for the lexical ones.
resolutionfixed
statusnewclosed

WG1 voted to leave them unbound.

resolutionfixed
statusclosedreopened

Many new issues pertaining to this ticket have been brought up on the public discussion list, so we are re-opening.

statusreopeneddecided

We voted to make these bound.

statusdecidedwriting
resolutionfixed
statuswritingclosed