[racket] Unexpected error extracting value from request bindings.
You are correct that it is effectively black magic, in that you probably
don't need to know about it right now. Only a small percentage of
Racket programmers will ever need to know about it.
When you look at the "reference/symbols.html" page of Racket
documentation, pretend that you don't see anything other than "symbol?",
"string->symbol", and "symbol->string". You will probably use those
three procedures a lot, and you will probably never need to use anything
else on that page.
I suggest making your own somewhat "gensym"-like procedure, tailored to
your needs. If you're, say, generating symbols that must be unique only
within a single generated Web page, write your own procedure to support
doing exactly that. In this procedure, you will naturally use
"string->symbol", and consequently procedures like "eq?", "memq", and
"assq" will simply work like you'd expect (no black magic). As an
example, here's one utility procedure you might write, which itself
produces a "gensym"-like procedure that you can use in the context of,
say, generating a single Web page:
;; Definition of your utility procedure:
(define (make-serially-numbered-symbol-maker prefix-string)
(let ((serial-number 0))
(lambda ()
(let ((last-serial-number serial-number))
(set! serial-number (+ 1 serial-number))
(string->symbol (string-append prefix-string
(number->string
last-serial-number)))))))
;; Example use of that utility procedure:
(let ((my-make-symbol (make-serially-numbered-symbol-maker "foo-")))
(list (my-make-symbol)
(my-make-symbol)
(my-make-symbol)))
;;==> '(foo-0 foo-1 foo-2)
If a procedure that produces new procedures seems a little too
fancy-pants right now, you can do a similar thing in a block of your
code that needs the symbols made, without the part about producing a
procedure. The nice thing here about a procedure that produces a new
procedure is that it's a good way to put this code into a reusable
library, rather merely having a code pattern that you retype or
copy&paste every time you need to do a similar thing.
Esoterica #1: If you wanted the produced symbol maker (in the example
above, a particular "my-make-symbol" value) to be callable from multiple
threads simultaneously, then the code should be modified to use a
semaphore, so that the setting of "last-serial-number" and the
incrementing of "serial-number" happens in a mutex block. (The
"string->symbol" part could be left out of the mutex block, to increase
parallelism.) But you probably don't want to be calling the same
"my-make-symbol" from multiple threads simultaneously, anyway, so I
didn't complicate this illustration with a semaphore.
Esoterica #2: You'll see functions like "gensym" and "gentemp" in some
old Lisp dialects, and they will be used mostly to get around problems
of non-hygienic macros in that particular dialect. I don't recall
seeing them used in real Racket or Scheme code, however, probably
because those languages have hygienic macros.
Estoterica #3: In some Lisp dialects (not Racket), interned symbols are
not garbage-collected, so, if you tried to generate unique symbols
infinite numbers of times in a run of a program, *eventually* they might
want to take up more space than can be represented by your computer and
then by the universe.
--
http://www.neilvandyke.org/