Configure function default values

Sometimes it’s really useful, or let’s say even necessary, to configure your function-level default values per environment.

Now, without any further ado, here is how you do it:

@default_tty 1000 * 60

def something(ttl \\ default_ttl()) do
  # do something
end

# Time to live (ttl) period (in milliseconds).
defp default_ttl do
  Application.get_env(:myapp, :some_topic, @default_ttl)
end

But be careful
Application.get_env/3 is evaluated during compile time!

Compile Time Only!

This means that it might be useful to configure different values for the test, dev, and production environments but it wouldn’t work on a runtime level or per instance. This is just the way Elixir as a compiled language works. When the code is compiled, it needs to know what the function would use as default values for optional arguments.

Be careful in dependency scenarios

As you can read in this old issue back from 2015 there is a non-obvious behavior related to this coding option. When your code is used as a dependency in another project. It’s the compile time of that dependency that is relevant and used for setting the default value then.

So be sure to run mix deps.clean dependencyA in order for the default value to pick up the current setting. dependencyA in this example would be the dependency that is using the env var default value in it’s function.

Summary

Using this way to configure the default value for your functions when needed, provides you with a beautiful balance of great performance at runtime, while still having a level of customizability using your config files.

What are your opinions and experiences on this? Any comments, critiques and suggestions are highly welcome.

Leave a Reply

Your email address will not be published. Required fields are marked *