The reader tries to read a record instead of a literal if the tag contains periods.
Summary of reader forms:
|Record||#user.Foo||record class name||OK|
|Clojure reader tag||#uuid "c48d7d6e-f3bb-425a-abc5-44bd014a511d"||not a class name, no "/"||OK|
|Library reader tag||#my/card "5H"||not a class name, has "/"||OK|
|#my.ns/card "5H"||not a class name, has "/"||OK|
|#my/playing.card "5H"||not a class name, has "/"||BROKEN - read as record|
Note: reader tags should not be allowed to override the record reader.
Cause: In LispReader, CtorReader.invoke() decides between record and tagged literal based on whether the tag has a ".".
Proposed: Change the discriminator in CtorReader.
Alternative 1 (purely string inspection):
- If name has a "/" -> readTagged (not a legal class name)
- If name has no "/" or "." -> readTagged (records must have qualified names)
- Else -> readRecord (also covers Java classes)
Tradeoffs: Clojure-defined data reader tags must not contain periods. Not possible to read a Java class with no package. Avoids unnecessary class loading/construction for all tags.
Alternative 2 (prioritize Class check):
- Attempt readRecord (also covers Java classes)
- If failed, attempt readTagged
Tradeoffs: Clojure tags could not override Java/record constructors - I'm not sure that's something we'd ever want to do, but this would cut that off. This alternative may attempt classloading when it would not have before.
Hybrids of these are also possible.