Keyword.validate/2 is a great way to guarantee that a function would be called with the right keyword options.

For example:

def do_something(%User{} = user, opts \\ []) when is_list(opts) do
  {:ok, opts} = Keyword.validate(opts, [:preload])
  preload = Keyword.get(opts, :preload, [])
  #...
end

Examples:

{:ok, result} = Keyword.validate([], [one: 1, two: 2])
Enum.sort(result)
[one: 1, two: 2]

{:ok, result} = Keyword.validate([two: 3], [one: 1, two: 2])
Enum.sort(result)
[one: 1, two: 3]

If atoms are given, they are supported as keys but do not provide a default value:

{:ok, result} = Keyword.validate([], [:one, two: 2])
Enum.sort(result)
[two: 2]

{:ok, result} = Keyword.validate([one: 1], [:one, two: 2])
Enum.sort(result)
[one: 1, two: 2]

Passing unknown keys returns an error:

Keyword.validate([three: 3, four: 4], [one: 1, two: 2])
{:error, [:four, :three]}

Passing the same key multiple times also errors:

Keyword.validate([one: 1, two: 2, one: 1], [:one, :two])
{:error, [:one]}

inspiration documentation