Instead of a new `#%q-expression` form, I think there's potential to use `#%datum` or `quote` itself for this. Potentially, the only thing that makes numbers (for instance) special is that the reader, printer, IDE, and bytecode systems already know what module(s) the number structure type(s) come from. As long as user-defined structure types are able to provide each of those systems with the same knowledge (e.g. through a structure type property), then they can have the same benefits.
One complication: User-defined structure types typically aren't interoperable across phases and module registries, the way kernel-defined, cross-phase persistent structure types like numbers and lists are. Even if we know what their module path is, that's not all the information needed, some of the information only "exists" once a generative `struct` definition has created it. In particular, I think using `quote` on user-defined types brings up cross-phase difficulties: A `quote` expression is typically computed at phase (N + 1) for use as a constant at phase N. If we expect to be able to compute it at compile time using phase-(N + 1) instances of user-defined structure types, and if we expect to be able to process it at run time using phase-N instances of those types, then the `quote` operation itself needs to perform some kind of marshalling between those. How to do that marshalling? Well, whatever materials we need, the structure type property can provide them. For instance, certain structure types might go through no change at all (e.g. simple procedures, perhaps). Certain others may do their marshalling using a (module path, identifier, data) intermediate stage just like Matthew Flatt and Alexis King are talking about. Maybe some values would even use complex higher-order marshalling behaviors (similar to contracts or an FFI), letting us take an object that uses phase-(N + 1) tools internally and wrap it up in such a way that it can process phase-N input and output values. And maybe some steps of the marshalling would use side effects, for instance to implement the interning zeRusski is talking about. Whatever the technique we use for marshalling any particular structure type, once the marshalling has completed at phase N, we're often going to want a value that's compatible with the phase-N instance of the structure type. And that means that by the time we ever see that result value, the structure type must have been defined at phase N already -- which means the module where the `quote` appears should (at least indirectly) have a phase-N dependency on the module that contains that definition. To make this work, this time it can be the structure type itself that "carries its own `require` at all times" (via the structure type property), and a `quote` implicitly acts as a `require` for all the structure types that appear inside it. This has a lot in common with the `#q` approach, but it seamlessly blends in user-defined types with core types: We can say that when we `quote` numbers and lists, we implicitly `require` their modules too, but that since those modules are part of the kernel, the `require` has just been imperceptible the whole time. For types that need to be marshalled to bytecode or saved as plain text from a graphical editor, I agree that the (module path, identifier, data) format seems like a fine choice. That said, I do want to point out that in this approach, the *bytecode* and *plain text* uses of (module path, identifier, data) triples would be subtly different from each other. In bytecode, the module path would be required at phase 0 (because, as far as I understand it, phase 0 is all that there is in the bytecode) and the construction would be performed near the start of the module. In plain text Racket code, that phase 0 behavior only happens as the *result* of compiling a `quote` form. Since `quote` marshals the value down one phase, it must have started out at phase 1, and thus we need the reader to return a phase-1 instantiation of the value. This suggests that although we would use a reader syntax like `#q(module-path identifier data)` in this approach, its behavior would be to `require` that module path at phase 1 and perform the construction immediately. On Tuesday, April 23, 2019 at 12:45:04 PM UTC-7, zeRusski wrote: > > (begin-for-syntax > (list 1 #k(foo) 2)) > ;; => ; tag: undefined; > > This can be solved with (require (for-syntax prelude/tags)) but as with > other autoquoted types I'd probably want to be able to just write them in > any phase. Docs say some stuff about namespaces having a scope that crosses > all phases plus separate scopes for each phase. Is there a way for a > binding to span all phases without cooperation from the user? > I think one thing that might help is to have #k(foo) read as: ( (let () (local-require (only-in prelude/tags tag)) tag) 'foo) This still supposes that `#%app`, `let`, `local-require`, and `only-in` are bound, so each module might need to require `racket/base` at the appropriate phase levels for each `#k` it uses. I think with the particular `#q` approach Matthew Flatt was talking about, the situation would be pretty much the same, but the error message would specifically report that no `#%q-expression` transformer was bound. And the approach I'm talking about would be similar, reporting that `#%datum` was unbound. Since most code will need stuff like `#%app` to be bound anyway, in many cases all the necessary bindings will already exist, and there won't be any additional step to take. > Another problem is with REPL. Above runs fine when I run the module, but > not if I type in REPL. > I think for testing out reader macros at the REPL, you can at least use (current-readtable ...) to set the readtable to a different one to use in subsequent commands. I don't have any experience yet with using custom `#lang` languages at the REPL, so maybe there's an easier option. I hope someone else chimes in. -Nia -- 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.