the structure of things - axkr/symja_android_library GitHub Wiki

The structure of things

Every expression in Symja is built upon the same principle: it consists of a head and an arbitrary number of children, unless it is an atom, i.e. it can not be subdivided any further. To put it another way: everything is a function call. This can be best seen when displaying expressions in their “full form”:

>> FullForm(a + b + c)
"Plus(a, b, c)"

Nested calculations are nested function calls:

>> FullForm(a + b * (c + d))
"Plus(a, Times(b, Plus(c, d)))"

Even lists are function calls of the function List:

>> FullForm({1, 2, 3})
"List(1, 2, 3)"

The head of an expression can be determined with Head:

>> Head(a + b + c)
Plus

The children of an expression can be accessed like list elements:

>> (a + b + c)[2](/axkr/symja_android_library/wiki/2)
b

The head is the 0th element:

>> (a + b + c)[0](/axkr/symja_android_library/wiki/0)
Plus

The head of an expression can be exchanged using the function Apply:

>> Apply(g, f(x, y))
g(x,y)

>> Apply(Plus, a * b * c)
a+b+c

Apply can be written using the operator @@:

>> Times @@ {1, 2, 3, 4}
24

This exchanges the head List of {1, 2, 3, 4} with Times, and then the expression Times(1, 2, 3, 4) is evaluated, yielding 24.

Apply can also be applied on a certain level of an expression:

>> Apply(f, {{1, 2}, {3, 4}}, {1})
{f(1,2),f(3,4)}

Or even on a range of levels:

>> Apply(f, {{1, 2}, {3, 4}}, {0, 2})
f(f(1,2),f(3,4))

Apply is similar to Map (operator /@):

>> Map(f, {1, 2, 3, 4})
{f(1),f(2),f(3),f(4)}

>> f /@ {{1, 2}, {3, 4}}
{f({1,2}),f({3,4})}

The atoms of Symja are numbers, symbols, and strings. AtomQ tests whether an expression is an atom:

>> AtomQ(5)
True

>> AtomQ(a + b)
False

The full form of rational and complex numbers looks like they were compound expressions:

>> FullForm(3 / 5)
"Rational(3,5)"

>> FullForm(3 + 4 * I)
"Complex(3,4)"

However, they are still atoms, thus unaffected by applying functions, for instance:

>> f @@ Complex(3, 4)
3+I*4

Nevertheless, every atom has a head:

>> Head /@ {1, 1/2, 2.0, I, "a string", x}
Integer,Rational,Real,Complex,String,Symbol}

The operator === tests whether two expressions are the same on a structural level:

>> 3 === 3
True

>> 3 == 3.0
True

But

>> 3 === 3.0
False

because 3 (an Integer) and 3.0 (a Real) are structurally different.