Skip to content

Syntax

Postfix application (//)

expr // f is equivalent to f[expr]. The // operator has the lowest precedence, so it applies to the entire left-hand expression.

$ wo '4 // Sqrt'
2
$ wo '{1, 2, 3} // Length'
3

Because it really is f[expr], a Sequence on the left spreads into f's arguments rather than arriving as one:

$ wo 'Sequence[1, 2] // f'
f[1, 2]

A Sequence one level down has already been spread by the head holding it, so f still sees a single argument:

$ wo '{Sequence[1, 2]} // Length'
2

Postfix after an operator chain:

$ wo '1 + 2 // ToString'
3
$ wo 'Sqrt /@ {1, 4, 9} // Length'
3

Postfix with a curried function call:

$ wo '{1, 4, 9} // Map[Sqrt]'
{1, 2, 3}

Chained postfix:

$ wo '16 // Sqrt // Sqrt'
2

Prefix application (@) with comparison operators

@ has higher precedence than ==, so f@x == y means (f@x) == y.

$ wo 'Length@{1,2,3} == 3'
True
$ wo 'Length@Union@{1,2,1} == Length@Union[{1,2,1} + Range@3] == 3'
False

Apply (@@) and Map (/@) inside an implicit product

@@, @@@ and /@ bind tighter than multiplication, so in a b @@ c the operator reaches only the factor next to it — whether the leading factor is a number or a function call:

$ wo '2 Times @@ {3, 4}'
24
$ wo 'Sum[i, {i, 0, 2}] Times @@ {3, 4}'
36
$ wo 'Length[{a, b}] f /@ {x, y}'
{2*f[x], 2*f[y]}

Rule (->) and RuleDelayed (:>) as general operators

-> creates a rule, and :> creates a delayed rule. These can be used anywhere in expressions, not just in replacement contexts.

$ wo '{1, 2} -> 3'
{1, 2} -> 3
$ wo 'Frame -> All'
Frame -> All
$ wo 'x :> x + 1'
x :> x + 1

Multi-index Part extraction ([[i, j]])

expr[[i, j]] extracts nested parts: first part i, then part j from the result.

$ wo 'x = {{a,b},{c,d}}; x[[2,1]]'
c
$ wo 'x = {{a,b},{c,d}}; x[[1,2]]'
b
$ wo 'FullForm[a[[1,2,3]]]'

Part::partd: Part specification a[[1,2,3]] is longer than depth of object.
.* (regex*)
FullForm[a[[1,2,3]]]

Spaces inside the Part brackets (x[ [i] ])

The two brackets of [[…]] are separate tokens, so whitespace, newlines and comments may sit between them — a lone […] can never start an expression, so x[ [i] ] is unambiguously Part[x, i].

$ wo 'myList = {10, 20, 30}; myList[ [ {1, 2} ] ]'
{10, 20}
$ wo 'ToString[Hold[a[ (* index *) [1] ]], InputForm]'
Hold[a[[1]]]

Part of an operator expression ((a /. b)[[i]])

[[…]] binds tighter than every infix operator, so a parenthesized operator expression keeps its parentheses when echoed — dropping them would change what re-parsing produces.

$ wo '({9, 8} /. 8 -> 5)[[1]]'
9
$ wo 'ToString[Hold[(a /. b :> c)[[1]]], InputForm]'
Hold[(a /. b :> c)[[1]]]

Increment (++) and Decrement (--)

x++ increments x by 1 and returns the old value. x-- decrements x by 1 and returns the old value.

$ wo 'x = 5; x++; x'
6
$ wo 'x = 10; x--; x'
9
$ wo 'x = 0; Do[x++, {i, 1, 5}]; x'
5

Extraction and application in a chain (a["k"][[1]]["j"])

[[...]] and [...] alternate freely, so a nested association is walked in one expression.

$ wo 'g = <|"e" -> {<|"d" -> 9|>}|>; g["e"][[1]]["d"]'
9

The same holds for a slot, which is what sorting associations by a keyed field relies on.

$ wo 'SortBy[{<|"pos" -> {3, 1}|>, <|"pos" -> {1, 2}|>}, #["pos"][[1]] &]'
{<|pos -> {1, 2}|>, <|pos -> {3, 1}|>}

A statement sequence closed by &

A & with no statement between it and the preceding ; turns everything before it into the body of a pure function, and that function takes the usual continuation — stmt; & /@ list is (stmt;) & /@ list.

$ wo 'Module[{r = {}}, AppendTo[r, #^2]; & /@ {1, 2, 3}; r]'
{1, 4, 9}

Part Assignment

Assigning to a Part expression modifies the list in-place.

$ wo 'x = {1, 2, 3}; x[[2]] = 99; x'
{1, 99, 3}
$ wo 'x = {{1, 2}, {3, 4}}; x[[2, 1]] = 99; x'
{{1, 2}, {99, 4}}
$ wo 'x = {a, b, c}; x[[3]] = z; x'
{a, b, z}

Rule Pattern Evaluation

Both sides of -> (Rule) are evaluated.

$ wo '{2, First@{1}} -> "Q"'
{2, 1} -> Q

Stored Anonymous Functions

Anonymous functions can be stored in variables and called later.

$ wo 'f = (# + 1) &; f[5]'
6
$ wo 'g = (# * #2) &; g[3, 4]'
12
$ wo 'f = # &; Map[f, {1, 2, 3}]'
{1, 2, 3}

Nested Function Slot Scoping

Slots (#) bind to the innermost & (Function).

$ wo '(# + 1 &) /@ {10, 20, 30}'
{11, 21, 31}

Head-Constrained Patterns (_Head)

A blank can be restricted to a head, with or without a name. Each head is a separate definition, so the argument's head selects which one fires.

$ wo 'f[_String] := "a string"; f[_Integer] := "an integer"; f[1]'
an integer
$ wo 'f[_String] := "a string"; f[_Integer] := "an integer"; {f[2], f["a"]}'
{an integer, a string}
$ wo 'g[x_Integer] := x^2; g[_] := "other"; {g[3], g[a]}'
{9, other}

Alternatives (|)

The | operator represents alternatives in pattern matching.

$ wo 'Cases[{1, "a", 2, "b"}, _Integer]'
{1, 2}
$ wo 'Cases[{1, 2, 3, 4, 5}, Except[2 | 4]]'
{1, 3, 5}

Optional Pattern Defaults (:)

Writing pattern : value gives an argument a default, so the argument may be left out. The short form names a blank (x_ : 2):

$ wo 'f[x_ : 2] := x^2; {f[3], f[]}'
{9, 4}

The default may be written on any pattern, not just a named blank. Naming the pattern first (x : … : 2) makes the colon close the whole named pattern, so a pattern test or an alternation gets the default:

$ wo 'f[x : x_?NumericQ : 2] := x^2; {f[3], f[], f[a]}'
{9, 4, f[a]}
$ wo 'f[x : _Symbol | _Integer : 2] := x^2; {f[3], f[a], f[]}'
{9, a^2, 4}

Without that leading name the colon binds tightly to the term written in front of it, which is rarely what you want: in _Symbol | _Integer : 2 the default lands on _Integer alone, and an Optional buried inside an alternation makes no argument optional:

$ wo 'g[_Symbol | _Integer : 2] := 7; {g[3], g[a], g[]}'
{7, 7, g[]}

After a ? the colon is read as part of the test, so _?NumericQ : 2 is PatternTest[_, Pattern[NumericQ, 2]] and matches nothing:

$ wo 'h[x_?NumericQ : 2] := x^2; {h[3], h[], h[a]}'
{h[3], h[], h[a]}

The default value is taken as written — it is not checked against the pattern it stands in for:

$ wo 'f[x : x_?NumericQ : 2] := x^2; {f[3], f[]}'
{9, 4}

Comments ((* … *))

A comment is skipped wherever whitespace is, and what it holds is never read as code — not even a bracket, a quote or a semicolon left over from commented-out code:

$ wo 'Hold[f[a (* endof For[ i *); b]]'
Hold[f[a; b]]
$ wo '{1 (* a ) b *); 2}'
{2}
$ wo 'Range[5][[2 (* [ *) ;; 3]]'
{2, 3}

Comments nest, so a commented-out block that itself holds comments is skipped whole:

$ wo '1 + (* outer (* inner *) still a comment *) 2'
3