[racket] Generated symbols

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Sun Jul 3 14:29:03 EDT 2011

Kazimir Majorinc wrote at 07/03/2011 12:07 AM:
> I need review of uses of generated symbols (string->symbol) in Scheme
> (or Racket.) What are typical or interesting uses of these?

I can't think of a good quick answer right now, so I will type a lot 
here, and hopefully something in here will be helpful...

Three of the ways that "string->symbol" gets used:

1. First, note that, in Racket and other languages of Lisp heritage, 
it's commonplace to represent and manipulate data using basic types like 
lists, symbols, numbers, strings, etc.  In these representations, 
symbols are often used instead of strings for things like keywords; this 
can be for linguistic reasons, or for performance reasons (since 
equality comparisons of symbols can be faster than for strings).

For example, some Racket libraries for parsing XML will read from an 
input port and produce a representation in Racket memory using these 
types.  In this Racket representation, XML elements are lists that start 
with a symbol for the element name, and XML CDATA is represented as 
strings.  In the XML representation example, if you're writing a program 
to create this representation, you might, for example, need to transform 
a string from a textual representation of XML into the symbol 
representation that your Racket uses.

For example, Oleg Kiselyov's SSAX XML parser will internally read XML 
like "<p>Hello, <code>world</code>!</p>" as characters and strings, and 
need to use "string->symbol" as part of producing Racket symbols for the 
element names, for a representation like:

    (p "Hello, " (code "world") "!")

You can see here that "p" and "code" are Racket symbols (that's where 
the "string->symbol" was used), and that "Hello, ", "world", and "!" are 
Racket strings.

I think that this is the most common use.

2. "string->symbol" is also sometimes used in the more powerful macro 
transformers, like "syntax-case", for generating new identifiers, for 
variable bindings exposed outside of the macr..  Beginners should not 
use this capability, since they should first learn that generating new 
bindings like this is usually not necessary.  However, this capability 
is available for advanced programmers who know what they are doing and 
have a good reason.

For example, let's say you have a really good reason that you want to 
write a macro called "define-funny-record", for defining a new kind of 
record type, and you want to have example uses of it look something like 

    (define-funny-record ttt (aaa bbb ccc))

where you want "ttt" to be the name of the record, and "aaa" through 
"ccc" to be names of fields.  You also want this macro to expand to 
several procedure definitions, one procedure for accessing each field of 
the record type.  Each of these procedures needs a name, which starts a 
symbol.  So, if you want a name for the procedure that accesses the 
"aaa" field of a "ttt" record, you might want the procedure name 
"ttt:aaa" to be generated, which probably means your macro transformer 
will have a use of "string->symbol" something like this:

    (let ((field-accessor-procedure-name-symbol (string->symbol (format 
"~A:~A" record-name-symbol field-name-symbol))) ...)

Again, I will say that most macros will be written intentionally *not* 
to generate names, but Racket will let advanced programmers generate 
names when they really want to.  I am only mentioning this because 
someone asked about ways "string->symbol" is used, and this is one of 
the ways.

3. In some older Racket libraries based on Scheme libraries, you might 
see things like:

    (define html-right-arrow-symbol (string->symbol "rArr"))

This was done because the programmer wanted the symbol to have those 
exact upper- and lower-case letters, not to be turned by the Scheme 
reader into "rarr" (all lower-case) or "RARR" (all upper-case).

In Racket, this kind of use of "string->symbol" is not necessary, and 
you could just do:

    (define html-right-arrow-symbol 'rArr)

or in Racket you could just put the "rArr" symbol literally wherever you 
wanted it, just like any other symbol, without making this separate 
variable to hold the symbol.

Perhaps other people can think of other uses of "string->symbol" to mention.


Posted on the users mailing list.