# Examples

## Patterns

Because a lot of non-essential features are removed from the language and core, the user has freedom to implement them however they want. In this section we provide some of possible solutions for these types of challenges.

### Polymorphism

Polymorphism can be achieved using contracts and optional arguments.

```elixir
Draw = fn(S: type -> type) { 
    fn(shape: S -> string) 
}

drawCircle: Draw(Circle) = fn(x: Circle -> string) {...}
drawSquare: Draw(Square) = ...
drawTriangle: Draw(Triangle) = ...

superDraw = fn(shape: T, drawFunction :> Draw(T) -> nothing) {
      drawFunction(shape)
}
```

### Dependency management

It is advised to put all import dependency paths in one module like `refs` and import it to specify import paths.

```perl
#refs
std_map = "/http/github.com/dotLang/std/v1.9.5/MapHelper"
```

and then use above to do actual import:

```
#File1 module
refs = import("/src/main")
MapHelper = import(refs..std_map)
```

### Variadic generics

Sometimes we need to have a generic function that can accept any other function (regardless of input count/type and output type). This is not directly possible in dotLang but there are other alternatives that can help in these cases. For example suppose that you have a function that accepts an optional validation function. If the function is provided, you want to call it, but if not, you want to ignore. You can define a generic function that can do this as here, we only care about the output of the validation function:

```perl
NopFunc1 = fn(input: T, T: type -> nothing)
NopFunc2 = fn(input1: T, input2: U, T: type, U: type -> nothing)
NopFunc3 = fn(input1: T, input2: U, input3: V, T: type, U: type, V: type -> nothing)
...
result = (validator//NopFunc3)(x, y, z)
```

### Pattern matching

Many languages have `switch, case` or `match` keyword to do pattern matching. in dotLang we use maps as a simple alternative.

```perl
int_result = 
[
    value1: fn{1},
    value2: fn{2}
][exp]()
```

### Empty application

```perl
main = fn( -> int ) { 0 }
```

This is a function, called `main` which has no input and always returns `0` (very similar to C/C++ except `main` function has no input).

You can simplify `main` to: `main = fn{ 0 }`

### Hello world

```perl
main = fn( -> int) 
{
    print("Hello world!")
    0
}
```

### Expression parser

We want to write a function which accepts a string like `"2+4-3"` and returns the result (`3`).

```perl
NormalExpression = struct {
    op: char, 
    left: Expression, 
    right: Expression
}

Expression = int|NormalExpression

eval = fn(input: string -> float) 
{
    #assume we already have the parse function
    exp = parse(input)
    innerEval(exp)
}

innerEval = fn(exp: Expression -> float) 
{
    int_val = int|nothing(exp)
    int_val // fn{
        #now we are sure that exp is of type NormalExpression
        y = unwrap(normal_exp)

        ['+' : fn{innerEval(y.left) + innerEval(y.right)},
         '-' : fn{innerEval(y.left) - innerEval(y.right)},
         '*' : fn{innerEval(y.left) * innerEval(y.right)},
         '/' : fn{innerEval(y.left) / innerEval(y.right)}][y.op]()
    }()
}
```

### Quick sort

```perl
quickSort = fn(list:[int], low: int, high: int -> [int])
{
    ifElse(high<low, list, fn{    
        mid_index = (high+low)/2
        pivot = list[mid_index]

        #filter is a built-in function
        small_list = filter(list, fn(x:int -> bool) {x < pivot}))
        big_list   = filter(list, fn(x:int -> bool) {x > pivot}))

        quickSort(small_list) + [pivot] + quickSort(big_list)
    })
}
```

### Sequence sum

A function which accepts a list of numbers and returns sum of numbers.

```perl
sum = fn(data: [int] -> int)
{
    calc = (index: int, sum: int -> int)
    {
        iElse(index >= length(data), fn{sum}
            fn{calc(index+1, sum + data[index]})()
    }

    calc(0,0)
}
```

### Digit extractor

A function which accepts a number and returns its digits in a sequence of characters. Generally for this purpose, using a linked-list is better because it will provide better performance, but we are using recursion to show how it works.

```perl
extractor = (n: number, result: string -> string)
{
  ifElse(n < 10, fn{result + char(48+n)}, fn{
        digit = n % 10
        extractor(n/10, result + char(48+digit)
     })
}
```

### Max sum

A function which accepts two sequences of numbers and returns the maximum of sum of any any two numbers chosen from each of them. This can be done by finding maximum element in each of the arrays but we want to do it with a nested loop.

```perl
maxSum = (a: [int], b: [int] -> int)
{
    calc = (idx1: int, idx2: int, current_max: int -> int)
    {
        ifElse(idx2 >= length(b), fn{current_max}, fn{
            sum = a[idx1] + b[idx2]
            next1 = (idx1+1) % length(a)
            next2 = idx2 + int((idx1+1)/length(a))
            calc(next1, next2, max(current_max, sum))
        })
    }

    calc(0, 0, 0)
}
```

### Fibonacci

```perl
fib = (n: int, cache: [int|nothing] -> int)
{
    ifElse(cache[n] != nothing, unwrap(cache[n], int),
        fn{
            seq_final1 = set(seq, n-1, fib(n-1, cache))
            seq_final2 = set(seq_final1, n-2, fib(n-2, seq_final1))

            seq_final2[n-1] + seq_final2[n-2]
        })
}
```

#### Guessing game

```perl
std = import("/http/github.com/dotLang/std")
stdin = std..stdin
stdout = std..stdout
rand = std..random

main = fn
{
    secret = rand(1,100)
    stdout.write("Please enter a number: ");
    guessRaw: int|nothing = tryParseString(int, stdin.readLine())

    ifElse(guessRaw == nothing, 
    fn{
        stdout.write("Invalid number")
    },
    fn {
        guess = unwrap(guessRaw)
        actions = [guess<secret: fn{ stdout.write("Too small!") },
                   guess>secret: fn{ stdout.write("Too large!") },
                   guess==secret: fn{ stdout.write("Well done!") }
                  ][true]()
    })
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dotlang.org/examples-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
