The Front End as Development Environment

New ways to use the notebook interface to develop your code

John Fultz

Wolfram Research, Inc.

Talk Overview

New support for editing of package files

FE-based Mathematica debugger

Syntax coloring

Thoughts about Mathematica and version control

Some future concepts

Editing Packages — The Old Ways

Autosave packages

Write your program in a notebook and Save As Special ▶ Package

Open package in notebook, hope it remains a package when you save

Editing Packages — Autosave packages

Button["Example", Run["\"c:\\Program Files\\Wolfram Research\\Mathematica\\5.2\\Mathematica.exe\" -directlaunch c:\\WRI\\Conference\\2005\\Examples\\Example1.nb"]]

SetDirectory[NotebookDirectory[]];
<<Examples/Example1.m;

Example1Plot[Sin[(E^x)], {x, 0, 5}]

Advantages:

Disadvantages:

Editing Packages — Autosave packages

Slight improvement — The Code style

Button["Example", NotebookLocate[{ToFileName[{NotebookDirectory[],"Examples"}, "Example2.nb"], None}]]

Editing Packages — Open package as notebook

Opens a .m file as a single cell

Button["Example", Run["\"c:\\Program Files\\Wolfram Research\\Mathematica\\5.2\\Mathematica.exe\" -directlaunch c:\\wri\\conference\\2005\\Examples\\Example3.m"]]

Editing Packages — Goals

First-class package support in the front end

Work with, not against, editing of packages in external editors

Make .m files as human-readable as possible

Full support of FE features in package editing

Editing Packages — The New Way

First-class package support

Creating new packages off the New submenu

Button["Example", Run["start notepad", ToFileName[{NotebookDirectory[], "Examples"}, "MyProduct.m"]]]

Opening existing packages

Editing Packages — The New Way

More about the Code style

Debugging Mathematica code — Ground rules

No Dynamic code

Must evaluate all cells while debugger is on

All code to be debugged must be evaluated directly from front end

Debugging Mathematica code — The Stack

FibonacciPrime[n_Integer]:=
FixedPoint[fibPrime, {1, 1, 2, n}][[{3,2}]];

fibPrime[{fibOld_Integer, fibNew_Integer, fibIndex_Integer, primeIndex_Integer}]:=
With[{primeq=PrimeQ[fibNew]},
If[TrueQ[primeq & (primeIndex== 1)],
{fibOld, fibNew, fibIndex, primeIndex},
{fibNew, fibOld+fibNew, fibIndex+1, If[primeq,primeIndex-1,primeIndex]}]]

FibonacciPrime[6]

Debugging Mathematica code — Breakpoints

What is a breakpoint?

f1[x_]:=
Module[ {y1,y2},
y1=f2[x^2];
y2=f2[x^3];
y1+y2
]

f2[x_]:=
Module[{y3,y4,y5,y6,y7},
y3=x;y4:=x+1;
y5=f3[x+2];
y6=f3[x+3];
y7=x+4;
{y3,y4,y5,y6,y7}
]

f3[x_]:=x+3

f1[1000]

Debugging Mathematica code — Break anywhere!

Unprotect[Graphics];

Graphics /:
Power[Graphics[x_, opts___], exp_] :=
Graphics[x/.{Line[pts:{_, _, ___}] :> Line[N[({First[#],Power[Last[#],exp]}&) /@ pts]]}, opts];

Protect[Graphics];

Plot[{x,(Sqrt[Abs[x]])}, {x, -1, 1}]

Debugging Mathematica code — Message Breakpoints

errFun[x_]:=
Module[ {y1,y2},
y1=x+2;
y2=1/y1;
x+Ceiling[y2^2]
]

errFun[-3]

Nest[errFun,-5,10]

Debugging Mathematica code — Watchpoints

outlies[num_, mean_, range_]:=(mean - range > num)|| (mean + range<num);
countOutliers[lst_, deviations_]:=
Block[{count=0, range = deviations ×StandardDeviation[lst], mean = Mean[lst]},
Map[If[outlies[#, mean, range],count++]&, lst];
count]

countOutliers[{2, 5, 3, 9, 1, 4, 2, 10}, 1]

Debugging Mathematica code — Pattern Matcher Integration

g[x_]:=x>10

patt[x_/;g[x]]:={x,g}

patt[x_/;x<5]:={x,small}

patt[x_?Positive]:={x,pos}

patt[x_]:={x}

patt[7]

Syntax Coloring — Basics

The Old

Plot[Sin[x], {x, 0, 2π]

The New

Plot[Sin[x], {x, 0, 2π]

Syntax Coloring — Basics

Other incomplete forms

2+

"A string

(* a comment
f[x_]:=x!

Other syntactic hints

2+2
"A string"
(* A Comment *)

Syntax Coloring — What if I could color anything I wanted to?

Priority #1

min = Min[data];

data = {5, 3, 9};
min = Min[data];

line=Line[{{0,0},{1,1}}];

log = Log[x];

Syntax Coloring — Argument counting

Functions called with too many arguments…

Log[Abs[base,z]]

NotebookOpen[ToFileName[{$TopDirectory, "Documentation", "English"}, "GettingStarted", "GettingStarted.nb"]]

DeleteFile["c:\\tmp\\2","c:\\tmp\\3"]

…or too few

f[x_]:=Plot[x]

…but we check for double and triple blanks!

f[x__]:=Plot[x]

Syntax Coloring — Bad options

Plot[x, {x, 0, 1}, PlotTitle->"A Linear Plot"]

ListDensityPlot[data,MeshRange->{{5,10},{5,10}}]

FullSimplify[((n!)/(n Gamma[n])),ExcudedForms->_!]

Syntax Coloring — Variable Localization

Local variables

Block[{$Path = Append[$Path, "C:\\Temp"]}, Get["MyFile.m"]]

Module[{x=x}, f[x]];

With[{x=x},f[x]];

f[x_]:=g[x,x]

Special use variables

Table[dummy!, {dummy, 5, 10}]

Manipulate[Plot[((Abs[Sin[x]])^y), {x, 0, 1}], {y, 0, 4}]

Integrate[Sin[x]Cos[y], {x, 0,π}, y]

Solve[{(x-y) (z^2)==1,(x^2)==3,(y^2)+yy==3},{x,y,z}]

Syntax Coloring — Variable localization

Pattern variables

Choose[setSize_, chooseSize_] := ((setSize!)/((setSize - chooseSize)!))

FoldList[#1+((#2)^2)&,0,Range[10]]

expr /.  x_-a_:>2x-a

…with a warning when things aren't properly scoped

Choose[setSize_, chooseSize_] = ((setSize!)/((setSize - chooseSize) !))

FoldList[#1+((#2)^2), 0, Range[10]]

expr /. x_-a_ ->2x-a

Syntax Coloring — Our programming mistakes; what about yours?

Scoping conflicts

f[z_]:=Module[{x=z, y=(z^2), z=(z^3)}, x+y+z]

Assignment instead of equality check

If[x = y,Print["x is equal to y"]];

Shadowing

Global`xyz = 0;
System`xyz = 1;

xyz

Remove[System`xyz]

Advisory for new syntaxes

Plot[Sin[x], {x, 0, 2π}];

Syntax Coloring — Customize it!

Use the preferences dialog to change the syntax coloring defaults if you don't like them

f[z_]:=Module[{x=z, y=(z^2), z=(z^3)}, x+y+z]

If[x = y,Print["x is equal to y"]];

Version Control — Why it's a Good Thing™

Complete record of what you've done and why

Ability to rewind the clock from broken to working versions

Synchronization between multiple developers

Version Control — Options

Subversion

CVS

SourceSafe (for Windows)

and many, many others

Version Control — Dealing with Notebooks

Textual diffs of notebooks

Structural diffs of notebooks

Needs["AuthorTools`"];
SetDirectory[ToFileName[{NotebookDirectory[],"Examples"}]];
NotebookPut[NotebookDiff["CircleOld.nb", "CircleNew.nb"], Saveable->False];

Generated notebooks

Looking into the Future

...all the way to the year 2000!!

Documentation integration tools

Profiling

Project management

Easy deployment of applications

Integration with version control

Your ideas