I must apologies for what follows will be more of a rambling than an exercise in clear thinking. That is because I am a bit stuck and thought I'd seek help.
I have been thinking some about languages and how it isn't always easy to clearly separate language being implemented from the language used to implement it. The picture gets particularly blurry in Lisps. This time around the question that gave me pause was one of implementing symbols. Better still Racket keywords, since like many lispy terms "symbol" has so many confusing meanings that its nigh impossible to tell what people mean exactly. I specifically talk about autoquoted datums. Two interned symbols that are equal? are eq?, two keywords that are equal? are eq?, 42 is eq? to 42, etc. Symbols are bad example cause people often think about 'symbol or identifier with semantics being: perform variable lookup. Someone on this list said everything in Racket is a struct, so lets start there. (struct kw (symbol)) We can also come up with some syntactic representation and extend our language with read and read-syntax that translate this new syntax into kw-struct as needed. But then we also demand that two syntactically equal kws end up being the same value in the language, so no matter where our reader encounters #kw(foo) it must produce the same value. This must be true across module boundaries, too. Just like Racket keywords. So, what are we to do? There's time when the reader runs, followed by expansion. Does this mean they need to communicate somehow? Also, the reader "runs", that is it is written in Racket (or some derivative) after all, but reader's environment isn't one where expansion happens, and that of the final code being evaled is different still. Right? To ensure eq? of two kws with the same printed representation we'll probably want to keep some global table around that keeps track of "interned" kws. So, for any two #kw(foo), our reader would have to produce something like (lookup-intern-kw #:symbol 'foo), which at run-time would consult the table of kws and return the (kw 'foo) already there, or create a fresh entry and return that new struct. Two observations: (a) it follows that the global table is one that must exist at runtime - not while the reader runs, and (b) we end up relying on the host language for symbol equality after all 'foo is eq? 'foo and that allows us to key the table by symbols e.g. 'foo. Is this how you would do it? Is there a better way that involves the reader more and relies on the runtime less? Bonus question. What if we allow families of kws effectively partitioning kws into namespaces: #kw(family name). This appears a small variation of the above, where you'd simply assemble a compound symbol from family and name to use for the table lookup. That is until you allow parameterizing by "current-family", so kw declaration can omit the family part and it gets inserted as needed - not unreasonable in a language with modules or explicit namespaces. We could allow something like this: #lang racket/kws #:current-family addams #kw(morticia) now any kw within a module without family must translate into one of addams family. But also any #kw(addams morticia) in a different module must be eq? to the one above and in fact to any one like that anywhere. One exception is probably if we send them across Racket spaces which IIUC amount to running separate VMs. In the above example the reader would have to be aware of #:current-family declaration that may appear at the top of the module. We'd probably translate that to some (current-family 'addams) parameter setup, or wrap #%module-begin body in parameterize, then every kw without explicit family would have to check the (current-family) parameter. Is there a way to push this more to the read-time? If there is, what happens if we load the module and enter REPL? Could we ensure its reader is properly parameterized that it would use appropriate current-family? How screwed up is my thinking here? Is there a way to leverage the reader more and rely on the runtime less? I imagine that'd make kws discussed lighter weight? We talk about phases some in Racket, but reader runs somewhere or rather sometime, too. I'd like to have a clearer picture in my head, I guess. Thanks -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.