Brief Introduction to WL and Mathematica
- author:
Alan G. Isaac
- organization:
American University
- copyright:
2025-11-17
Background
What Is Mathematica?
Mathematica is a commercial computer algebra system built around the Wolfram Language (WL). Mathematica is popular among economists because it natively supports symbolic as well as numerical computation, including native support for multidimensional arrays. Additionally, the Mathematica software includes excellent notebook facilities, making it very convenient to write and store long computations with supporting text.
The Mathematica REPL
There is a rather limited text-based environment that allows REPL-like access to the Mathematica kernel. Most users will prefer to work with Mathematica notebooks in order to take advantage of their display capabilities and convenient navigation.
Mathematica from the Command Line
The wolfram and wolframscript executables can
run Mathematica programs from the command line.
The latter can execute code snippets from your operating system’s
command shell.
wolframscript -code (2+2)
https://reference.wolfram.com/language/workflow/RunWolframLanguageCodeFromTheCommandLine.html
Getting Help
Start up a new Mathematica notebook (e.g., by double-clicking the program icon). In the new notebook, start typing. This opens a new input cell. Type a question mark followed by a command. For example, to access the help for Mathematica’s mathematical constant Pi as follows.
?Pi
After typing this in an input cell,
display the basic help for the command
by pressing [shift]+[enter].
This evaluates the expression in the input cell.
Exit the program as usual.
Interactive Hello World
In a Mathematica notebook
enter Print["Hello World!"] in an input cell,
followed by [shift]+[enter].
This prints the string.
Hello World Script
Create a folder for your Mathematica experiments.
In this folder,
create a file named HelloWorld.wl
that contains this single line:
Print["Hello World!"]
In your shell, change to your project directory.
Enter wolframscript -file HelloWorld.wl,
and you should see the expected result print out in your shell.
Next, start the Mathematica REPL in the folder containing this file. Enter the following at the REPL command line, and you should see the expected result print out in the REPL.
Get["HelloWorld.wl"]
Video: The All-New Wolfram Script
Documentation: Create Wolfram Language Scripts and WolframScript (for the Command Line).
Older Conventions for File Execution
The relatively new wolframscript binary sits alongside the traditional math and wolfram binaries. Consider math to be a deprecated alias for wolfram; the binaries appear to be identical.
The wolframscript binary offers a superset of the capabilities of wolfram, including simple execution in the cloud.
However, all we care about right now is wolframscript -file file vs wolfram -script file.
These are roughly equivalent as long as you have a single version of Mathematica (or the EngineJ) installed.
Related to this, the extensions .m, .wl, and .wls are all in use. We will use only the .wl extension.
https://reference.wolfram.com/language/ref/program/wolfram.html https://reference.wolfram.com/language/ref/program/wolframscript.html
Basic Syntax
See the excellent documentation of WL’s basic syntax. A value in Mathematica is always an expression, and operations on expressions typically have no additional data type expectations. (If an operation encounters an expression it does not know how to manipulate, it simply leaves it unevaluated.)
Surprises
There are a few key syntax surprises for those coming from other languages.
the need to use a backtick instead of an underscore to separate parts of variable names,
the use of square brackets for function application,
the percent sign (
%) is not the remainder operator,a space between expressions is treated an implicit multiplication, (e.g.,
x yis the same asx*y), andthe function definition syntaxes are unusual (see below).
Numbers
WL allows computing with many different number types.
The most basic distinction is between exact and approximate numbers.
The values 1/3 and 1.0/3 are not the same,
because 1 is an exact number (an integer)
but 1.0 is an approximate number (floating point).
Computations with exact numbers produce exact numbers.
So the first fraction is an exact number, stored as its two integer parts.
The second fraction is an approximate number,
stored as a floating point approximation (at machine precision).
Working with exact numbers avoids dealing with the
inherent imprecision of approximate (floating point) numbers,
but it comes at a huge cost in computational speed.
Therefore it is most often desirable to compute with approximate numbers,
just as in any other programming language.
This requires some alertness to the associated problems and ways to handle them.
For example, it is sometimes useful to force approximate zeros to zero using Chop,
which replaces approximate zeros with exact zeros.
3/10 - 2/10 - 1/10 (* exact 0 *) 0.3 - 0.2 - 0.1 (* -2.77556*10^-17; approximately zero *) 0.3 - 0.2 - 0.1 //Chop (* exact 0 *)
Displaying Numbers
WL allows substantial control over the display of numbers.
By default, approximate numbers display with 6 significant digits,
but trailing zeros after the decimal point are truncated.
The NumberForm and PercentForm commands can change this notebook display.
1.0 / 5.0 (* displays 0.2 *)
NumberForm[1.0/5.0, {4,4}] (* displays 0.2000 *)
PercentForm[1.0/5.0] (* displays 20% *)
Arithmetic Operators
Arithmetic operators are pretty standard,
except that exponentiation uses the caret (^).
The most surprising thing for new users is that
an operator is always a convenient short form for an underlying function.
1+2+3 (* 6 *) Plus[1,2,3] (* 6 *)
One other surprising behavior is the support for implicit multiplication, as in Julia. (This is convenient in the REPL, but do not use it in your code.)
x=3 2 x (* 6 *)
Use Quotient[m,n] for integer division;
it produces the greatest integer less than m/n.
Use Mod[m,n] for the remainder from integer division.
(Unlike some other languages, do not use % for this;
it is not the remainder operator.)
Produce both the divisor and the remainder with QuotientRemainder.
Mathematica provides a very large collection of builtin functions.
Mathematica’s support for broadcasting is powerful
but somewhat idiosyncratic.
Pay particular attention to Thread and MapThread.
Symbols and Assignment
Use a single equals sign to immediately bind a symbol to the value of an expression.
x = 3.0 / 2.0; x (* evaluates to 1.5 *)
Use WL’s Protect command to prevent subsequent changes
to the value associated with a symbol.
(See the documentation
for details.
There are numerous variants on the equals sign,
with different uses.
As in many other languages,
test equality with the == operator,
which is shorthand for the Equal function.
Test identity with the === operator,
which is shorthand for the SameQ function.
Make delayed assignments with the := operator,
which is shorthand for the SetDelayed command.
(See the documentation for details.)
Random Numbers
The RandomReal and RandomInteger functions are builtin.
To seed them, use SeedRandom or BlockRandom.
SeedRandom[314]
RandomInteger[{0, 5}, 5] (* {5, 2, 0, 4, 5} *)
BlockRandom[
RandomInteger[{0, 5}, 5],
RandomSeeding -> 314] (* {5, 2, 0, 4, 5} *)
Compound Expressions
Using semicolons,
a sequence of expressions may be chained into a compound expression,
which has the value of the last expression.
(Or, use the CompoundExpression command.)
z = (x = 0; y = 1; x + y) (* 1 *) z = CompoundExpression[x=1,y=2,x+y] (* 1 *)
This is sometime called chain syntax, and it may span multiple lines.
z = (x = 0;
y = 1;
x + y)
Warning: Compound expressions do not establish a new variable scope.
You can use With instead.
z = With[{x = 0,y = 1}, x + y]
Core Data Types
List
The list is a fundamental data type in WL. It is used to represent sets, vectors, and matrices. Make a list by enclosing comma-separated expressions in braces. A list is a sequence type: order and repetition matter. Here is a list of the first three positive integers.
{1, 2, 3}
WL makes it simple to construct and manipulate lists.
For example, apply the Range function to a positive integer n
in order to produce a list of the first n positive integers.
So Range[3] is also a way
to create a list of the first three positive integers.
- Helpful Videos:
Basics of Lists by Leandro Junes.
Listable Operations
In WL, the usual arithmetic operators all have the Listable attribute.
This means that they apply elementwise when the operands are lists.
For example, you may double a list of numbers as follows.
lst01 = {1, 2, 3};
2 * lst01
Or, you may multiply two lists elementwise as follows.
lst01 = {1, 2, 3};
lst02 = {3, 2, 1};
lst01 * lst02
Creating Lists with Table
Core iterator functionality is provided by Table,
the simplest form of which requires two arguments.
The first argument is an expression in an iterator variable,
and the second argument is an iterator specification
for that variable.
The iterator specification determines the values to iterate over.
For example, the following expression squares each value
of the iterator variable i,
which the second argument determines to have the values from 1 to 10.
Table[i^2, {i,1,10}]
It often proves useful to provide a specific list of values
for iterate over, and Table allows this,
as illustrated by the next example.
lst = Range[10];
Table[i^2, {i,lst}]
To create a list of lists, provide Table with a second iterator variable.
In a notebook, it is often convenient to display this using TableForm.
tbl = Table[i*j, {i,lst}, {j,lst}];
TableForm[tbl, TableHeadings->{lst,lst}]
Creating Lists by Importing Data
The Import command is able to import varied data formats.
To import a tabular CSV file,
specify the "Data" format and the number of header lines.
In order to produce a self-contained example,
the following illustration creates a string to represent
the contents of a CSV file and imports it with the closely related
ImportString command.
csvstr = "header01,header02\n1,2\n2,4\n3,9" ImportString[csvstr, "Data", HeaderLines -> 1]
The result is a matrix (i.e., list of lists) containing the data (but not the header line). It is also possible to import a restricted selection of the data, such as a single column. For example, import all the data in just the final CSV column as follows. (The result is a numerical list.)
ImportString[csvstr, {"Data", All, -1}, HeaderLines -> 1]
Function
Ordinary Function Definition
In Mathematica, functions are first class objects.
This means that they can be passed around like any other object.
Ordinary function definition uses the Function command
(or equivalent shorthand notation).
There is Return command,
but its use is optional.
In the absence of a Return,
the value of the function is the value of the last expression in the function body.
test = Function[x, 1+x]
Here the equals sign binds the name test to the defined function object.
Note that the name x in this function definition is just a placeholder.
It does not refer to any value outside the function definition.
The same is true if we use the following
three-part maps to arrow (|->),
a shorthand syntax for function creation.
x |-> 1+x
This three-part-arrow syntax usually provides the right trade-off between
brevity and readability.
Still, the variable x in this definition is just a placeholder or slot,
so it plays no substantive role in function definition.
Correspondingly, WL offers a special slot syntax for producing the same function.
Function[1+#]
There is even a very terse equivalent shorthand for the slot syntax. This is particularly convenient for short anonymous functions.
(1 + #)&
To introduce additional variables into a function body that are local to the function,
use the Module command.
Or for local constants, use the With command.
Variables and Scope
A variable can have local or global scope.
Here global means in the Global context.
Variables are typically lexically scoped,
so the meaning of a nonlocal variable in a function
is determined by the scope in which the function definition occurs,
not the scope from which it is called.
There is no substitute for Mathematica’s documentation of scoping constructs.
Function Arguments
Pattern-based function definitions can include ordinary arguments or keyword arguments. Keyword arguments are defined as options (and must have default values).
Composition and Piping
WL uses a @* for ordinary composition:
\(f @* g\) produces the ordinary composition of two functions,
such that \((f @* g)[x]==f[g[x]]\).
The same effect is produced by piping: x // g // f.
Operator Forms
Some WL commands have an operator form.
One example is Map.
f = #^2&; (* define a squaring function *)
Map[f, {1,2,3}] (* core syntax to map f across expr *)
Map[f][{1,2,3}] (* equivalent, using operator form *)
Map[f] @ {1,2,3} (* equivalent, applying operator form with @ *)
f /@ {1,2,3} (* equivalent short-input form *)
Control Flow
WL’s boolean values are True and False.
Conditional branching is done with If syntax.
If[x < y, Print[x," is smaller than ", y], Print[x," is not smaller than ", y] ]
However, since If produces a value,
the following might be preferred.
tmp = StringTemplate["`` is ``smaller than ``"] Print@tmp[x,If[x<y,"","not "],y]
Atomic and Composite Types
todo
Constructors for Composite Types
You may define a constructors to create a composite type.
newPoint[x_Integer,y_Integer] := point[N@x, N@y] pt = newPoint[1,2] #point[1.0,2.0]
This example is rather pointless (pun intended).
Tabular
Much of data science has shifted to the use of columnar storage formats, where the associated data type is often called a dataframe. In WL, the code{Tabular} data type provides this functionality. This is a very efficient data type and can readily be used with very large data sets. The use here with a tiny data set is purely illustrative.
You can profitably think of a Tabular object as a collection of named vectors,
one in each column.
In a Tabular named df,
you can extract an entire column named say "c1" as follows:
df[[All,"c1"]].
When a column is numeric, it can be scaled.
(For example, 2 * df[[All,"c1"]].)
When two columns are numeric, they can be added.
(For example, df[[All,"c1"]]+df[[All,"c2"]].)
It is possible to perform such columnar transformations
and then use ToTabular to construct a new tabular obect from these results.
ToTabular[{"scale"->2*df[[All,"c1"]],"add"->df[[All,"c1"]]+df[[All,"c2"]]}]
However, it is uncommon to proceed in this way.
Instead, use ConstructColumns or TransformColumns
to transform the data and produce the desired dataframe.
For example:
(* create a first dataframe, with two named columns *)
df = Tabular[RandomInteger[{0,10},{50,2}],{"c1","c2"}]
(* describe the desired new dataframe columns *)
trans = TransformColumns[{"scale" -> (2*#c1 &), "add" -> (#c1 + #c2 &)}]
(* create the new dataframe (with all four columns) *)
dfnew = trans@df
Packages
Plotting
Mathematica’s plotting capabilities are extensive and simple to use. There are many online introductions. Consider watching the introductory Plots video by Socratica.
Run-Sequence Plot
In a notebook, produce a run-sequence plot (“line chart”) as follows.
plt1 = ListPlot[{1,2,3}]
plt2 = ListLinePlot[{1,2,3}]
If you creat several plots, you can plot them together.
Show[plt1, plt2]
Use GraphicsRow, GraphicsColumn, or GraphicsGrid
to control the layout of multiple plots.
Sequence Plot
A real sequence is a function from the positive integers to the real numbers.
To plot a sequence prefix,
it is rather natural to use DiscretePlot.
DiscretePlot[1/n, {n, 1, 10}]
However, by default this produces a pin plot. Usually we want a line chart, possibly with markers. And it is always a good idea to label your axes.
DiscretePlot[1/n, {n, 1, 10},
AxesLabel->{"n","1/n"},
Filling->None, Joined-> True, PlotMarkers->{Automatic,Small}]
Plotting Line Segments
A striaght line segment joins two end points and includes every point that is a convex combination of the two endpoints.
In one dimension, use a number-line plot. The simplest way is to plot an interval.
NumberLinePlot[Interval[{1, 2}]]
In two dimensions, use a line chart. The simplest way is to plot the two points, joined.
pts = {{1,2},{3,4}};
ListPlot[pts, Joined->True]
ListLinePlot[pts]
Make this look a bit better.
{xs, ys} = Transpose[pts];
ListLinePlot[pts,
PlotRange -> {{0, 5}, {0, 5}},
Ticks -> {xs, ys},
PlotMarkers -> {Automatic, Small},
AxesLabel -> {"x", "y"}]
In three dimensions, you need three-dimensional plotting facilities. Given these, the simplest way is to again plot the two points, joined.
pts = {{1, 2, 3}, {3, 2, 1}};
ListLinePlot3D[pts,
PlotRange -> {{0, 4}, {0, 4}, {0, 4}},
Ticks -> Transpose[pts],
PlotMarkers -> {Automatic, Small},
AxesLabel -> {"x", "y", "z"}]
Labeled Scatter Plots
todo
2D Contour Plots
The ContourPlot command can plot contours of binary real functions
or solution sets of equations in two real variables.
f = {x,y} |-> 3*x + 2*y; (* define a binary function *)
ContourPlot[f[x,y],{x,0,4},{y,0,4}] (* plot many contours *)
ContourPlot[f[x,y]==6,{x,0,4},{y,0,4}] (* plot a solution set *)
Arrays
Entering Matrices by Hand
WL considers any two-dimensional rectangular list of lists to be a matrix.
It can be convenient to create small matrices by hand.
One my simply type in a list of lists.
This is not a very pretty display however.
Use MatrixForm to produce a better display of a matrix
(in a Mathematica notebook).
mA = {{1,2},{3,4}} (* create a matrix *)
MatrixForm[mA] (* nicer display *)
Unfortunately, a matrix form is not a matrix, and you cannot use it for matrix operations. This seems to create a tradeoff between readability and usability. However, in a Mathematica notebook, it is possible to have both. Here are three techiques.
Wolfram documents how to use Mathematica’s Insert menu to insert a nice looking matrix).
Use Mathematica's Basic Math Assistant palette to typeset your matrix. One of the typesetting options will insert a \(2 \times 2\) matrix. Hover your mouse over this to see the instructions for expanding it.
Enter it by hand, following the matrix expansion instructions mentioned in the previous option. E.g., within empty parentheses, enter a number (the \(1,1\) element), then enter
ctrl+commato add a column, then enterctrl+enterto add a row.
Array Creation
In WL, lists are the basic array structure. This support elementwise operations. (See above.) There are many specialized functions for list creation.
ConstantArray[0, {3, 5}] (* matrix of 0s *)
ConstantArray[1, {3, 5}] (* matrix of 1s *)
IdentityMatrix[3] (* 3 × 3 identity matrix *)
Generally, lists can hold any mix of objects. However, typed array creation is possible.
xs = NumericArray[{1,2,3},"Real64"]
Unfortunately, as of version 14.3, doing even simple arithmetic operations on numeric arrays (without converting them to ordinary lists) requires writing compiled functions with a fair amount of boilerplate. So the following discussion focuses on ordinary lists.
Broadcasting
WL lists are very powerful and support natural elementwise operations.
Many functions have the Listable attribution,
which means that applying them to a list will apply them elementwise.
xs = (Pi/2) * {1,2,3}
ys = Sin[xs]
A more complicated example.
mA = ArrayReshape[Range[6], {2, 3}] (* 2×3 matrix *)
pos = Position[mA, x_?EvenQ, {2}] (* indexes of even elements *)
Extract[mA, pos] (* list of even elements *)
Iterators
Sometimes it is convenient to operate on arrays without ever producing them explcitly. Iteration is often perfect for this. As a simple example, consider summing the squares of the first 1000 positive integers. A memory intensive approach would create the an array of integers, then map over this to square them (thereby creating another array), and then finally reduce the list of squares by summing them. Instead, we can avoid array creation altogether as follows.
total = Sum[i*i, {i,1000}]
More general purpose iterators are somewhat hidden (in GeneralUtilities).
total = Fold[#1 + #2^2 &, 0, GeneralUtilities`RangeIterator[1000]]
These iterators are stateful.
xs = GeneralUtilities`RangeIterator[2] GeneralUtilities`PackageScope`PullIterator[xs] (* 1 *) GeneralUtilities`PackageScope`PullIterator[xs] (* 2 *) GeneralUtilities`PackageScope`PullIterator[xs] (* GeneralUtilities`IteratorExhausted *)
Using Other Languages
Julia
First, start a new session and load needed libraries.
session = StartExternalSession["Julia"] ExternalEvaluate[session, "using LinearAlgebra;"]
Use session to build an external Julia function.
jlfn = ExternalFunction[session, "f(x)=tr(cholesky(x).U)"]
Use it as a normal function.
jlfn[mA]
Some Mathematica Exercises
Weights and Heights
Download the Kaggle heights and weights dataset in CSV format. (You may keep the current filename or choose your own.)
import the data in tabular format:
dfraw = Import[fname,"Tabular"].make a list-plot of the data:
ListPlot[dfraw -> {"Height(Inches)", "Weight(Pounds)"}]
Some Mathematica Resources
Introductory Materials
- An Elementary Introduction to the Wolfram Language
(by Stephen Wolfram) [Wolfram-2024-WolframMedia]_
- Mathematica Introduction
https://subversion.american.edu/aisaac/notes/mmaPart1.pdf (Please report typos!)
Videos
Introductory Videos
- Video by Socratica: Numerical Type In Mathematica
- Video: Drawing Tools by Noah Hardwicke
- Video: Mathematica Basics
by Jon McLoone
- Video: Hands-on Start to Mathematica
by Cliff Hastings
- Video by Sal Mangano: Introduction to Function
- Video by Richard Southwell: Mathematica For Beginners: The Basics
- Video by Ben Zwickl: Importing Data into Mathematica
http://www.youtube.com/watch?v=MmS3JNk7JE4 (his other videos are also good).
Differential Calculus
- Video by Socratica: Derivatives in Mathematica and the Wolfram Language
Introductory Books
- An Elementary Introduction to the Wolfram Language (2nd Edition}
[Wolfram-2024-WolframMedia]_ is free online.
- The Student's Introduction to Mathematica and the Wolfram Language
[Torrence.Torrence-2019-CambridgeUP]_ is a mathematically oriented introdution to Mathematica. Chapter 1 and 2 provide a gentle introduction to the language. Chapter 8 provides a good overview of Mathematica programming.
A Few Intermediate Books
- An Introduction to Modern Mathematical Computing: With Mathematica
Borwein, Jonathan M. and Matthew P. Skerritt (ISBN: 978-1-4614-4252-3)
- Wolfram Virtual Book
https://reference.wolfram.com/language/tutorial/VirtualBookOverview.html
- Practical Optimization Methods: With Mathematica Applications
by M. Asghar Bhatti; Springer (2000) ISBN-13 978-0387986319
- Multivariable Calculus with Mathematica 1st Edition
by Robert P. Gilbert, Michael Shoushani, Yvonne Ou; Chapman and Hall/CRC; 1st edition (November 25, 2020) ISBN-13 978-1138062689
A Few Advanced Books
- Mathematica Programming: An Advanced Introduction
[Shifrin-2009-Self]_ (free online at http://www.mathprogramming-intro.org/).
- Modeling naturecellular automata simulations with Mathematica
Gaylord, Richard J. and Kazume Nishidate isbn 0387946209
- Modern Differential Geometry of Curves and Surfaces with Mathematica 3rd Edition
by Elsa Abbena, Simon Salamon, Alfred Gray; Chapman and Hall/CRC; 3rd edition (June 21, 2006) ISBN-13 978-1584884484
- Computer Science with Mathematica
by Roman Maeder [Maeder-2000-CUP]_
Useful Weblinks
- A Primer on Association and Dataset
by Seth Chandler https://community.wolfram.com/groups/-/m/t/1167544
- Anderson-Moore Algorithm
Packages and Applications
In particular, see the discussion of folder structure here: https://reference.wolfram.com/workbench/index.jsp?topic=/com.wolfram.eclipse.help/html/tasks/applications/applications.html