Lately, and by lately I mean since version 7 or so, the number of atomic expressions in Mathematica constantly grew. In former times only the native types like integers and optimised arrays were atomic, but now we have Image
, Graph
, Association
and many more.
The reason for this is mostly to make those structures highly performant. The big disadvantage is that it is not instantly visible what is atomic and that things like pattern matching, replacing, etc. don't work with them. A simple example is
Image[{{1, 0}, {0, 1}}] /. {0 :> {0, 1, 0}, 1 :> {1, 0, 0}}
The result is still a b/w image. When pattern matching doesn't work, I often give people the tip to look at the FullForm
, but that doesn't help either. Those expressions look like something they are not.
Beside this obvious break with the one of the basic Mathematica paradigms, atomic expressions have advantages. One of those applications is when you use container expressions to store important information that should never be changed manually or bad things will happen. Let me give a simple example:
Assume you have a C++ library you use to calculate something and you need to manage a global object there. This object needs to stay alive for several callbacks from Mathematica. An easy way to achieve this is to not delete
it and give a pointer to the object to Mathematica. So in Mathematica we have something like
LibraryObject[ptr->123456,state->"Initialised"]
Everyone should see that it is vitally important that no one changes the ptr
to the object or the state
. Therefore my question
Is it possible to make
LibraryObject
atomic likeImage
and protect it from access through[[]]
from other changes?
System`Private`SetNoEntry
on any expression which you want to protect in this manner. $\endgroup$HoldPattern@uncover@_@args__ := {args}
anduncover@atomicExpr
. $\endgroup$