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

Re: Simple symbols as keywords

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

On 4-May-06, at 3:33 AM, soo wrote:

I wonder why a new data type such as keyword object is necessary to
implement named optional parameters.
Aren't simple symbols enough to use as keywords?

I think it is important for the named parameter markers to be easily distinguished from normal parameters, both for the humans reading the code and the compiler and interpreter. Compare

  (buy 'apple 'day 'low 'price 71.89 'qty 1000)


  (buy 'apple 'day 'low price: 71.89 qty: 1000)

In the second case, using SRFI 88 keywords, the reader gets a visual clue that ``apple'', ``day'' and ``low'' are certainly not named parameters, and ``price:'' and ``qty:'' are probably named parameters. Note that there is uncertainty on the nature of the last four parameters but not on the first three. In the first case, which uses plain symbols as named parameter markers, many different combinations are possible.

So it is important for humans reading the code that the named parameter markers are visually different from other parameters: they contain a colon at the end and are self-evaluating.

Keyword objects could be viewed as a distinct type as specified in SRFI 88. They could also be viewed as a subtype of symbols, i.e.

(define (keyword? obj)
  (and (symbol? obj)
       (let ((s (symbol->string obj)))
         (and (> (string-length s) 1)
              (char=? #\: (string-ref s (- (string-length s) 1)))))))

But the ``keyword as subtype of symbol'' view has problems because it does not clearly distinguish keywords and symbols. When is the object ``foo:'' supposed to be treated as a keyword and when should it be treated as a symbol? The human readers of the code, the compiler, the interpreter, the syntax transformers (macros) must all ask this question and their answers may be inconsistent (treating it as a symbol in some cases and sometimes as a keyword). This will make code understanding more difficult than if keywords are a distinct type.

Here's a simple example. Say you write a macro ``defstruct'' to define records which generates the accessor function names automatically by joining the name of the record type and the name of the field. Then consider the definition

  (defstruct foo bar baz:)

This will define, among other things, a function for accessing field ``baz:'' which is bound to the variable ``foo-baz:''. But when you call it like this

  (foo-baz: (make-foo 111 222))

is the compiler supposed to treat ``foo-baz:'' as a self evaluating keyword or as a variable? You could say that the bug is in the definition of the macro ``defstruct'' which was not coded to refuse keywords as field names. Bugs like this may go undetected for a long time to the point of becoming a feature of the macro when the author/ maintainer of the code has vanished. Errors like this are a consequence of not making a clean distinction between symbols and keywords. The situation is very similar for other Scheme objects. Why does Scheme distinguish symbols, characters and strings, why does it distinguish the empty list and #f, etc.?