# Scala

Perhaps, the third (after Scheme and Haskell) programming language worth learning.

## Expressions

In a right language everything is an expression.

## Values

Every expression evaluates (could be reduced to) a value.

```(define x 2)
```
```def x = 2
```

evaluated when called

## Types

Each value has a type.

## Bindings

Lexically scoped local binding

```(let ((x 2))
...
)
```

Once bound (with val) symbols cannot be rebound

```val x = 2
```

evaluated at compile-time

## Blocks

```(begin
(+ 1 2)
(+ 2 3)
)
```
```{
1 + 2
2 + 3
}
```

## lambdas

```(lambda (x) (+ x 1))
```
```{ (x: Int) => x + 1 }
```

## Thunks

Defining a thunk (a lazy value)

```(delay 2)
```
```lazy val x = 2
```

evaluated on-demand

## Procedures

```(lambda (x) (+ 1 x))
```
```(x: Int) => x + 1
```

Binding

```(define inc (lambda (x) (+ 1 x)))
```
```val inc = (x: Int) => x + 1
```

Applicative Order - the argument will be evaluated before procedure application (call by value)

```def square(x: Double)
```

Normal Order - the argument will be evaluated inside of the function (call by name)

```def square(x: => Double)
```

Variable number of arguments

```(define sum (lambda xs ...))
```
```def sum(xs: Int*) = { ??? }
```

## Higher order procedures

Nesting

```import scala.annotation.tailrec

def factorial(x: Int) = {
@tailrec
def recur(acc: Int, x: Int): Int =
if (x == 0)
acc
else
recur(acc * x, x - 1)
recur(1, x)
}
```

Composition

```type R = Double // a type alias

def compose(f: R=>R, g: R=>R) = (x: R) => f(g(x))
```

use (anonymous function of arity 1 literals with underscore `_` argument syntactic sugar)

```val f = compose({_*2}, {_-1})
```

## Currying

```(lambda (x) (lambda (y) (+ x y)))
```
```def f(x: Int)(y: Int) = x + y
```

## Infix syntactic sugar

`1 + 2` is a syntactic sugar for

```1.+(2)
```
```(1 to 5) map (_*2)
```

## Reductions

```(define sum (lambda xs (reduce + 0 xs)))
```
```def sum(args: Int*) = args.reduceLeft(_+_)
```

## Objects

Objects are values which has a structure and its own type, usually defined as a Class.

## Classes

Classes are Blueprints which define a structure of corresponding objects. They introduce a new type.

## Traits

Traits are Interfaces - a named sets of method signatures. They can be extended (inherited) but cannot be instantiated (like a class).

a Trait define what it takes to be a.... If an object implements a trait is could be substituted and used whenever this trait is required.

Something, which has a `head` and a `tail`

```trait L[+T] {
def tail: L[T]
}
```

a container for that

```class C[+T](val head: T, val tail: L[T]) extends L[T]
```

a NIL (denotation for emptiness)

```object N extends L[Nothing] {
```case class Thunk[+A](value: A)