[racket] Unexpected error extracting value from request bindings.

From: Eli Barzilay (eli at barzilay.org)
Date: Mon Aug 1 12:23:19 EDT 2011

Yesterday, Jay McCarthy wrote:
> (gensym) generates something that cannot be created again in anyway.
> 
> Even it is printed as 'g1753, that doesn't mean typing 'g1753 will
> get the same thing, nor that (string->symbol "g1753") will either.
> This is the whole point of (gensym).

The process of converting an input string into the same symbol is
called "interning", and `gensym' doesn't do that as feature.  Two
relevant functions here are `symbol-interned?' and
`string->uninterned-symbol'.


> The Web server (basicaly) runs symbol->string to create the page and
> then string->symbol later to turn the HTTP request in to the symbol.
> When you did that to your gensym'd symbol, you got the same thing
> that came out of the HTML.

If that's for some symbols that are used in the server, then maybe
there should be a check using `symbol-interned?'?


> As for how it works... you can think of symbols as just pointers to
> table entries that contain the actual text. (gensym) basically just
> uses a different table, so it's impossible for a pointer in one
> table to be the same as a pointer in the other table even if the
> text is the same on both table entries.

`gensym' doesn't use a different table -- it just doesn't use any
table at all.


11 hours ago, Neil Van Dyke wrote:
> 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.

You just need to be aware of that `gensym' feature...


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

Sidenote: channels are often more convenient than a semaphore.
Instead of locking a mutex, you'd run a producer in its own thread and
dump the counter on a channel:

  (define counter
    (let ([ch (make-channel)])
      (thread (λ () (for ([i (in-naturals)]) (channel-put ch i))))
      (λ () (channel-get ch))))

and now each (counter) call returns a new number, safely.


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

They're still sometimes used as a reliable way to get a unique value.
(Since the uniqueness is its main feature, it will stay this way even
if Racket -- or the particular language you use -- ever avoids
allocating duplicate strings and uses hash-consing.)


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

(And that can lead to extremely frustrating bugs...)

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!



Posted on the users mailing list.