# Functions

Defined by **name** and # of args(**arity**) `hello/1` vs `hello/2`

Instead of early exits/for invalid args use **guards** and param pattern matching

Named Fts must be defined inside module, anon fts can be defined anywhere

## Named Fts

```elixir
defmodule M do
    def transform(myvar, _opts) do #_ means ignore arg
        8 * myvar + 3 #returns last value automatically
    end

    #defp for private fts
    defp privateTransform(v, z \\ 1) do  #default value
        v * 4 + z
    end

        def getcookie(%{cookie: c} = conn, _params) do
        IO.inspect(conn)
        IO.puts("Has cookie #{c}")
    end

    def getcookie(conn, _params) do
        IO.puts("No cookie")
    end
end
```

Recursion

```elixir
def factorial(num) do
    if num <= 1 do 
        1
    else 
        result = num * factorial(num - 1)
        result
    end
end
```

Loop?

```elixir
def sum([]), do: 0
def sum([h|t]), do: h + sum(t)

IO.puts("Sum: #{sum([1,2,3])}")
```

```elixir
def loop(0, _), do: nil
def loop(max, min) do
    if(max < min) do
        loop(0, -1)
    else 
        IO.puts "Num: #{max}"
        loop(max - 1, min)
    end
end

myloop(5,1) #=> 5,4,3,2,1
```

### Guards

```elixir
def drive(%User{age: age}) when age >= 16 do
  # Code that drives a car
end

drive(User.get("John Doe"))
#=> Fails if the user is under 16
```

```elixir
def print_multiple_times(msg, n) when n <= 1 do
    IO.puts msg
end

def print_multiple_times(msg, n) do
  IO.puts msg
  print_multiple_times(msg, n - 1)
end
```

Guards that would throw an error, just fail the guard like length

```elixir
def foo(term) when length(something) or is_float(term) or is_nil(term)
```

Capture

Need to capture to use named ft as anon ft

```elixir
Enum.each(data_by_columns, &put_in_one_row/1)
```

### Pipe |>

Output from the left is passed as first arg to ft on right

```elixir
Enum.sum(Enum.filter(Enum.map(1..100_000, &(&1 * 3)), odd?)) 
#becomes
1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(odd?) |> Enum.sum
```

### Anonymous fts

Defined within a variable scope

**Need a `.` after ft name to call**, `&` can capture Module fts making it anon and also create anon fts

`&List.flatten(&1, &2)` is the same as writing `fn(list, tail) -> List.flatten(list, tail)` end

```elixir
get_sum = fn (x,y) -> x + y end
IO.puts "5 + 5 = #{get_sum.(5,5)}"

get_less = &(&1 - &2)
IO.puts "7 - 6 = #{get_less.(7,6)}"

add_sum = fn #no args notice
    {x, y} -> IO.puts "#{x} + #{y} = {x+y}"
    {x, y, z} -> IO.puts "#{x} + #{y} + #{z} = {x+y+z}"
end
add_sum.({1,2})
add_sum.({1,2,3})
```


---

# 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://openai.gitbook.io/code-cheatsheets/all/elixir/functions.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.
