6
$\begingroup$

Maybe this is a boring question, but I cannot figure it out. Because every expression has a Head, and Head[1] is Integer, and Head[Integer] is Symbol. Therefore, 1 should somehow represented as Symbol["Integer"][1] or something similar. However, Depth[1] is one which means 1 should be presented as Symbol["Integer..."], not as a expression of depth 2, such as Symbol["Integer"][1].

What is correct representation of 1?

$\endgroup$
5
  • 4
    $\begingroup$ tl;dr Integer and Symbol are special. While everything must have some head, atomic objects are effectively headless. See if tutorial/BasicObjects helps to understand. Also, you'll find that Head[Symbol] is Symbol, but that doesn't mean that everything in the language is Symbol[Symbol[Symbol[... $\endgroup$
    – LLlAMnYP
    Commented Mar 10, 2016 at 12:11
  • 2
    $\begingroup$ It's a nice question though, so I hope someone with deep understanding of the subject will point to a duplicate or provide a detailed explanation. $\endgroup$
    – LLlAMnYP
    Commented Mar 10, 2016 at 12:13
  • 1
    $\begingroup$ To answer the question of the OP, the correct and fullest representation of 1 is literally 1. Even ToBoxes[1] gives "1". $\endgroup$
    – LLlAMnYP
    Commented Mar 10, 2016 at 12:15
  • $\begingroup$ On second thoughts, I think you're on to something here. From the tutorial I suggested, Atomic objects in the Wolfram Language are considered to have depth 0 and yield True when tested with AtomQ. On the other hand, you rightly observe that Depth[1] is 1 although it is atomic. Perhaps, some inconsistency in the documentation. $\endgroup$
    – LLlAMnYP
    Commented Mar 10, 2016 at 12:21
  • $\begingroup$ @LLlAMnYP @Xavier Therefore, because Integer is an Atom, it is a special type of expression. Therefore, Head of an expression does not imply the expression has a explicit form that start with the head. $\endgroup$
    – Kattern
    Commented Mar 10, 2016 at 12:37

1 Answer 1

8
$\begingroup$

In Mathematica there are compound expressions and atomic expressions.

Anything that AtomQ returns True for is atomic, and may behave in "strange" ways. These must be considered indivisible by users, and only standard and documented ways should be used to extract information from them.

All the rest are compound expressions and have the form head[arg1, arg2, ...]. Here head is the head of the compound expression.

Atomic expressions have "heads" too, by convention. These do not indicate a structure. They are used in practice to indicate the type of the atomic expression so we can programatically distinguish an Integer from a Real. The fact that Head[1] returns Integer does not imply that 1 is somehow represented as Integer[...] because AtomQ[1] is True.


Finally a warning:

Don't be fooled by what e.g. FullForm might show for an atomic expressions (e.g. FullForm[2/3] is Rational[2,3] which looks like it has a structure: an explicit head and two arguments. In reality it doesn't. AtomQ[2/3] is True. In practice atomic objects vary in how they behave when you attempt to disassemble them, but none of them work with all functions that would allow looking into their structure (such as pattern matching on the structure FullForm shows, Part, Extract, Depth, etc.). When you work with some objects, you must read their documentation and only handle them in standard and documented ways. Otherwise your code might misbehave in ways you didn't expect.

Other than the most basic data types in Mathematica (Symbol, String, Integer, Rational, etc.) there are more complex atomic objects such as SparseArray, Graph, Image, MeshRegion, etc. These are made to be atomic so that they can have a more efficient internal implementation.

$\endgroup$
10
  • $\begingroup$ This means atomic expression has a head, but they can not be parted with Part. Therefore, we can only get 1[[0]], but cannot get 1[[1]]. All integers are not the same, but if you compare them part by part they are the "same". $\endgroup$
    – Kattern
    Commented Mar 10, 2016 at 12:41
  • 2
    $\begingroup$ Amusingly, pattern-matching works with these two-argument atoms such as rational and complex. e.g. MatchQ[2/3, _[_,_]] $\endgroup$
    – LLlAMnYP
    Commented Mar 10, 2016 at 12:45
  • 3
    $\begingroup$ @Kattern As Szabolcs explicitly mentioned, FullForm on atoms sometimes gives things like Rational[2,3]. The pattern-matcher, I believe, is a "lexicographical" matcher (if I'm using this term correctly), so it seems that it matches the structure of the FullForm without regard for the true structure. PS, can't emphasise the it seems enough. It's what it looks like, but don't take my word for it. $\endgroup$
    – LLlAMnYP
    Commented Mar 10, 2016 at 12:52
  • 1
    $\begingroup$ @Kattern It's not as simple as that. This works: Replace[1/2, h_[n_, d_] :> {h, d, n}]. Stuff like this also works for SparseArray. For Graph it doesn't work at all (also atomic). Cases[1/2,_] doesn't work but Cases[rational[1,2], _] does. In general, what does and what doesn't work for an atomic object is unpredictable. Also what result you get this way from an atomic object is also unpredictable because they do not really have the structure FullForm shows. However, most atomic objects are really convertible to a compound expression for the purpose of storing ... $\endgroup$
    – Szabolcs
    Commented Mar 10, 2016 at 13:55
  • 1
    $\begingroup$ ... in files or sending through a MathLink connection. This is again a different thing. mathematica.stackexchange.com/a/97332/12 The statement that "pattern matching is based on FullForm" only applies for compound expressions, and it's just really trying to point out that for a (compound) expression what matters is not what you see on screen, but the underlying representation (in e.g. FullForm[a/b]). $\endgroup$
    – Szabolcs
    Commented Mar 10, 2016 at 13:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.