DEV Community

Onorio Catenacci
Onorio Catenacci

Posted on • Edited on

Just In Case

Recently I was working on some Elixir code and I ran into something which sort of surprised me although I guess it shouldn't have. I was typing code something like this:

alternate-value = 4

and iex responded with this:

** (CompileError) iex:8: cannot invoke remote function :erlang.-/2 inside a match

I thought to myself, "who's trying to subtract?" but then it occurred to me what was actually happening. And so I thought I might write this up for the sake of helping to reinforce the lesson for me as well as maybe to help some beginners understand a basic property of Elixir.

Let's Get Down To Cases

For sake of this discussion there are four ways of casing variable names that we're interested in. Casing meaning the mixture of upper and lower case letters in a variable name and what that conveys.

PascalCase

There's PascalCase which seems to have been the preferred casing of the Pascal programming language. I'm not sure of that and I've honestly never bothered to check because it isn't important.

If you PascalCase a variable in Elixir something odd happens:

iex(3)> PascalCase = 1
** (MatchError) no match of right hand side value: 1

What's going on here? Well by default in Elixir any name starting with an uppercase letter is an atom. In fact if we do this:

iex(3)> is_atom(PascalCase)
true

Yep, PascalCase is an atom. And because PascalCase is an atom the only thing it will match is itself.

iex(8)> PascalCase = PascalCase
PascalCase
iex(9)> PascalCase == PascalCase
true

Hence PascalCase = 1 is attempting to pattern match 1 to the atom PascalCase and it fails because the only thing that matches an atom is itself. Not to short-circuit the suspense but pattern matching is an important topic in Elixir and I'm not going to treat it here.

camelCase

The second type of casing for variable names is camelCase. In case you don't get the developers' (weak) attempt at humor here, the capital letter in the middle is supposed to resemble a camel's hump. Hence the fact that no developer is going to be booked into the Improv in our lifetime.

As far as I know, Elixir has no issue whatever with camelCase but it isn't standard Elixir idiom. This works:

iex(1)> camelCase = 1
1

However your colleagues may scratch their heads a bit at the funny casing you're using. Most of these casings are intended to allow us to use multi-word variable names without it all reading like alowercasesentencewhichcanbeveryhardtoread.

snake_case

Again, I think this name comes from a subtle attempt at humor. We developers are nothing if we're not a lot of frustrated comedians.

I once heard the "Baby Boom" generation referred to as an example of the "python swallowing a pig" model. If you visualize this rather gruesome (for the pig) scenario then you can probably figure out why it's called "snake_case".

snake_case is the preferred casing of variables in Elixir so try to get yourself in the habit of using it--except in module names where Pascal case is the rule.

kebab-case

As far as I know this casing style comes from Javascript and if you try to use it in Elixir (as my very first example showed) you'll get a very odd error. It may bear with a word of explanation.

Consider this code:

iex(8)> kebab-case = 1
** (CompileError) iex:8: cannot invoke remote function :erlang.-/2 inside a match

Now if you've come from most other languages that looks as if you're assigning the value of 1 to the name kebab-case. But that would be incorrect in Elixir (well, as far as I know in Elixir and any other BEAM based language). This is not assignment; it's actually pattern matching.

I won't belabor the point because far better writers than me have spent a bit of time explaining pattern matching. Suffice it to say that when you write kebab-case = 1 you're not doing assignment; you're actually pattern matching. And because Elixir code is ultimately translated into the bytecode of the BEAM virtual machine, when it sees the minus sign in your variable name it thinks you're attempting subtraction.

A word about that message: :erlang.-/2 is the BEAM's way of uniquely identifying a function. In Elixir an uppercase letter at the start of a symbol name signifies an atom; however you can also signify an atom with a leading colon. Hence :erlang is the identifier for the Erlang module. -/2 is the function name. It means the minus function taking two arguments.

So the message is essentially telling you that the beam thinks you've tried to invoke the subtraction function in a pattern match and that invoking a function in a pattern match is not allowed.

EDIT: It was pointed out to me that kebab-case doesn't come from Javascript. In fact as far as I can tell it's actually a coding standard in HTML and CSS. The point that it won't work in Elixir still stands though.

Top comments (2)

Collapse
 
hq063 profile image
Gonzalo HQ063

it's actually called kebAb-case.

And kebab-case = 1 doesn't work in JS either, probably there is almost no language that would interpret that as a variable assignment, kebab casing is motly used for paths or files, maybe as hash keys, package names or other type of names that are wrapped in strings, but not as regular variable names.

Collapse
 
olddutchcap profile image
Onorio Catenacci

Hmm. Thanks for the corrections. I think I had the standard use of kebab-case in some HTML and CSS conflated with Javascript.