20. Expressions and Strings

2014-06-28

The chapters numbered 20, 21,...  are of a more fundamental nature. Here the sturcture of Mathematica expressions and strings is investigated and commands for working on them are described.
Mathematica handles many different kinds of things: mathematical fornulas, lists, text, etc. Mathematica represents all of these things in one uniform way. But there are two types of objects to be treated: (Mathematical) expressions and strings: Expressions are treated in the kernel according to rules stored in the kernel; these rules are either provided (automatically) by the software or by rules prepared during the session by the user. 
Strings are text, which is stored as such and is not automtically reworked. But there also special commands to work on strings.

$Version

20.1  The Structure of Expressions

A prototypical example of an expression is   f[x,y]. this might be used to represent a mathematical
function  f(x, y). This function is named   f, its tow arguments as  x   and   y. 
x + y  is also an expression. When you type it in, Mathematica converts it to the standard form: 
Plus[x,y]. When you print it out, this is displayed as:   x + y.

This applies alos to other "operators" such as  ^ (Power) or  / (Divide). In fact, everything you type
into Mathematica and send to the kernel is treated as an expression, except it is tagged as a string by
quotation marks.

x + y + z      		Plus[x, y, z]

	x y z         			Times[x, y, z]

	x ^ n        			Power[x, n]

	{a, b, c}       		List[a, b, c]

	a -> b        			Rule[a, b]

	a =  b        			Set[a, b]

	FullForm[expr]   	give the full form of any expression
	
	Treeform[expr]		  displays expr as a tree with different levels at different depths

	 
		Head[expr]      		give the head of an expression

Input						Output / Representation

x + y + z					x + y + z

FullForm[%]					Plus[x, y, z]

x y							x y

FullForm[%]					Times[x, y]

Note that subtraction, division respectively are not represented by these operators but by addition, multiplication respectively:

x - y						x - y

FullForm[%]				Plus[x, Times[-1, y]]

x/y							x
							-
							y

FullForm[%]				Times[x, Power[y, -1]

a + b^c						a + b^c

FullForm[%]				Plus[a, Power[b, c]]

1 + x^2 + (y + z)^2		1 + x2 + (y + z)2

FullForm[%]                           Plus[1,Power[x,2],Power[Plus[y,z],2]]

FullForm[Sqrt[a + x]]

f[x, y]					f[x, y]

FullForm[ f[x,y] ]		f[x, y]

FullForm[I]				Complex[0, 1]

FullForm[a + b I]

The object  f  in an expression   f[x, y, ...]  is called the head of the expression. It is extracted by the command: "Head"

Input						Output / Representation

Head[a + b + c]					Plus

Head[{a, b, c}]					List

Head[ 23456 ]					Integer

Head[3.14]						Real

Head[Pi]						Symbol

Head[N[Pi]]						Real

Head[ f[x, y] ]					f

FullForm[ x -> Pi ]				Rule[x, Pi]

FullForm[ Real[x] :>  x ]		RuleDelayed[Real[x], x]

FullForm[ a = b ]				b

FullForm[a := c]				Null

a == b							a == b

FullForm[%]						Equal[a, b]

a != b							True

FullForm[%]						True

Hold[a != b]

Clear[a,b]; Remove[a,b]
a != b							True

BesselJ[1, 5.3]					-0.345961

FullForm[ BesselJ[1, 5.3]]  	-0.34596083380118675`

Head[ BesselJ[1, 5.3] ]			Real

FullForm[ BesselJ[1, 5]]		BesselJ[1, 5]

Head[ BesselJ[1, 5] ]			BesselJ

FullForm[ Real[x] ^=  x ]		x

FullForm[ f[x_] = Sin[a x] ]    Sin[Times[a, x]]

FullForm[ Clear[a] ]			Null

FullForm[ g[x_,c_] := Sin[c x]]	Null

FullForm[ f[x] /. x -> Pi]		f[Pi]

FullForm[  D[f[x], x]  ]		Derivative[1][f][x]

FullForm[ D[f[x], {x,3}] ]		Derivative[3][f][x]

FullForm[ D[f[x,y,z], {x,7}, {y, 3}, {z,2}] ]

D[ Sin[a x] Exp[b y], {x,3}, {y,2} ]

FullForm[ D[ Sin[a x] Exp[b y], {x,3}, {y,2} ]  ]

FullForm[ Expand[ (x + y)^2 ] ]

FullForm[ Series[ Sin[x], {x, 0, 3}] ]

g[x_,c_] := Sin[c x]
c = 0.3; 
FullForm[ Plot[g[x,c], {x,0,2Pi}, PlotPoints -> 7, 
PlotRange -> {0,1}] ]

FullForm[ FindRoot[Sin[x] + Cos[x], {x,1} ]  ]

FindRoot[Sin[x] + Cos[x], {x,1} ]

FullForm[ Integrate[x^2/(x^2 + y^2 + z^2), x] ]

Integrate[x^2/(x^2 + y^2 + z^2), x]

eq = f1 =  a + bx + (c/2) x^2 + d 3.33 y + Pi z^3 == 0

FullForm[%]

sig[x_] = If[x > 0, 1, 0]//FullForm

Which[x >= 2, 2, x > 0, 1, x <= 0, 0] //FullForm

DSolve[y'[x] == a y[x], y[x], x]

DSolve[y'[x] == a y[x], y[x], x]//FullForm

DSolve[y'[x] == a y[x], y, x]//FullForm

s = NDSolve[{y'[x] == 2 y[x], y[0] == 1}, y, {x,0,3}]

FullForm[s]

The output of  NDSolve[]  contains a large amount of data. This is contained in the file, though it is not 
shown in the print. It is recommended to delete these before storing the file. A file containing the output of several  NDSolve[]'s for long intervals of integration may well exceed the capacity of a floppy disk.

20.2  Strings

sn = 1234567890

Head[sn]

FullForm[sn]

Characters[sn]

Above there are still expressions. A string is tagged by quotation marks:

st = "1234567890"

Head[st]

FullForm[st]

sv = Characters[st]

Position[sv,5]

sw = FullForm[sv]

s9 = "9"

Position[sv,s9]

lp = Characters[ToString[Pi]]

np = N[Pi,17]

lp = Characters[ToString[%]]

Position[lp,s9]

ToString[expr] 			transforms expr to a string

ToExpression[string] 	transforms string to an expression

Characters[string]		 gives a list of the characters in a string

StringJoin[s1,s2,...]		gives a string consisting of the concatenation of the 
StringJoin[{s1,s2,...}]		strings  s1,s2,...

f = {u[2]-2*u[1]+u[0],u[3]-2*u[2]+u[1]}

FullForm[f]

u[i_]:=ToExpression["u"<>ToString[i]]

f

lx = {"x1","x2","x3"}

FullForm[lx]

StringJoin[lx]

Characters[lx]

StringJoin[%]

D[lx,x1]

D[ToExpression[lx],x1]

20.3 Special Ways to Input Expressions

Mathematica  converts the input  x + y  into  Plus[x, y].  There are several ways to type
the input for an expression:

f[x]        standard form

	f @ x       prefix form for		f[x]

	x // f      postfix form for		f[x]

Input						Output / Representation

Clear[f]

FullForm[ f[x] ]				f[x]

FullForm[ f @ x ]				f[x]

x // f							f[x]

FullForm[N[Pi]]

FullForm[N @ Pi]

FullForm[Pi //N]

f[x, y]    		standard form

	x ~ f ~ y  	infix form for    f[x, y]

Input						Output / Representation

FullForm[ f[x, y]  ]			f[x, y]

FullForm[ x ~ f ~ y ]			f[x, y]

x + y // f						f[x + y]

f @ x + y						y + f[x]

f @ (x + y)						f[x + y]

x y // f						f[x y]

f @ x y							y f[x]

f @ (x y)						f[x y]

3^(1/4) + Pi //N				4.45767

N[ 3^(1/4) + Pi ]				4.45767

N @ 3^(1/4) + Pi				4.45767

{a, b, c} ~ Join ~ {d, e}		{a,b,c,d,e}

20.3.1  Precedence of the Various Forms of Operations

Mathematica interprets  a + b^c  as  a + (b ^ c) .  The operator  ^  has higher precedence than + .
Every special input form is assigned a definite precedence. This includes not only the traditional 
mathemtical operators, but also forms as  ->,  :=  or the semicolons used to separate expressions
in a Mathematica program.

The precedence of prefix form and postfix form differs: The postfix form // has very low precedence.
 // f   at the end of an expression implies that     f    is applied to the whole expression preceeding it.
 Loosely speaking, the lower the precedence of an operator, the higher the range on which it operates.

Clear[f]
x + y + z//f

x + y - z  // f

The prefic form  @  has much higher precedence:   f @ x + y   is equivalent to  f[x] + y  :

f @ x + y

f @ (x + y)

prefixform			High Precedence		Small Range

	postfixform		Low  Precedence		Large Range

The forms of the operators and their precedences are listed in Tables  A.2.7 of the  Mathemtica  book. 
These tables of input forms are arranged in decreasing order of precedence. Input forms in the same box
have the same precedence.

20.4 Part of Expressions

Expressions are a particular kind of lists. One can refer to parts of any expression as one refers to
parts of a list  (cf. Chap.5).

Part[expr, n]  or  expr[[n]]     	the n-th part of expr

Part[expr, {n1, n2, ... }] or  	a combination of parts of an expression
expr[[n1, n2, .... ]]           

ReplacePart[expr, elem, n]      	replace the n-th part of expr  by  elem

Clear[a,b,c]

{a,b,c}[[2]]

(a + b + c)[[2]]

(a + b + c)[[-1]]

(a + b + c)[[0]]

Head[ (a + b + c) ]

(a b c) [[1]]

(a b c) [[0]]

h = f[g[a], g[b]]

FullForm[h]

h[[0]]

h[[1]]

h[[2]]

h[[3]]

Part::"partw" :  "
Part 3 of f[g[a],g[b]] does not exist. >>

h[[1,1]]

h[[1,0]]

The assignemt of indices to expressions is done on the basis of the internal Mathematica form of the expression,  as shown by  FullForm.

FullForm[x/y]

(x/y)[[1]]

(x/y)[[1,1]]

(x/y)[[2]]

(x/y)[[2,1]]

(x/y)[[2,0]]

(x/y)[[2,2]]

20.5	Expressions as Trees

The best way to investigate the hierarchical tree structure of a list representing a complicated expression  is to use the following commands:

TreeForm[expr]			Give the representation tree for    expr

Depth[expr]			The total number of levels   in    expr

Position[list, pattern]  	give position of  pattern  in   list

t = 1 + (3 + x)^2 / y

FullForm[t]

h = TreeForm[t]

In this expression the top node of the tree consists of a   Plus.  From this node come two "branches",
x^3  and   (1 + x)^2.  From the   x^3, there are then two branches,  x  and  3.

Depth[t]

The very first head (in the example above :  Plus  at the beginning of the first line)  is assigned a level  0.  Including this into the count of levels gives the depth  5.

Position[t,+]

Position[t,Plus]

Input						Output / Representation

Position[t, Plus]			{{0}, {2, 1, 1, 0}}

Position[t, Power]			{{2, 1, 0}, {2, 2, 0}}

Position[t,1]				{{1}}

Position[t,-1]				{{2, 2, 2}}

Position[t,3]				{{2, 1, 1, 1}}

Position[t,Times]			{{2, 0}}

20.6	Levels in Expressions

Many operators allow one to specify the levels in an expression on which they should act.

h = ( (x + y)^2 + (a x - z)^3 ) // TreeForm

Input						Output / Representation

Position[h, x, 1]		{}

Position[h, x, 2]		{}

Position[h, x, 3]		{}

Position[h, x, 4]		{{1, 1, 1, 1}}

Position[h, x, 5]		{{1, 1, 1, 1}, {1, 2, 1, 1, 2}}

Position[h, z]			{{1, 2, 1, 2, 2}}

Position[expr,form,n]	give the positions at which  form occurs down to level   n

Position[expr,form,{n}]	  give the positions of   form  exactly at level  n

Level[expr, lev]		a list of the parts of  expr  at the levels specified by  lev

h = ( (x + y)^2 + (a x - z)^3 ) // TreeForm

Depth[h]

Position[h, x]

Position[h, x, {5}]

Position[h, Times]

Position[h, Power]

Position[h, Plus]

Level[h, 1]

Level[h,2]

Level[h, 5]

Level[h, 6]

20.7  Changing Parts of Lists Representing Expressions

In a notebook session commands can be changed easily by returning to them with the cursor and editing them. Thus one may avoid to type lengthy expressions in slightly altered form. Such an approach is not possible when working with a text-based interface (cf. sect. 2.1). In such a case the method for changing parts of command lists described here may present some advantage.  This way is also useful for procedures and programmes  (cf. § 23.2.1). At first the position of the letter, symbol or strings of symbols is found with the help of the command   Position  so that   ReplacePart can be targeted precisely. The search for the position can be rendered more specific by given the level of the wanted symbol.

Part[expr, n]	= value 	give that part of  expr  characterized    
expr[[n]]		= value     by adress  n   the new value value

ReplacePart[expr, elem, n]    replace the n-th part of expr  by  elem

One can manipulate parts of expressions just as one manipulates parts of lists. The use of assignments
as shown below is clumsy and tedious.

t = 1 + (3 + x)^2 / y

FullForm[t]

t[[2, 1, 1]] = x

t

FullForm[t]

t = 1 + (3 + x)^2 / y

t[[2,1,1,1]] = 4

t

t[[2,1,2]] = z

t

t[[2,2,2]]

t[[2,2,1]]

t[[2,2,1]] = w

t

{a, b, c, d, e}[[{2, 4}]]

h = a + b + c + d + e

FullForm[h]

h[[{2,4}]]

h[[2, 4]]

Part::"partd" : 
Part specification (a + b + c + d + e)[2,,4] is longer than depth of object. >>

ReplacePart[h,aa,5]

Replacing parts of expressions as shown below in this subsection is clumsy and tetious. An easier method to do this is based on the use of the commands  Position  and  ReplacePart  as described in  section 20.7. But before this can be done properly some insight should be gained into the structure of lists representing expressions.

a + b + c + d

ReplacePart[%, x^2, 3]

ReplacePart[a + b + c + d, x^2,3]

h = ( (x + y)^2 + (a x - z)^3 )

Now we want to change the symbol  x  in the second term to w;  thereafter the exponent of the second term from  3  to  4.

Position[h,x]

h1 = ReplacePart[h, w, %[[2]] ]

Position[h1, 3]

ReplacePart[h1, 4, %//Flatten]

t = 1 + (3 + x)^2 / y

FullForm[t]

ReplacePart[t,w,2]

ReplacePart[t,w,{2,1}]

ReplacePart[t,w,{2,2}]

ReplacePart[t,w,{2,2,1}]

ReplacePart[t,w,{2,2,2}]

t = 1 + (3 + x)^2 / y

tt = t /. {y -> w, 3 -> 4, 2 -> 7}

tt /. + -> -

Syntax::sntxf: "tt /. + " cannot be followed by "-> -".

ttt = tt /. Plus -> Minus

Minus::"argx" : 
 Minus called with 2 arguments; 1 argument is expected. >>

ttt

Minus::"argx" : 
 Minus called with 2 arguments; 1 argument is expected. >>

Clear[x]
Minus[x]

FullForm[%]

20.8	Taking Parts of Expressions

These list operations can be applied to any kind of expression.

Take[expr, n]    		give the first   n   elements of               expr

          Take[expr,-n]   		give the last    n   elements of	    expr

         Take[expr,{m,n}]   	m-th   to  n-th  elements of 		expr

t = 1 + x + x^2 + x^3

Take[t,2]

Take[t,-2]

Take[t, {2,3}]

Take[t, {-1,4}]

Take[t, {-2,4}]

h = ( (x + y)^2 + (a x - z)^3 )

Now we want to obtain the content of the second bracket.

po = Position[h, a x - z]

g = ReplacePart[h,1,po]

The command  Take[]  may also be useful to get parts of a lengthy output.

f = ( (1 - x)^2 (x^2 + 1)^2 )^-1

g = Integrate[f, x]//Expand

TreeForm[g]

g3 = Take[g,3 ]

Part[g, 3]

g12 = Take[g, 2]

Part[g, {4,5} ]