[racket] Unexpected error extracting value from request bindings.

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Mon Aug 1 01:08:27 EDT 2011

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/


Posted on the users mailing list.