Re: Simple symbols as keywords Marc Feeley 09 May 2006 07:31 UTC

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.?