This question might have a remote connection to my older question, it is also about sameness of expressions and subtle differences observable only in certain forms.
I encountered this strange behavior:
a = Hold[<|1 -> 2|>] (* Hold[Association[1 -> 2]] *) b = Hold[Evaluate[<|1 -> 2|>]] (* Hold[<|1 -> 2|>] *) a === b (* False *) FullForm[a] (* Hold[Association[Rule[1, 2]]] *) FullForm[b] (* Hold[Association[Rule[1, 2]]] *) a[[1, 0]] (* Association *) b[[1, 0]] (* Association *) Uncompress[Compress[b]] === b (* False *) Uncompress[Compress[b]] === a (* True *) Print[Grid[{TreeForm /@ {a, b}}, Dividers -> All]]
What is going on here? What's the actual difference between a and b?
After I already started to write this question, I came up with one more testtests that might be more revealing:
MapAt[Hold, a, {1, Key[1]}] (* MapAt::partw: Part {1,Key[1]} of Hold[Association[1->2]] does not exist. *) (* MapAt[Hold, Hold[Association[1 -> 2]], {1, Key[1]}] *) MapAt[Hold, b, {1, Key[1]}] (* Hold[<|1 -> Hold[2]|>] *) Depth[a] (* 4 *) Depth[b] (* 3 *) AssociateTo[a[[1]], 3 -> 4] (* AssociateTo::invak: The argument Association[1->2] is not a valid Association. *) (* AssociateTo[a[[1]], 3 -> 4] *) So, it looks that a does not hold a real Association, but rather some kind of "raw" expression that can turn into a real Association when evaluated. For some reason, FullForm (which is supposed to be the most verbose) hides these details.
As a practical matter, I would like to be able to construct a Hold with a real Association inside, but whose values might be unevaluated expressions (wrapping each value in its own Hold is a possibility, but it would complicate matters).