Welcome! Please see the About page for a little more info on how this works.

0 votes
ago in Metadata by
edited ago by

Hello,

I am implementing a pretty printer and while adding/testing support for *print-meta* I noticed that pr prints an object whose metadata has metadata in the following way:

user> (binding [*print-meta* true]
        (pr-str (with-meta 'foo (with-meta {:bar :baz} {:frob :zork}))))
"^^{:frob :zork} {:bar :baz} foo"

When reading such a form, only the "outermost" metadata is preserved:

user> (binding [*print-meta* true]
        (let [s (pr-str (with-meta 'foo (with-meta {:bar :baz} {:frob :zork})))
              o (clojure.edn/read-string s)]
          {:o o
           :meta (meta o)
           :metameta (meta (meta o))}))
{:o foo, :meta {:bar :baz}, :metameta nil}

The behaviour is the same for clojure.core/read-string and also the tools.reader readers.

Can anyone clarify for me if this is either:

  1. simply GIGO
  2. a bug in the printer
  3. a bug in the readers
  4. a state that should be somehow disallowed
  5. something else?

Neither the metadata reference nor the reader reference explicitly allow or disallow such a thing, as far as I can tell. Should they?

N.B. this is not an issue in any kind of production context and I'm not aware of any library or program that constructs such a thing. It's simply something I tested to see if/how it would break the pretty printer I'm building.

EDIT:

I dug into this some more with Nicola. Here's a perhaps much clearer case that demonstrates the reader isn't propagating nested metadata:

user> (let [o ^^:foo {1 2} {3 4}]
        {:o o :meta (meta o) :metameta (meta (meta o))})
{:o {3 4}, :meta {1 2}, :metameta nil}

:metameta should be {:foo true}.

In this section of MetaReader.invoke we are iterating over the entries of the meta map and manually associng them into the existing meta of the object; any metadata on the meta map itself is not preserved. I have a patch that adds a failing test case and correctly propagates the the meta map's metadata. If this is worth a ticket then I'm more than happy to attach it to that or send it to you directly.

1 Answer

0 votes
ago by

Yes, nested metadata is valid and this is the correct syntax, so no bugs here. :)

ago by
Thanks for the quick response – but in that case shouldn't the reader preserve the "inner" metadata in the example above?
...