Structural Operations

The Wolfram System contains some powerful primitives for making structural changes to expressions. You can use these primitives both to implement mathematical properties such as associativity and distributivity, and to provide the basis for some succinct and efficient programs.

Here we describe various operations that you can explicitly perform on expressions. "Attributes" describes how some of these operations can be performed automatically on all expressions with a particular head by assigning appropriate attributes to that head.

You can use the Wolfram System function Sort[expr] to sort elements not only of lists, but of expressions with any head. In this way, you can implement the mathematical properties of commutativity or symmetry for arbitrary functions.

You can use Sort to put the arguments of any function into a standard order.
In[1]:=
Click for copyable input
Out[1]=
Sort[expr]sort the elements of a list or other expression into a standard order
Sort[expr,pred]sort using the function pred to determine whether pairs are in order
Ordering[expr]give the ordering of elements when sorted
Ordering[expr,n]give the ordering of the first n elements when sorted
Ordering[expr,n,pred]use the function pred to determine whether pairs are in order
OrderedQ[expr]give True if the elements of expr are in standard order, and False otherwise
Order[expr1,expr2]give if comes before in standard order, and if it comes after

Sorting into order.

The second argument to Sort is a function used to determine whether pairs are in order. This sorts numbers into descending order.
In[2]:=
Click for copyable input
Out[2]=
This sorting criterion puts elements that do not depend on before those that do.
In[3]:=
Click for copyable input
Out[3]=
Flatten[expr]flatten out all nested functions with the same head as expr
Flatten[expr,n]flatten at most n levels of nesting
Flatten[expr,n,h]flatten functions with head h
FlattenAt[expr,i]flatten only the i^(th) element of expr

Flattening out expressions.

Flatten removes nested occurrences of a function.
In[4]:=
Click for copyable input
Out[4]=
You can use Flatten to "splice" sequences of elements into lists or other expressions.
In[5]:=
Click for copyable input
Out[5]=

You can use Flatten to implement the mathematical property of associativity. The function Distribute allows you to implement properties such as distributivity and linearity.

Distribute[f[a+b+,]]distribute f over sums to give
Distribute[f[args],g]distribute f over any arguments which have head g
Distribute[expr,g,f]distribute only when the head is f
Distribute[expr,g,f,gp,fp]distribute f over g, replacing them with fp and gp, respectively

Applying distributive laws.

This "distributes" over .
In[6]:=
Click for copyable input
Out[6]=
Here is a more complicated example.
In[7]:=
Click for copyable input
Out[7]=

In general, if f is distributive over Plus, then an expression like can be "expanded" to give . The function Expand does this kind of expansion for standard algebraic operators such as Times. Distribute allows you to perform the same kind of expansion for arbitrary operators.

Expand uses the distributivity of Times over Plus to perform algebraic expansions.
In[8]:=
Click for copyable input
Out[8]=
This applies distributivity over lists, rather than sums. The result contains all possible pairs of arguments.
In[9]:=
Click for copyable input
Out[9]=
This distributes over lists, but does so only if the head of the whole expression is .
In[10]:=
Click for copyable input
Out[10]=
This distributes over lists, making sure that the head of the whole expression is . In the result, it uses in place of List, and in place of .
In[11]:=
Click for copyable input
Out[11]=

Related to Distribute is the function Thread. What Thread effectively does is to apply a function in parallel to all the elements of a list or other expression.

Thread[f[{a1,a2},{b1,b2}]]thread f over lists to give
Thread[f[args],g]thread f over objects with head g in args

Functions for threading expressions.

Here is a function whose arguments are lists.
In[12]:=
Click for copyable input
Out[12]=
Thread applies the function "in parallel" to each element of the lists.
In[13]:=
Click for copyable input
Out[13]=
Arguments that are not lists get repeated.
In[14]:=
Click for copyable input
Out[14]=

As mentioned in "Collecting Objects Together", and discussed in more detail in "Attributes", many builtin Wolfram System functions have the property of being "listable", so that they are automatically threaded over any lists that appear as arguments.

Builtin mathematical functions such as Log are listable, so that they are automatically threaded over lists.
In[15]:=
Click for copyable input
Out[15]=
Log is, however, not automatically threaded over equations.
In[16]:=
Click for copyable input
Out[16]=
You can use Thread to get functions applied to both sides of an equation.
In[17]:=
Click for copyable input
Out[17]=
Outer[f,list1,list2]generalized outer product
Inner[f,list1,list2,g]generalized inner product

Generalized outer and inner products.

Outer[f,list1,list2] takes all possible combinations of elements from and , and combines them with f. Outer can be viewed as a generalization of a Cartesian product for tensors, as discussed in "Tensors".

Outer forms all possible combinations of elements, and applies to them.
In[18]:=
Click for copyable input
Out[18]=
Here Outer produces a lowertriangular Boolean matrix.
In[19]:=
Click for copyable input
Out[19]=
You can use Outer on any sequence of expressions with the same head.
In[20]:=
Click for copyable input
Out[20]=

Outer, like Distribute, constructs all possible combinations of elements. On the other hand, Inner, like Thread, constructs only combinations of elements that have corresponding positions in the expressions it acts on.

Here is a structure built by Inner.
In[21]:=
Click for copyable input
Out[21]=
Inner is a generalization of Dot.
In[22]:=
Click for copyable input
Out[22]=