System`Private`*Entry* functions
Since version 10.0 System`Private`SetNoEntry and System`Private`EntryQ functions are available.
System`Private`SetNoEntry
Changes internal representation of given expression so that it is considered atomic, it returns "atomized" version of expression. This change affects all references to given expression, but not new expressions even if they are the same.
ClearAll[f, x, y, tmp];
tmp = tmp2 = f[x, y];
System`Private`SetNoEntry@tmp (* f[x, y] *)
Ordinary f[x, y] is not atomic, but all references to f[x, y] that was passed to SetNoEntry are considered atomic:
f[x, y] // AtomQ (* False *)
tmp // AtomQ (* True *)
tmp2 // AtomQ (* True *)
Those expressions are still considered same:
tmp === f[x, y] (* True *)
Head of expression (part 0) is accessible but not other parts:
tmp // Head
(* f *)
tmp[[0]]
(* f *)
tmp[[2]]
(* Part::partd: Part specification f[x,y][[2]] is longer than depth of object. *)
(* f[x, y][[2]] *)
Part accessing/modifying functions treat it as other atomic objects, so they either complain:
Append[tmp, z]
(* Append::normal: Nonatomic expression expected at position 1 in Append[f[x,y],z]. *)
(* Append[f[x, y], z] *)
or ignore our expression:
ReplacePart[tmp, 1 -> z]
(* f[x, y] *)
Pattern matching works as before and can still "go inside" this expression:
Replace[tmp, head_[arg1_, arg2_] :> {head, arg1, arg2}]
(* {f, x, y} *)
I've learned about this function from Leonid's answer to "Make my data-structure atomic" post.
System`Private`NoEntryQ
Tests whether given expression was set as "no entry" expression:
tmp = f[x, y];
tmp // System`Private`NoEntryQ (* False *)
System`Private`SetNoEntry@tmp;
tmp // System`Private`NoEntryQ (* True *)
Some built-in atomic data structures use this mechanism, e.g. SparseArrays evaluate to "no entry" atomic form:
SparseArray@{0, 1} // Unevaluated // System`Private`NoEntryQ (* False *)
SparseArray@{0, 1} // System`Private`NoEntryQ (* True *)
Since version 10.4 there are five additional "Entry-related" functions.
System`Private`EntryQ
Is the opposite of NoEntryQ:
tmp = f[x, y];
tmp // System`Private`EntryQ (* True *)
System`Private`SetNoEntry@tmp;
tmp // System`Private`EntryQ (* False *)
System`Private`HoldSetNoEntry
System`Private`HoldNoEntryQ
System`Private`HoldEntryQ
Are variants of SetNoEntry, NoEntryQ and EntryQ with HoldAllComplete
attribute.
System`Private`ConstructNoEntry
Creates new "no-entry" expression using first argument as head, and rest of arguments as arguments of created expression:
System`Private`ConstructNoEntry[f, x, y] (* f[x, y] *)
% // System`Private`NoEntryQ (* True *)