Stratus3D

A blog on software engineering by Trevor Brown

Function/Variable Ambiguity in Elixir

Variable syntax is one of the big differences between Erlang and Elixir that I encountered when learning Elixir. Instead of having to start each variable name with an uppercase letter, a lowercase letter must be used. This change in syntax seems like an improvement - after all most mainstream programming languages require variables to start with a lowercase letter, and lowercase is generally easier to type. However, a deeper look at this syntax choice reveals some significant downsides that I want to present here.

The Problem

The example I’m using to illustrate this problem is from a blog post on variable shadowing in Elixir by Michael Stalker.

defmodule Shadowing do
  x = 5
  def x, do: x
  def x(x = 0), do: x
  def x(x), do: x(x - 1)
end

Without running the code, tell me what the return values of these three function calls are:

Shadowing.x()

Shadowing.x(0)

Shadowing.x(2)

No, really. Think about the code for a minute.

Now…are you positive your answers are right?

This code snippet is confusing because the variable names and function names are indistinguishable from each other. This is an ambiguity in scope and also an ambiguity in identifier type. It’s not clear whether the token x is the function name (an atom) or a variable (identified by the same sequence of characters). Both are identifiers, but unlike Erlang, function identifiers and variable identifiers look the same. Despite this the compiler doesn’t get confused and handles this code according to Elixir’s scoping rules.

Erlang Is Better

I translated the Elixir code above to Erlang. The functions in this Erlang module behave the exact same as the functions in the Elixir module above.

-module(shadowing).

-export([x/0, x/1]).

-define(X, 5).

x() -> x().
x(X) when X == 0 -> X;
x(X) -> x(X - 1).

With Erlang all the ambiguity is gone. We now have functions and variables that cannot be confused. All variables start with uppercase letters and all function names always start with a lowercase letter or are wrapped in single quotes. This makes it impossible to confuse the two. Granted this is not an apples to apples comparison because Erlang doesn’t have a module scope for variables so I used a macro for the model-level variable. But we still have a function and a variable that can no longer be confused.

Conclusion

Despite it’s rough edges Erlang syntax is unambiguous. This is a key advantage Erlang has over Elixir when it comes to syntax. Variables, functions, and all other data types are easily distinguishable. Keywords can be confused with other atoms but this is seldom a problem in practice. The list of keywords is short and easy to memorize but syntax highlighters highlight them in a specific color making memorization unnecessary most of the time.