[racket] Unexpected error extracting value from request bindings.
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!