Expressions & Notebooks

CPSC 215, March (8^th), 2002

C. Jacob

Expressions Describing Notebooks

Everything is an expressions ...

Internal Representation of Expressions

Mathematica works internally with a uniform representation of all objects as expressions. Even entire notebooks are expressions and can be programmed accordingly (see Section 2.10.3 of the Mathematica Book). Numbers, names, and strings are atomic expressions. Nonatomic expressions have the form f[(Subscript[a, 1]),(Subscript[a, 2]),…]. The name f denotes the head, and zero or more arguments (Subscript[a, 1]), (Subscript[a, 2]), … are placed in square brackets. The arguments are themselves expressions.

The function FullForm shows the representation as an expressions. With

FullForm[f[x]]

nothing sensational happens, because f[x] was already written as an expression. More interesting is:

FullForm[(((a + b))^n)]

Here we see that a+b is written internally as Plus[a,b] and the power with Power. An alternative view is produced by TreeForm, which displays the hierarchical structure as a tree.

TreeForm[(a + b)^n]

We see that the first argument of Power is itself a nonatomic expression (that is Plus[a,b]); the vertical line | indicates the next level in the hierarchy. The second argument of Power is atomic.

Somewhat more complicated is:

TreeForm[{a, ((((a^2) - b))^n)}]

This internal representation of expressions is important with many problems (see in-depth; will be discussed in the labs!). Mathematica uses it in all calculations, especially in pattern recognition.

Many functions which we know from list manipulation also work for expressions. Have a look at:

expr = (x^2) + x - 1

FullForm[expr]

The first part (the first argument of the outer expression) is

expr[[1]]

the second part is

expr[[2]]

and the third part is

expr[[3]]

We can easily add a further element using Append:

Append[expr, (x^3)]

FullForm[%]

Assignments are Expressions

Immediate Assignments

An assignment of the form

a = 3;

has the internal representation

Set[a, 3]

Therefore, we can enter any immediate assignment also through the internal representation:

Set[b, π]

?a

?b

a + b

Delayed Assignments

There is a similar internal representation for delayed assignments.

zeroOrOne := Random[Integer]

Table[zeroOrOne, {10}]

The SetDelayed function acts the same way as ":=".

SetDelayed[oneThroughTen, Random[Integer, {1, 10}]]

Table[oneThroughTen, {10}]

?zeroOrOne

?oneThroughTen

Function Definitions are Expressions

Functions with a Single Argument

Even any function that we define within Mathematica is internally represented as a symbolic expression.

Here is an example of a simple function definition:

myFunction[x_] := (Sqrt[x])

?myFunction

We know how to represent delayed assignments (SetDelayed). We just have to find out how "patterns" such as "x_" are represented internally.

Let us check this for a simple expression such as f[x_]:

f[x_Integer] // FullForm

Knowing this, we can write a function definition using an internal representation (which is a little more cumbersome, but a good exercise on symbolic expressions):

SetDelayed[anotherFunction[Pattern[y, Blank[]]], 
      Power[y, 2]]

?anotherFunction

anotherFunction[7]

Functions with more than One Argument

The definition for this function

f[x_, y_] := x + y

using the internal representation works as follows:

SetDelayed[
f[Pattern[x, Blank[]], 
        Pattern[y, Blank[]]], 
Plus[x, 
        y]
]

?f

Functions with Typed Patterns

What about argument patterns with type information?

g[x_Integer /; x > 0, y_List] // FullForm

The Blank[...] expression contains the "type" of the arguments.

So we can use this information in our function definition for g with types:

SetDelayed[
g[Pattern[x, Blank[Integer]], 
        Pattern[y, Blank[List]]], 
Times[x, 
        Power[y, 2]]
]

?g

g[2, {1, 2, 3}]

Are Graphics Symbolic Expressions?

g = Plot[Sin[x], {x, 0, 2  Pi}]

g // FullForm

h = g /. {List[x_, y_] :> Point[{x, y}]}

h // FullForm

h /. {Line -> List}

Show[%]

Notebook Cells are Expressions

Anything you write in a notebook is internally represented as an expression.

Have a look at this sample notebook.

Notebooks Programming

Notebooks are Expressions

The file format, in which a notebook is saved, is a symbolic expression.

Have a look at the file format of the sample notebook.

Note: Use any normal text editor to view this file. For example, type the following command in a shell terminal window (this is the window where you enter the command to start Mathematica): 

	more SampleNotebook.nb

Hit the SPACE key to see more and more of the file. Hit "q" to quit viewing this file.

Notebooks Programming

Exploring a Notebook's Expression

As even notebooks are represented by expressions, we can write programs to create and manipulate notebooks. Here is a simple example, so that you understand the basic idea behind notebook programming.

More examples can be found in the Mathematica Book (see Section 2.10  .3).

You can use these programming concepts for

□ creating interactive tutorials,

□ have Mathematica create notebooks with customized
 	   contents, for instance from specific input data, etc.

Open the notebook NotebookProg.nb before we try the following commands.

Getting and Manipulating a Notebook's Expression

The function Notebooks[] returns a list of all notebooks that are currently open in the FrontEnd:

Notebooks[]

We can then extract a specific notebook, like the one we want to use for our demos:

nb = Notebooks["NotebookProg.nb"]

This gets the expression corresponding to this specific notebook into the kernel:

nbExpression = NotebookGet[First[nb]]

This replaces every occurence of the string "Section" by "Text".

nbExpression /. "Section" -> "Text"

Finally, this creates a new notebook in the FrontEnd, using the modified notebook expression.

NotebookPut[%]

Manipulating a Notebook through Programming

Identifying a Notebook to Manipulate

We assign a symbol to our demo notebook, so that we can easily refer to it for the following manipulation commands.

nb = First[Notebooks["NotebookProg.nb"]]

Now, select the word First in the demo notebook.

Moving Selections ...

Then, evaluate this command:

SelectionMove[nb, Next, Word]

SelectionMove[nb, All, Word]

This has moved the selection to the next word.

We can combine these two commands into a single command, thus performing the selection move in one step:

Map[SelectionMove[nb, #, Word] &, {Next, All}];

This moves the selection to the entire cell, where the cursor is currently in.

SelectionMove[nb, All, Cell]

And this moves the cursor to the very end of the notebook.

SelectionMove[nb, After, Notebook]

Writing to a Notebook ...

We append another Section cell at the end of the notebook.

NotebookWrite[nb, Cell["Third Cell", "Section"]]

A Subsection cell and a normal Text cell is added.

NotebookWrite[nb, 
      Cell["Subsection 1", "Subsection"]]

NotebookWrite[nb, 
      Cell["Evaluate the following formula:", "Text"]]

Writing an Input Cell and Evaluating it

Now we write an Input cell into the notebook.

NotebookWrite[nb, Cell["77!", "Input"]]

We select the previous cell, which happens to be the last cell in the notebook, ...

SelectionMove[nb, Previous, Cell]

... and we evaluate its contents, ...

SelectionEvaluate[nb]

... which generates the corresponding output cell with the result.

Manipulating a Notebook through Programs (2)

Evaluating a Selected Expression (with Replacement)

Here is another example for writing to notebooks and initiating commands through programs.

\(NotebookWrite[nb, 
      Cell["Evaluating a Selection with Replacement", "Subsection"]]\)

This writes the formula x + 1/Expand[(((1 + x))^4)] into an Input cell.

NotebookWrite[nb, 
      Cell[BoxData[
          RowBox[{"x", "+", 
              RowBox[{"1", "/", 
                  RowBox[{"Expand", "[", 
                      SuperscriptBox[
                        RowBox[{"(", 
                            RowBox[{"1", "+", "x"}], ")"}], "\
4"], "]"}]}]}]], "Input"]]

Then we select the entire cell contents, ...

SelectionMove[nb, All, CellContents]

..., and evaluate it:

SelectionEvaluate[nb]

This replaces the original selection by the result.

Evaluating a Selected Expression

... and Creation of a New Output Cell

If we want to keep the original Input cell, we have to use the SelectionEvaluateCreateCell command.

\(NotebookWrite[nb, 
      Cell["Evaluating a Selection with New Output Cell", "Subsection"]]\)

NotebookWrite[nb, 
      Cell["Here we make a selection, evaluate it, and create a new output \
cell for the result", "Text"]]

We create the Input cell again.

NotebookWrite[nb, 
      Cell[BoxData[
          RowBox[{"x", "+", 
              RowBox[{"1", "/", 
                  RowBox[{"Expand", "[", 
                      SuperscriptBox[
                        RowBox[{"(", 
                            RowBox[{"1", "+", "x"}], ")"}], "\
4"], "]"}]}]}]], "Input"]]

Then we select the entire cell contents, ...

SelectionMove[nb, All, CellContents]

..., and evaluate it, now with the evaluation applied to a copied cell (which then turns into an Output cell):

SelectionEvaluateCreateCell[nb]