Thanks for exploring this! I was tempted down this path earlier this year because I was trying to future-proof my structure type definitions by making them cross-phase persistent. I see no innate reason for them not to be, so I figured I'd put in the effort early and avoid having to make a breaking change later on.
In the end, it turned out I wanted my structure type definitions to use certain things like `gen:custom-write` and `gen:equal+hash` that aren't supported by cross-phase persistent modules. In fact, the cross-phase persistent modules in Racket seem to have very few *specified* exports at all[1][2][3], so I was afraid I might rely on some unspecified behavior today and find it missing tomorrow. On top of that, even a cross-phase persistent module doesn't "persist" across multiple module registries, so it doesn't fully match my expectations. This logger approach looks like it could achieve something just as "persistent" as a cross-phase persistent module (unfortunately not persisting over multiple module registries or multiple loggers), and with very little use of unspecified behavior along the way (although I see you still rely on a few exports of `#%kernel`, particularly `gensym`). Of course, if it runs up against the separate compilation guarantee, this might be the kind of specified behavior that's ruled to be a specification error someday. As for what to do about it... It seems to me that the separate compilation guarantee's exception for "external effects" means it's not a very strict guarantee. As long as compile-time code can interact back and forth with the outside world, an occasional programmer may rig up a system in the outside world that serves no purpose except to be an accomplice in breaking the guarantee. If the root logger can be that accomplice, should it just be considered external (by fiat), essentially documenting that it's an exception to the guarantee? I don't suppose many other external effects make it easy to round-trip object references in a memory-safe way, so this might make it a bit special. On the other hand, the design of the logging interface seems especially prone to abstraction leaks. Isn't logging often thought of as an implementation detail? I wouldn't expect to be able to listen to a module's logs unless I had power over its code inspector (or something like that). [1] "The exact set of function bindings exported by `racket/kernel` is unspecified and subject to change across versions. <https://docs.racket-lang.org/reference/Kernel_Forms_and_Functions.html>" [2] "Primitive modules with names that start with #% [like `#%kernel`] are defined, but they are not meant for direct use, and the set of such modules can change. <https://docs.racket-lang.org/reference/running-sa.html>" [3] Admittedly, certain identifiers like `#%declare`, `#%provide`, `define-values` and `gensym` are documented to be part of the accepted grammar of cross-phase persistent modules, so I suppose it's strongly implied that at least some cross-phase persistent modules exist that export these bindings. On Sunday, April 21, 2019 at 3:41:15 AM UTC-7, Alexis King wrote: > > Hello all, > > I just published a blog post on defeating Racket’s separate compilation > guarantee. While I don’t imagine such a thing is actually a good idea, I > think the path to getting there is interesting anyway, and it touches lots > of different parts of the Racket system. For those who are interested, the > blog post is available here: > > > https://lexi-lambda.github.io/blog/2019/04/21/defeating-racket-s-separate-compilation-guarantee/ > > > Comments welcome, > Alexis > > -- 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.