Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What functions in Clojure core preserve meta?

Tags:

meta

clojure

Clojure meta is only preserved if a function takes care to do so and the Clojure core functions do not globally preserve meta. The general rule of thumb I've heard is that collection functions like conj, assoc, etc are supposed to preserve meta but sequence functions like map, filter, take, etc do not preserve meta.

Is there a list somewhere of what functions DO preserve meta?

like image 438
Alex Miller Avatar asked Jan 12 '11 19:01

Alex Miller


1 Answers

It's all about the types. Sequence functions act like they call seq on their argument and thus doesn't always return the same type of object. Collection functions and type-specific functions doesn't call seq and return an object of the same type as what was given to them. It kind of make them give the illusion of returning the same object (this might be the reasoning for this behavior) even if that's really not the case. We could say that the rule of thumb is that a functions preserve the meta when it preserve the type.

user> (meta (seq (with-meta (list 1) {:a 1})))
{:a 1}
user> (meta (seq (with-meta (vector 1) {:a 1})))
nil

Be sure to be aware of when laziness is involved tough:

user> (type (list 1))
clojure.lang.PersistentList
user> (type (map identity (list 1)))
clojure.lang.LazySeq
user> (meta (seq (with-meta (map identity (list 1)) {:a 1})))
nil

For a list of functions that preserves meta on collection, see the data structures page. The ones not preserving meta are under the sequences page, with the exception of when they return an object of the same type.

Under the hood I'm not quite sure about the details since laziness and chunked sequence has been added, but you can look at the cons, seq and seqFrom methods from the RT class. The functions not preserving meta-data go through these methods. While the collection functions end up using methods specific to their types.

like image 112
Nicolas Buduroi Avatar answered Sep 19 '22 08:09

Nicolas Buduroi