Recently I was looking at various ways to create a constants in Elixir. I come from ruby background, where it is very easy to create and think of constant. You can create constant by assigning a value to constant name. Constant name should begin with capital letter in ruby. Concept of constant is bit twisted in ruby as we can reassign constant to different value.

 I_AM_CONSTANT = "though i can be reassigned :)"

Ohh! Just remembered this is a post about Elixir and not Ruby. Being in love with Ruby, I can't stop talking about it. I guess it happens with every Ruby developer.

Now let us talk about how do we create constant in Elixir. There is no concept of constant in elixir. Though we can create something similar to it using below two approaches.

  1. Module Attribute

Module attribute in elixir servers various purposes. We won't go into detail though. One purpose it servers is to hold constant value.
You can declare module attribute as

defmodule  SoYouNeedConstant do
  @i_am_a_constant "not really. But people use me for it though"
  def get_constant do
    @i_am_a_constant  #=> o/p "not really. But people use me for it though"
  end
end

Module attributes are not really a constants. Similar to Ruby constants, module attributes can be reassigned to something else.
Module attribute value exists only during compilation time. The value assigned to module attribute is copied where it is used at compile time (Similar to macro expansion). Due to this it cannot be reassigned inside any function and also it cannot be accessed outside the module in which it is declared.

Side Note: Ruby constant also can't be reassigned inside a method. I told you, I can't stop talking about Ruby :)

Now question might pop up "How to define constant that we can use across different module?". Let us see the second approach.

  1. Creating functions to return constant value
    We can create a module and create different functions, just to return some constant value.

    defmodule LookingForGlobalConstant do
    def can_u_beilive_it_i_am_a_constant do
    "I can't do anything, you have to belive me"
    end
    end

    LookingForGlobalConstant.can_u_beilive_it_i_am_a_constant #=> o/p "I can do nothing, you have to believe me"

This made me think, why do we have constant in other language when we can use functions. Above approach is fine, but we can create abstraction around it, so we don't have to create function manually every time we need to define a constant.

defmodule Constants do
  defmacro const(const_name, const_value) do
    quote do
      def unquote(const_name)(), do: unquote(const_value)
    end
  end
end

Above is the abstraction for creating constant. It uses power of metaprograming provided by Elixir. Doesn't it look simple? Let us see how to use it.

defmodule MyApp.Constant do
  import Constants
  
  const :facebook_url, "http://facebook.com/rohanpujaris"
end

MyApp.Constant.facebook_url  # You can use this line anywhere to get the facebook url.

const is a macro, which defines function with the name which is provided to it as a first argument(facebook_url). This function returns the second argument(http://facebook.com/rohanpujaris") provided to const macro.

Finally we defined the constant that we can use everywhere :). Hope this was helpful.

Just started with Elixir, It is already changing my perspective towards programming.