In this and the next chapters, we briefly explain the syntax of Egison. This chapter explains an aspect of Egison as an ordinal purely functional programming language. We will explain patterns and pattern-matching, the most important feature of Egison in the next chapter. The readers familiar to other functional programming languages can skip this chapter.

## Top Expressions

`define`

and `test`

Expressions

We first explain two kinds of *top expressions*, `define`

expressions and `test`

expressions.
A `define`

expression binds the variable to the value or the function.
A `test`

expression evaluates the given expression.
We can try a function defined with a `define`

expression using a `test`

expression.
We can omit `test`

.

`load`

and `load-file`

Expressions

We can load Egison libraries with `load`

expressions.

To load your own program, we can use `load-file`

expressions.
A `load-file`

expression takes a full-path to the Egison program file.

## Built-in Data

Boolean values, integers, float numbers, and characters are implemented as built-in data in Egison.

### Boolean Values

`#t`

represents true.

`#f`

represents false.

### Integers

A string which consists of only numbers is a number literal.
An integer literal is a number literal or concatenation of `-`

and a number literal.
We support complex numbers as built-in data.

### Rational Numbers

We are supporting rational numbers.

### Floats

A floating-point literal is concatenation of an integer literal, `.`

, and a number literal.

### Characters

A character literal is a character enclosed in single quotes.

### Strings

A string literal is a string enclosed in double quotes.

### Undefined

`undefined`

is a useful built-in data that you can put where you have not written yet.

## Objects

### Six Enclosures

First of all, we explain the enclosures of Egison.
Perhaps you are surprised at how many kinds of enclosures in Egison when you first see code of Egison.
In Egison, there are five kinds of enclosures, i.e. parentheses `(`

`)`

, brackets `<`

`>`

, square brackets `[`

`]`

, braces `{`

`}`

, double brackets `[|`

`|]`

, and double braces `{|`

`|}`

.
They represents procedure call, an inductive datum, a tuple, a collection, an tensor, and a hash.
Roughly speaking, you should use parentheses as LISP, brackets when you want to create patterns or your own data, double brackets to create a tensor, and double braces to create an hash.
Square brackets and braces are both used to collect values.
The difference between them is the number of values.
The former are used to collect the fixed number of values, but the latter are used to collect the others.

### Inductive Data

` <`*Identifier* *value* ...>

We can create an new object combining objects. It is called an inductive datum. An inductive datum can have values. In particular, it can have any inductive data. This is why it is called "inductive". Note that the name has to start with uppercase.

### Tuples (Multiple Values)

` [`*value* ...]

A tuple is expressed as a sequence of elements enclosed in square brackets.

If a tuple consists of an element, the tuple and the element are the same.

### Collections

` {`*value* ...}

A collection is a sequence of elements enclosed in braces. Unlike a tuple, a collection of an element and its unique element differ.

A collection may contain a collection as its element.
Generally, an element of a collection that is an element of a collection isn't an element of the outer collection.
`@`

placed before a collection breaks the collection.
Then, an element of a collection with `@`

that is an element of a collection is an element of the outer collection.
Using this notation, you can construct a collection from subcollections.

### Tensors

` [|`*value* ...|]

a tensor is a sequence of elements enclosed in double brackets.
Adding an underscore `_`

and an index at the end, you can get the associated element of a tensor.
If the index is larger than the size of a tensor, you will get an error.

We can get the size of a tensor with tensor-size.

a tensor can have another tensor as its element. It allows us to use multi-dimensional tensors.

Egison prepares special syntax for tensors. They are generate-tensor, tensor-size, and tensor-ref. The former gives an easy way to create complicated tensors, and the latter shows the size of tensors. The details are described in each subsection.

### Hash Maps

` {|[`*key* *value*] ...|}

A hash map is a sequence of key-value pairs enclosed in double braces.
Adding an underscore `_`

and an index at the end, we can get the associated element of a hash map.
If the index is not a key of a hash map, we will get undefined.

## Syntax of Egison

`lambda`

expressions

` (lambda [`*variable* ...] *formula*)

Lambda expressions make functions as other functional programming languages.
It takes two arguments.
The first one is a tuple of variables, which are the dummy variables of the function.
Note `[$x]`

and `$x`

are the same.
The second argument is a formula, which is the body of the function.

From ver.3.0, a lambda expression is equipped with simpler notation.
In this notation, you can omit to write "lambda" and the arguments of the function.
You can refer to the i-th argument by writing concatenation of `$`

and i.
If the order of occurrences of the arguments is the same as the order of the arguments and their occurrences are exactly one, then you can omit a number after `$`

.
That is, `(lambda [$x $y] (+ x y))`

, `(+ $1 $2)`

, and `(+ $ $)`

are the same.
Although this notation is so powerful, it is limited to specific functions.
The body of such a function has to be simple.
Namely, it is application of a function and its arguments, and all occurrences of `$i`

are the arguments.
For example, you can't write `(+ $1 (* $2 2))`

or `(if $1 #f #t)`

`let`

expressions

` (let {[`*variable* *formula*] ...} *formula*)

A `let`

expression takes two arguments.
The first argument is a collection of binary tuples, which are pairs of a variable and a formula.
These formulas will be evaluated when the associated variable is needed in an evaluation of the second argument, and then the variable is bound to them.
Since a formula in the first argument is evaluated with the original environment, you can't use variables in the first argument in the formula.

`let*`

expressions

` (let* {[`*variable* *formula*] ...} *formula*)

A `let*`

expression is a syntax suger to avoide nested `let`

expressions.
This expression is desugared as follow.

`letrec`

expressions

` (letrec {[`*variable* *formula*] ...} *formula*)

A `letrec`

expression is the same as a let expression except the fact that you can use recursive definition in the first argument.
Mutual recursion is also allowed.

`if`

expressions

` (if `*boolean* *formula* *formula*)

It's ordinary `if`

.
But, note the result of an evaluation of the first argument must be a boolean value (i.e. `#t`

or `#f`

).

`apply`

expressions

` (apply `*function* [*value* ...])

If you have a function and its arguments as a tuple, and want to get the result of the application, then you should use this expression.
The result of the evaluation of an apply expression is the result of application of the function with the arguments.
That is, `(apply f [x`

is the same thing as _{0} x_{1} x_{2}])`(f x`

.
_{0} x_{1} x_{2})

`generate-tensor`

expressions

` (generate-tensor `*function* *collection-of-natural-numbers*)

Egison is equipped with two ways to generate a tensor.
One is to write elements explicitly using double brackets `[|`

`|]`

.
The other is this `generate-tensor`

expression.

The first argument is the index variable, the second is the size of each dimension, and the third argument determines each element of the tensor. Note the first argument and the second argument have the same number of elements. For example, the above and the followings are examples to create a tensor whose size is 5 and 5×3, respectively.

`tensor-size`

expressions

` (tensor-size `*tensor*)

An `tensor-size`

expression tells us the start index and last index of a given tensor.

`seq`

expressions

` (seq `*expr* *expr*)

Egison's `seq`

expression derives from Haskell's `seq`

expression.
The first argument of `seq`

is strictly evaluated.
The most popular use case of `seq`

is in the definition of the `foldl`

function.