Wolfram Language Tutorial

By Xah Lee. Date: . Last updated: .

This is a simple and basic Wolfram Language tutorial so that you can start coding it in 1 hour. This tutorial is designed especially if you are familiar with a industrial language, for example: python, JavaScript, php, ruby, lisp, java.

This tutorial focus on showing you how WolframLang works. You'll be able to code WolframLang in a hour, but also, make you understand symbolic pattern matching, that's the heart of WolframLang.

See also: Get Wolfram Language Free

Print Version Number

Print[ $Version ]
(* "12.2.0 for Microsoft Windows (64-bit) (December 12, 2020)" *)

Print[ $VersionNumber ]
(* 12.2 *)

Comment

(*this is comment.
can be multiple lines, can be nested *)

Print

Print
print a expression.
  • In notebook, every expression is auto printed after evaluation, unless it ends in semicolon.
  • In WolframScript, either use Print explicitly, or use command line option -print or -print all. [see WolframScript Tutorial]
Print[ "something" ]
(* Print return Null *)

String

String is quoted by double straight quote.

"this is a string"

string can be multi-line, can include any unicode characters:

x = "i ♥ cats
a → b"

(* 2 lines *)
\n
newline char in string.
\t
tab char in string.
\"
double quote in string.
"this is\na string"

"Said \"Yes\""

String Functions

Length:

StringLength["abc"] === 3

Join:

(* FullForm syntax *)
StringJoin["ab", "cd", "e"] === "abcde"

(* short syntax *)
"ab" <> "cd" <> "e" === "abcde"

More String Functions

There are about 100 functions on string. Here's just some of the most basic ones:

String generation:

StringRepeat
Repeat a string.
StringRepeat[ "x", 3 ] === "xxx"

Substring:

StringTake
Get substring, by position.
(* first 3 *)
StringTake["abcde", 3] === "abc"

(* last 3 *)
StringTake["abcde", -3] === "cde"

(* nth char *)
StringTake["abcde", {3}] === "c"

(* n to m *)
StringTake["abcde", {2,4}] === "bcd"
StringCases
Get parts by pattern.

String to list:

StringSplit
To list of parts.
(* split by whitespace *)
StringSplit[ "a b" ] === {"a", "b"}

(* by comma *)
StringSplit[ "a,b,c", "," ] === {"a", "b", "c"}

List to string:

StringRiffle
List to string

Insert and delete:

StringInsert
Insert by position
StringDrop
Delete parts by position
StringDelete
Delete parts by pattern
StringTrim
Remove whitespace

search, pattern matching:

StringQ
Check if is string.
StringStartsQ
StringEndsQ
StringMatchQ
StringContainsQ
StringContainsQ[ "some thing", "th" ]
(* True *)
StringFreeQ
StringPosition
StringCount
Count occurance

Note: function name that ends in Q means it always return one of the builtin symbols True or False. Q is for “question”. This is similar to lisp's functions ending in p for predicate, and in ruby and scheme lisp ends in a question mark.

string replace:

StringReplace
replace string by pattern.
StringReplace[ "some dogs" , {"dog" -> "cat"}] === "some cats"
StringReplacePart
replace string by position.
StringReplacePart[ "some dogs", "cat", {6, 8}] === "some cats"

format:

ToString
Convert number or any expression to string.
StringTemplate
Template system with placeholders

string pattern:

RegularExpression
Regular expression. Used in functions that take a string pattern.
StringExpression
A string pattern system based on Wolfram's symbolic pattern matching system. More powerful than regex. Used in functions that take a string pattern.

List All Functions, Find Function

Coding in WolframLang is essentially just about calling functions, nothing else. Any software written in WolframLang, the entire source code, is one nested sequence of function calls. Even when you write code to define a function, or assign a value to variable, you are calling functions to do so.

It's essential to be able to find the function you want.

All WolframLang's function names are long and descriptive.

Here's how to print all functions containing the word String:

?*String*

or the FullForm

Information["*String*"]

If you just want a list of function names, use:

Names["*String*"]

This is helpful when you are trying to find a function.

Get help of a function

Type ?FunctionName. Works in notebook. If in shell, the result is hard to read.

(* return help string of Map *)
?Map

(* FullForm syntax *)
Information[ "Map" ]

Arithmetic

3+2 === 5

(* FullForm syntax *)
Plus[3, 2] === 5
3-2 === 1

(* FullForm syntax *)
Plus[3,-2] === 1
3 * 2 === 6

(* FullForm syntax *)
Times[3, 2] === 6
3/2. == 1.5

(* FullForm syntax *)
Times[3, Power[2., -1]] == 1.5
3^2 === 9

(* FullForm syntax *)
Power[3, 2] === 9
(* remainder, or modular arithmetic *)
Mod[5, 2] === 1
EvenQ[4] === True

OddQ[3] === True

Symbolic Result vs Numerical Result

All computation are by default done symbolically, returning symbolic or exact result. For example, 3/2 return just itself, not 1.5. And 6/4 return the rational number 3/2. Another example: 3/2 + 5/9 return 37/18

3/2
(* return itself *)

3/2 + 5/9
(* return 37/18 *)

If one of your expression contains approximate number, then the result may not be exact.

3/2 + 5/9.
(* return 2.05556 *)

Force Numerical Result

To force numerical result, use N[expr]. When N is wrapped around expression, the entire expression is computed numerically.

N[3/2]
(* return 1.5 *)

A common way to use N is via postfix notation, That is, N[expr] is the same as expr//N

x = ((1/2)^5 + (3/2)^2)^3
(* 389017/32768 *)

x //N
(* 11.871856689453125 *)

List, and Everything Is a Expression

List is the core data structure of WolframLang.

WolframLang source code is made of expressions. Every part in source code, is expression. (there is no such thing as “statements”, “commands”, “directives” etc.) Everything is a expression.

Every expression in WolframLang is either a single atom (such as a number), or a list of atoms, in the form e0[e1, e2 ]. Each of the e is a atom or a list of atom. A atom is a number, or a symbol (usually function or variable names), a string, or a special character such as \[Pi]. The form e0[e1, e2 ] is called FullForm.

{3, 4, 5}

(* FullForm syntax *)
List[ 3, 4, 5 ]

List can nest in any way.

{3, 4, {1,2}, 5}

Generate List

Range
return a flat list. Like python range but more powerful. Argument needs not be integer.
Range[5]
(* {1, 2, 3, 4, 5} *)

(* min to max *)
Range[4,8]
(* {4, 5, 6, 7, 8} *)

(* in steps of 0.5 *)
Range[1, 3, 0.5]
(* {1., 1.5, 2., 2.5, 3.} *)

(* in step of 1/2, symbolic *)
Range[1, 3, 1/2]
(* {1, 3/2, 2, 5/2, 3} *)

(* step can be negative *)
Range[1, -1,  -0.5]
(* {1., 0.5, 0., -0.5, -1.} *)

(* any arg can be symbolic *)
Range[0, 3 Pi,  Pi/2]
(* {0, Pi/2, Pi, (3*Pi)/2, 2*Pi, (5*Pi)/2, 3*Pi} *)
Table
For generating nested list (n-dimensional matrix). Like python's list comprehension but more powerful.
(* repeat n times *)
Table[ x, {3}]
(* {x, x, x} *)

(* eval with x from 1 to max *)
Table[ x, {x, 3}]
(* {1, 2, 3} *)

(* eval with x from min to max, *)
Table[ x, {x, 6, 9}]
(* {6, 7, 8, 9} *)

(* eval with x from min to max in step 0.5 *)
Table[ x, {x, 1, 3, 0.5}]
(* {1., 1.5, 2., 2.5, 3.} *)

(* symbolic *)
Table[ x, {x, 1, 3, 1/2}]
(* {1, 3/2, 2, 5/2, 3} *)

(* first arg can be any expression *)
Table[ {x, x^2}, {x, 1, 5}]
(* {{1, 1}, {2, 4}, {3, 9}, {4, 16}, {5, 25}} *)

Table[ Sin[x], {x, 0, 2 Pi, Pi/4}]
(* {0, 1/Sqrt[2], 1, 1/Sqrt[2], 0, -(1/Sqrt[2]), -1, -(1/Sqrt[2]), 0} *)
(* 2 dimensions *)
Table[ {x, y}, {3}, {2}]
(* {{{x, y}, {x, y}}, {{x, y}, {x, y}}, {{x, y}, {x, y}}} *)

Table[ {x, y}, {x, 3}, {y, 2}]
(* {{{1, 1}, {1, 2}}, {{2, 1}, {2, 2}}, {{3, 1}, {3, 2}}} *)

(* 3 dimensions. *)
Table[ {x, y, z}, {x, 1, 3}, {y, 8, 9}, {z, 0, 1, 0.5}]
(* {{{{1, 8, 0.}, {1, 8, 0.5}, {1, 8, 1.}}, {{1, 9, 0.}, {1, 9, 0.5}, {1, 9, 1.}}}, {{{2, 8, 0.}, {2, 8, 0.5}, {2, 8, 1.}}, {{2, 9, 0.}, {2, 9, 0.5}, {2, 9, 1.}}}, {{{3, 8, 0.}, {3, 8, 0.5}, {3, 8, 1.}}, {{3, 9, 0.}, {3, 9, 0.5}, {3, 9, 1.}}}} *)

(* complex expression *)
Table[ f[x+y]*z, {x, 3}, {y, 3}, {z, 2}]
(*
{
{{f[2], 2*f[2]}, {f[3], 2*f[3]}, {f[4], 2*f[4]}},
{{f[3], 2*f[3]}, {f[4], 2*f[4]}, {f[5], 2*f[5]}},
{{f[4], 2*f[4]}, {f[5], 2*f[5]}, {f[6], 2*f[6]}}}
*)

Note: Table is the most powerful way to generate a list, and is most used. Master it.

Nested List, Tree, Rectangular Array, Dimensions

List is critically important in WolframLang. Here's some notion on tree, array, position, you need to understand.

rectangular array
(aka n-dimensional array/matrix) A nested list where there are same number of elements at each level of nesting. e.g. {{3,1}, {4, 5}, {2, 4}}.
tree
(aka jagged array) A arbitrarily nested list. e.g. {3, {4, 5}, {9}}
Dimensions
Shape of rectangular array. A list of integers that is the count at each level of nesting. e.g. Dimensions on a 3 by 2 matrix {{3,1}, {4, 5}, {2, 4}} return {3,2}
Dimensions[{a, b}]==={2}
Dimensions[{x, y, z}]==={3}
Dimensions[{{a, b}, {c, d}}]==={2, 2}
Dimensions[{{{a}, {b}}, {{c}, {d}}}]==={2, 2, 1}

(* jagged array. return the max regularity *)
Dimensions[{{{a}, {b}}, {{c}, d}}]==={2, 2}
ArrayDepth
Length of dimensions. The number of indexes needed to specify the position of a element in a n-dimensional array. ArrayDepth[expr] is same as Length[Dimensions[expr]]

Position of Item in a Expression

Given a expr, we use a list of integers to specify any part in the expr. e.g. {3,2,4} means 3rd part at 1st level, then 2nd part of that, then 4th part of that.

Extract
return the part of expr at a given position.
(* a tree *)
tr = {a, {{b,c}, d}, e};

(* get the element of a given position *)
Extract[ tr, {1} ] === a
Extract[ tr, {2} ] === {{b, c}, d}
Extract[ tr, {3} ] === e
Extract[ tr, {2, 1} ] === {b, c}
Extract[ tr, {2, 1, 1} ] === b
Position
Return the position of a sub expression in a given expression. The “sub expression” can be any single element (a atom), or a more complex sub expression.
(* a tree *)
tr = {a, {{b,c}, a}, e};

(* using Position to get the index of a sub expr. It return a list of positions, because the expr may appear in multiple places *)

(* position of e is {3} *)
Position[ tr, e ] === {{3}}

(* position of b is {2, 1, 1} *)
Position[ tr, b ] === {{2, 1, 1}}

(* position of a is {1} and {2, 2} *)
Position[ tr, a ] === {{1}, {2, 2}}

(* position of {b, c} and {2, 1} *)
Position[ tr, {b, c} ] === {{2, 1}}

List Elements

There are many functions that extract or insert or delete list elements. Here's the most frequently used ones.

Note: They always return a new list. If you want to change a variable that holds a list, assign it back to the variable.

get elements:

Part
(Short syntax: expr[[n]] is same as Part[expr,n] )
Get elements by position.
expr[[i]]
ith part of expr. If i is negative, count from right.
expr[[i,j,]]
same as expr[[i]][[j]]

expr[[{i1,i2,etc}]]
a list of the parts i1, i2, etc.
expr[[m;;n]]
parts m through n. (note: a;;b is short for Span[a,b])
expr[["key"]]
value of the key "key" in an association expr.
expr[[Key[k]]]
the value associated with an arbitrary key k. k is not necessarily a string.

Example of getting 1 element:

x = {a, b, c, {d1, d2}, e}

(* get 2nd element *)
Part[x, 2] === b

(* short syntax *)
x[[2]] === b

(* count from right *)
x[[-2]] === {d1, d2}

Example of getting a nested element that needs 2 indexes:

x = {a, b, c, {d1, d2}, e}

(* from index 4, 1 *)
x[[4,1]] === d1

Example of getting a span of elements:

x = {a, b, c, {d1, d2}, e}

(* 2 to 4th elements *)
x[[2;;4]] === {b, c, {d1, d2}}

Example of getting a list of single elements:

x = {a, b, c, {d1, d2}, e}

(* 2nd and last *)
x[[{2,-1}]] === {b, e}
Select
Get elements by a filter function
Cases
Get elements by pattern

add element:

Append
Add to end
Prepend
Add to begin

delete element:

Drop
Delete a range of elements by position
Delete
Delete elements by positions
DeleteCases
Delete elements by pattern
DeleteDuplicates
Delete duplicates

check existence:

MemberQ
Check existence by pattern
Count
Count by pattern

replace:

ReplacePart
Replace by pattern

group into sublists:

Partition
Cut into sublist
GroupBy
To association list

Function

Function
(Short syntax: Function[{x,y},x+y] is same as Function[#1+#2] or #1+#2&)
Represent a function. (like lisp's “lambda”.)
Function[{x1,x2 }, body] represent a function with formal parameters x1,x2 etc. When the function is called, body is evaluated, with formal parameters replaced by arguments. For example, Function[{x,y}, x+1][3, 4] return 7.

To define a function, use Function.

(* a function that adds 1 *)
f = Function[ {x}, x + 1 ]

(* call it *)
f[3] === 4

(* add 2 numbers *)
f2 = Function[ {x,y}, x + y ]

f2[3,4] === 7

function arguments in Function can be represented by #.

This makes the code shorter.

f1 = Function[ {x,y}, x + y ];
(* same as *)
f2 = Function[ #1 + #2 ];

f2[3,4] === 7

Function[body] has the short syntax body&

This makes the code even shorter, and is often used.

f1 = Function[ #1 + #2 ];
(* same as *)
f2 = ( #1 + #2 &);

f2[3,4] === 7

Doc String for Function

you can give your function (any symbol) a docstring, like this:

add2::usage = "add2[x] returns x plus 2."

When user type ?add2, the usage string will be shown.

The FullForm of

symbol::usage

is

MessageName[ symbol , "usage" ]

Using Pattern Matching to Define a Function

function can also be defined by using pattern matching.

(* function that adds 2 numbers *)
f1[x_ , y_] := x + y;

f1[3,4] === 7

The FullForm syntax for

f1[x_ , y_] := x + y

is

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

This means, define a delayed transformation rule. f1[x_ , y_] means a pattern that's f followed by square brackets, with 2 anything inside, named x and y. Whenever that form occur when evaluating expression, replace it by x + y .

Transformation of expression by symbolic pattern matching is a major mechanism of how WolframLang does computation. (called term rewriting system) We'll discuss pattern matching more later.

Apply function to list

Map
(Short syntax: f /@ expr is same as Map[f,expr] )
Like many language's map, but can map to specific level of a nested list, such as at leafs of a tree. e.g. Map[ f, {1, {{2}, 3}}, {-1} ] === {f[1], {{f[2]}, f[3]}}

Map a builtin function to list:

ii = {1, {2, 3}};

Map[ Length, ii ] === {0, 2}

(* short syntax *)
Length /@ ii === {0, 2}

Map a user function to list:

ii = {1, {2, 3}};

Map[ Function[{x}, x^2 ], ii ] === {1, {4, 9}}

(* short syntax *)
(#^2 &) /@ ii === {1, {4, 9}}

Map a function to different levels of a rectangular array:

x = Table[{i, j}, {i, 2}, {j, 2}]
(* {{{1, 1}, {1, 2}}, {{2, 1}, {2, 2}}} *)

(* map to 1st level, as in flat map *)
Map[ f, x, {1} ]
(* {f[{{1, 1}, {1, 2}}], f[{{2, 1}, {2, 2}}]} *)

(* map to 2nd level *)
Map[ f, x, {2} ]
(* {{f[{1, 1}], f[{1, 2}]}, {f[{2, 1}], f[{2, 2}]}} *)

(* map to 3rd level *)
Map[ f, x, {3} ]
(* {{{f[1], f[1]}, {f[1], f[2]}}, {{f[2], f[1]}, {f[2], f[2]}}} *)

(* map to deepest level, the leafs. in this case, same as 3rd level *)
Map[ f, x, {-1} ]
(* {{{f[1], f[1]}, {f[1], f[2]}}, {{f[2], f[1]}, {f[2], f[2]}}} *)
WolframLang level of nesting 2021-11-23
WolframLang map to different levels of nesting

Map to a tree.

tree = {a, {{b,c}, d}, e};

(* map to top level *)
Map[ f, tree ] === {f[a], f[{{b, c}, d}], f[e]}

(* same as 1st level *)
Map[ f, tree, {1} ] === {f[a], f[{{b, c}, d}], f[e]}

(* map to leafs *)
Map[ f, tree, {-1} ] === {f[a], {{f[b], f[c]}, f[d]}, f[e]}
MapIndexed
Like Map, but also feed the index info to the function. Useful when you want to “iterate” over array but need the index, not just value. The function receive 2 args, first is value, second is the position of the value. The position is in standard form {i,j,...}, a list of indexes that specify the item position.
MapIndexed[ f, {a,b,c} ] == {f[a, {1}], f[b, {2}], f[c, {3}]}
MapThread
Like Map, but for functions that take more than 1 arg.
x = {{1, 2, 3} , {a, b, c} };
MapThread[ f, x ] == {f[1, a], f[2, b], f[3, c]}
li = {{1, 2, 3}, {a, b, c}, {x, y, z} };
MapThread[f, li] == {f[1, a, {{1, 2, 3}, {a, b, c}}], f[2, b, y], f[3, c, z]}

Variables

Set
(short syntax: x=y is same as Set[x,y])
Create a transformation rule so that expr on left-hand-side transform to right-hand-side. The right-hand-side is evaluated befor setting the rule.
(* global variable, of current session  *)
x = 5
SetDelayed
(short syntax: x:=y is same as SetDelayed[x,y])
Like Set, but right-hand-side is evaluated when at the time the left-hand-side is encountered.
Clear
Clear the transform rules of symbols.
Clear[x]

(* clear multiple variables *)
Clear[x1,x2]

(* clear all variable starting with x *)
Clear["x*"]
(* BE CAREFUL WITH THIS *)
Remove
Remove symbols from the system. (removes all transformation rules with it too) Note: this is more advanced. Usually you just need Clear.

Local Variable

Module
Eval code with temp local variables. Module[{symbols}, body] eval body, with temp variables symbols. Return the value of body.

To create local variables, use Module[{var1,var2}, expr] . Each of the var1 can have the form var1=val1

This is lexical scoped.

x = 5;
Module[{x}, x = 3; x^2]
(* 9 *)

x
(* x is still 5 *)
Module[{x = 3}, x^2]
(* 9 *)

To assign variable that depends on previous variable value, put code in body

(* later values in variable is not available *)
Module[{x=2, y=x}, y]
(* return the symbol x *)

(* to assign variable that depends on previous variable value, put code in body *)
Module[{x=2, y},
y=x;
y]
(* 2 *)

CompoundExpression and Semicolon

CompoundExpression[expr1,expr2, ]
(short syntax: expr1;expr2;)
Eval all arguments and return the value of last argument.

(CompoundExpression is similar to lisp's progn)

CompoundExpression (or the semicolon) is frequently used in Function, Module, If, or anytime when you need to do several computation as a single expression as one arg to function.

Examples:

Module[{}, expr1; expr2; ... ]

If[{}, doTrueExpr1; doTrueExpr2; , doFalseExpr1; doFalseExpr2; ]

Function[{}, expr1; expr2; ]

Often, even if you do not need CompoundExpression, you'll find it convert to put a semicolon at end of some expression. In particular, after assignment. It has the effect of suppressing output.

For example, x=3 return 3, but x=3; return Null and is not printed.

[see WolframLang Syntax/Operators]

True and False

True and False are builtin symbols to represent true and false.

3 > 2
(* return True *)

Logic Operators

And
(short syntax: x&&y is same as And[x,y])
Return True when all args are True.
x = True;
y = True;
x && y
Or
(short syntax: x||y is same as Or[x,y])
Return True if any args is True.
x = True;
y = False;
x || y
Not
(short syntax: !x is same as Not[x])
Return True if arge is False, and vice versa.
x = False;
! x

Comparison Test

Equal
(short syntax: ==)
return True if two exprs are equal, False if not. If equality cannot be determined, return whole expr unchanged.
x = 4;
y = 4;
x == y
result = (a == 3);

result
(* result is a == 3, because the equality cannot be determined *)

(* if we replace a by 3, then True *)
ReplaceAll[ result , a -> 3 ]
(* True *)
Unequal
(short syntax: !=)
Similar to Not[Equal[x,y]].
x = 3;
y = 4;
x != y
SameQ
(short syntax: ===)
tests if two expr are symbolically identical. For example, 3 === 3.0 return False because one is exact number while the other is approx. But 3 == 3.0 return True.
x = 3;
y = 4;
x === y
UnsameQ
(short syntax: =!=)
Same as Not[SameQ[x,y]] .
x = 3;
y = 4;
x =!= y
Greater
(short syntax: >)
x = 3;
y = 4;
y > x
GreaterEqual
(short syntax: >=)
x = 3;
y = 4;
y >= x
Less
(short syntax: <)
x = 3;
y = 4;
x < y
LessEqual
(short syntax: <=)
x = 3;
y = 4;
x <= y

If then

If[3 > 2, "yes", "no"]

Everything in Wolfram Language is a expression. That means, everything return a value, including the If function. There is no such thing as statements.

Note: if a function's argument requires True/False, such as the first argument of If[test,a,b] , the expression test must eval to exactly True or False, else the entire expression is returned symbolically as is. Example:

result = If[x, "yes", "no"]

result
(* If[x, "yes", "no"] *)
(* The symbolic expression is returned unchanged. because x is not one of the exact symbols True, False *)

(* now assign a val to x *)
x = 3 < 4;

(* result changed *)
result
(* "yes" *)

There is no “coerce” or forcing or “convert” a value to be True/False. Your code need to eval to True/False explicitly.

Loop (procedural style)

Wolfram Language is a function language. However, it supports the traditional loops constructs such as for-loop, while-loop, do-loop. In general, you should not use them, because they are less efficient and ugly.

For-loop:

For[i = 1, i < 9, i++, Print[i]]

While-loop:

n = 1; While[n < 4, Print[n]; n++]

Here's Do-loop. It has many parameters controlling the iteration and nested iteration.

Do[expr,n]
evaluate expr n times.
Do[expr,{i,iMax}]
evaluate expr with the variable i successively taking on the values 1 through iMax (in steps of 1).
Do[expr,{i,iMin, iMax}]
start with iMin.
Do[expr,{i,iMin, iMax, di}]
use steps di.
Do[expr,{i,iMin, iMax, di}, {j,jMin, jMax, dj} ]
evaluate expr looping over different values of j etc. for each i.
Do[expr,{i,{i1, i2, i3 }}}]
use the successive values i.

Example:

Do[Print[n^2], {n, 4}]
(* 1 4 9 16 *)
Do[Print[n,m], {n, 4}, {m, 2}]
(* 11 12 21 22 31 32 41 42 *)

Important: the forms

is called iteration specification. It is used in many of Wolfram Language functions.

loop (functional style)

In general, you should use the following functions for loop or iteration. These are functional style constructs.

recursion of function with 1 arg

Nest
Recursion of a function n times.
Nest[f, x, 3] === f[f[f[x]]]
NestList
Like Nest but return all steps.
NestList[f, x, 3] === {x, f[x], f[f[x]], f[f[f[x]]]}
NestWhile
Like Nest, but with a condition when to stop.
NestWhileList
Like NestWhile but return all steps.
FixedPoint
Recursion of a function until result no longer changes.
FixedPointList
Like FixedPoint but return all the steps.

recursion of function with 2 args

Fold
Similar to reduce in many programing languages.
Fold[f, x, {a,b,c}] === f[f[f[x, a], b], c]
FoldList
Like Fold but return all the steps.
FoldList[f, x, {a,b,c}] === {x, f[x, a], f[f[x, a], b], f[f[f[x, a], b], c]}
FoldWhile
Like Fold but with a condition test to stop.
FoldWhileList
Like FoldWhile but return all the steps.

Principles of WolframLang

Summary of what you learned:

There are 2 ways WolframLang does computation:

We have seen some basic symbolic pattern transformation, when we defined a function by pattern, using SetDelayed:

f1[x_ , y_] := x + y;

(*
FullForm:

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

*)

and when we used Set:

Set[x,3]

In either case, it tells Wolfram Engine that whenever it sees form on the left-hand-side, change it to the right-hand-side.

continue to WolframLang Syntax/Operators

WolframLang Tutorial