# Basic Syntax¶

## Top-level Expressions¶

### Definition¶

You can bind an expression to a variable by connecting them with `:=`

.
If you want to declare it at the top level of a program, start with a `def`

keyword.
When defining functions, the argument variable can be placed in the left hand side of the `:=`

.

```
def x := 1
-- The following two definitions are identical.
def f := \x -> x + 1
def f x := x + 1
```

You can decompose data at the argument position as follows.

```
def uncurry f (x, y) := f x y
uncurry (+) (1, 2) -- 3
```

### Expression¶

You can also write arbitrary expressions at the top level of programs.
These expressions are evaluated only when the `-t`

option (see -t / --test) is specified.

```
-- definitions
def x := 1
def y := 2
-- A top-level expression which will evaluate to 3.
x + y
```

`load`

and `loadFile`

¶

We can load Egison libraries with `load`

.
To load your own program, call `loadFile`

with a full-path or a relative path to the file.

```
-- Load Egison library.
load "lib/core/number.egi"
-- Load your program.
loadFile "myfile.egi"
```

### Infix Declaration¶

(From version 4.0.4)

You can define your own infixes (binary operators) for expressions and patterns. In Egison, infix declaration consists of the following 4 parts.

- Associativity …
`infix`

(non associative),`infixl`

(left associative) or`infixr`

(right associative) - Infix type …
`expression`

(for functions) or`pattern`

(for pattern constructors) - Priority of the infix
- Representation of infix

```
-- Define a right-associative infix '&&' of priority 5.
infixr expression 5 &&
-- Definition of the semantics of '&&'.
def (&&) a b := match (a, b) as (eq, eq) with
| (#True, #True) -> True
| _ -> False
-- Define a left-associative infix '<>' of priority 7.
infixl pattern 7 <>
def exampleMatcher := matcher
| $ <> $ as (integer, integer) with
| $x :: $y :: [] -> [(x, y)]
| _ -> []
match [1, 2] as exampleMatcher with $x <> $y -> x + y
---> 3
```

## Basic Expressions¶

### Anonymous function¶

An anonymous function consists of two parts: arguments and a body.
The arguments are written between `\`

and `->`

, and the body is written at the right of `->`

.

```
-- A function of one argument.
\x -> x + 1
-- A function of two arguments.
\x y -> x + y
-- A function of no arguments.
\() -> 1
-- Function application
(\x y -> x + y) 3 7 ---> 10
```

You can also decompose data at the argument position as follows.
Unlike the pattern-matching with `match`

expressions, you can write only one pattern for
each argument.
Also, this decomposition works the same way as the ‘pattern matching’ in OCaml or Haskell, since you
cannot specify matchers.

```
(\(x, y) -> x + y) (3, 7) ---> 10
```

### Anonymous parameter function¶

Egison has a shorthand notation for the anonymous function.
In this syntax, the function body is prefixed with a `n#`

, where `n`

indicates the arity of the function.
There must not be any spaces between the arity number `n`

and the `#`

.
Also, the arguments are specified by numbers, where `%i`

refers to the i-th argument.

This syntax is inspired by the anonymous function syntax of Clojure.

```
-- The followings are identical.
2#(%1 + %2)
\x y -> x + y
```

### Section¶

Egison has a special syntax for the partial application of infix operators, which is inspired by the section notation of Haskell.

`(+)`

is desugared into`\x y -> x + y`

`(+ 1)`

is desugared into`\x -> x + 1`

`(1 +)`

is desugared into`\x -> 1 + x`

`let`

… `in`

expression¶

A `let`

… `in`

expression (or simply a `let`

expression) locally binds expressions to variables.
Bindings defined in a `let`

expression cannot be referred to outside of the `let`

expression.

```
let x := 1 in x + 1 ---> 2
```

You can write multiple bindings in a single `let`

expression.
Note that the head of the binding must be aligned vertically in order to be parsed correctly.

```
let x := 1
y := 2
in x + y
---> 3
```

The above expression can be written in a single line as follows.
The bindings must be wrapped with `{`

`}`

and separated with `;`

.

```
let { x := 1 ; y := 2 } in x + y
```

Bindings in the same `let`

expression can depend on each other.
The bindings do not necessarily be aligned in the order of dependency.

```
let y := x -- 'x' is defined in the next binding
x := 1
in y
---> 1
-- We can even define mutual-recursive functions.
let isOdd n := if n = 0 then False else isEven (n - 1)
isEven n := if n = 0 then True else isOdd (n - 1)
in isOdd 5
---> True
```

As a result, note the following behavior.

```
def x := 3
let y := x
x := 1
in y
---> 1 (not 3)
```

You can also decompose data as follows.
This decomposition does not require matchers and you can only specify one pattern.
To support multiple patterns, use the `match`

expression.

```
let (x, y) := (1, 2) in x + y -- 3
let (x :: _) := [1, 2, 3] in x -- 1
let (x :: _) := [] in x -- pattern match failure
```

The patterns must be syntactically atomic. If you want to use infix patterns (ex. `::`

) or
data constructor patterns with arguments, surround them with parentheses.

```
let (x :: _) := [1, 2, 3] in x -- 1
-- let x :: _ := [1, 2, 3] in x -- parse error!
let (Just x) := Just 1 in x -- 1
-- let Just x := Just 1 in x -- parse error!
```

`where`

expression¶

`where`

is a syntax sugar for the above `let`

expression.
Unlike the `let`

expression, the bindings in `where`

expressions come after the body expression.

For example, the following two expressions are identical.

```
-- local bindings with `where`
expression
where
x1 := expr1
x2 := expr2
-- local bindings with `let`
let x1 := expr1
x2 := expr2
in expression
```

`if`

expression¶

It is the ordinary `if`

expression.
The guard expression (the one right after `if`

) must be evaluated to a boolean (`True`

or `False`

).

```
if True then "Yes" else "No" ---> "Yes"
if False then "Yes" else "No" ---> "No"
```

`do`

expression¶

A `do`

expression can group several IO functions into one IO function.
You can bind expressions to values with `let`

in the `do`

expression as well.
Every lines in the `do`

block must either be an expression that evaluates to an IO function or a `let`

binding.
Note that all the lines in the `do`

block must be aligned vertically.

```
def repl := do
write ">>> "
flush ()
let line := readLine ()
write line
flush ()
repl
```

A `do`

expression can be written in one line as follows.
The expressions needs to be wrapped with `{`

`}`

and separated by `;`

.

```
do { print "foo" ; print "bar" ; print "baz" }
```

The last statement in a `do`

block must be an expression.
The last expression in a `do`

block is interpreted as the evaluation result of the `do`

expression.

```
> io (do { return 1; return 2; return 3 })
3
```

`seq`

expression¶

This expression is inspired by the `seq`

function in Haskell.

A `seq`

expression takes two arguments.
The first argument of `seq`

is strictly evaluated.
The most popular use case of seq is in the definition of the foldl function.

```
def foldl $fn $init $ls :=
match ls as list something with
| [] -> init
| $x :: $xs ->
let z := fn init x
in seq z (foldl fn z xs)
```