How to have default and optional arguments?

I have this function

    def start(data, opts \\ [pages: 17, depth: 3]) do
        maxPages = opts[:pages]
        maxDepth = opts[:depth]
        IO.puts maxPages
        IO.puts maxDepth

When I do Program.start("data", pages: 8) then I want it to print 8 and 3 but it only prints 8


You could go with Keyword#get/3 instead, like:

def start(data, opts \\ []) do
    maxPages = Keyword.get(opts, :pages, 17)
    maxDepth = Keyword.get(opts, :depth, 3)
    IO.puts maxPages
    IO.puts maxDepth

Or alternatively, Keyword#merge/2 pass in opts with some defaults:

def start(data, opts \\ []) do
    finalOpts = Keyword.merge([pages: 17, depth: 3], opts)
    maxPages = finalOpts[:pages]
    maxDepth = finalOpts[:depth]
    IO.puts maxPages
    IO.puts maxDepth

Hope it helps!

With map instead of keyword list is in my opinion more compact / nicer:

defmodule U2 do
  def format(value, opts \\ %{}) do
    opts = %{unit: "kg", decimals: 2} |> Map.merge(opts)
    "#{Float.to_string(value, [decimals: opts.decimals])} #{opts.unit}"
IO.inspect U2.format 3.1415                            # "3.14 kg"
IO.inspect U2.format 3.1415, %{decimals: 3}            # "3.142 kg"
IO.inspect U2.format 3.1415, %{decimals: 3, unit: "m"} # "3.142 m"
IO.inspect U2.format 3.1415, %{unit: "Pa"}             # "3.14 Pa"


 ? Golang map json to struct
 ? Struct changes after encode/decode
 ? Reading from multiple files into a struct
 ? Marshaling Struct Array with Strings Between c# and c++. Strings are empty
 ? Swift 3: How to set all struct properties to nil
 ? How to copy data values in char** into a new char**?
 ? Declaring a long constant byte array
 ? C: Writing structs of RGB values to file to create ppm image - premature end of file
 ? Dynamic array of structures in dynamic array of structure in C
 ? Sending message to remote node port(s) in erlang