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! _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users