# := vs <-

The familiar assignment operator from C, `=`, splits into two forms in
plover: `:=, <-`. In short, `:=` is used to declare and initialize a
variable (whose type will generally be inferred), while `<-` is used to
mutate a variable already in scope.

See definitions [1] and locations [2].

# Value of a Block

As described in sequencing [3], the value of a sequence expression `(a ; b)` is
the value of `b`. A common error is to call a function as the last statement
of a block which is intended to have void type.

For instance,

f (x :: int) :: () := ( printf "x: %d" x; );

will produce an error, because the (often ignored) return type from printf is
actually `int`. The simplest fix in this case is to add a void literal,
`()`:

f (x :: int) :: () := ( printf "x: %d" x; (); );

Another consequence of this convention is that the `return` keyword is
optional on the last statement of a function. It is still useful as an early
return mechanism, of course.

# if/then/else

The branches of an `if` expression must have the same type. When the `else` branch is omitted, it has void type. Hence

if condition then printf "hi there\n";

is incorrect.

Notably, when `return` is used, the expression being returned is checked
against the return type of the enclosing function, but the type of the
`return` expression itself changes to match what is expected by its immediate
context. Thus, the following is ok:

f (x :: int) :: int := ( if x > 0 then return x; return -x; );

but, when possible, this is a better style:

f (x :: int) :: int := if x > 0 then x else -x;

.

# Delimiters

A block is typically delimited with parentheses: `(a; b; ...)`. Semicolons
(`;`) must separate statements within a block. Top-level definitions and
`extern` definitions are, likewise, separated by semicolons.

Warning

In the face of a troubling parsing or typechecking error, make sure you haven't left out any semicolons.

# Vectors and Matrices

The size of a vector object is represented, internally, as a list of Plover expressions. Each position in this list is called an "index", and the expression at a given index is called a "bound" or a "dimension." This is meant to coincide with the usual language for discussing tensors. We will refer to the number of indices as the object's rank.

Generally we call rank-1 and rank-2 objects vectors and matrices, respectively.

Plover overloads multiplication [4] to handle certain frequent use cases. In
particular, for a matrix-vector product `(M*v)`, the vector is interpreted as
a column vector. The vector-matrix product is not implemented; instead, you may
use `(v^T*M)`. Note that the builtin transpose operator converts a rank-1
vector of dimension `n` into an explicit, rank-2, `[1,n]` matrix. For this
reason, taking a transpose twice may not return an object identical to the
initial one. Some discussion on the complexity of this issue: julia [7].

# Indexing

Plover indexing is 0-based. Matrices are row-major. See ranges [5] and slicing [6] for more information.

# References

[1] | http://swift-nav.github.io/plover/reference.html#variable-definitions |

[2] | http://swift-nav.github.io/plover/reference.html#locations |

[3] | http://swift-nav.github.io/plover/reference.html#sequencing |

[4] | http://swift-nav.github.io/plover/reference.html#multiplication |

[5] | http://swift-nav.github.io/plover/reference.html#ranges |

[6] | http://swift-nav.github.io/plover/reference.html#slices |

[7] | https://github.com/JuliaLang/julia/issues/4774 |