What are the exact differences between underscore variables and a named variable that starts with underscore from the Erlang compiler point of view (apart from adding readability to the code)?
For example are _
and _Var
different?
What are the exact differences between underscore variables and a named variable that starts with underscore from the Erlang compiler point of view (apart from adding readability to the code)?
For example are _
and _Var
different?
The don't care variable _
is a VERY SPECIAL variable which matches anything and is NEVER bound to a value. It is used when I know there is something there but I don't care what the value is and I will never use. Seeing _
is never bound it can not be used in an expression and the compiler flags it as an error.
Variables like _Var
are perfectly normal variables which you can match against and will be bound to values which means they can be used in expressions. Prefixing a variable with _
is about intent. The compiler normally warns you about a variable which is bound in a pattern but is never used, often a sign of an error. But the compiler does not warn for variables prefixed with _
like in _Var
. The intent being that I want to give the variable a name, naming things is good, but that I know I will never use it.
Remember that _
is really the only special variable and that _Var
are normal variables and behave as such if used. If you are feeling perverse then you could prefix all your variables with _
and everything will still work.
Let's quote the doc here:
The anonymous variable is denoted by underscore (
_
) and can be used when a variable is required but its value can be ignored. [...]Variables starting with underscore (
_
), for example_Height
, are normal variables, not anonymous: they are however ignored by the compiler in the sense that they will not generate any warnings for unused variables.
In other words, you use _Var
form when you need the matched expression to be matched - but don't want to use it further AND/OR you want show its meaning. And you use _
variable when neither you nor compiler should care for the expression that will be matched by it.
Example 1:
member(_, []) -> [].
In this function is not quite clear what the first _
matches. But rewriting it directly, like this:
member(Elem, []) -> [].
... will generate a warning, if the code is compiled with the flag warn_unused_vars
set. You still can make you code readable here, though, by using underscored variable:
member(_Elem, []) -> [].
Example 2:
{_, _, Some} = {1, 2, 3}
This tuple matching will go though quite all right, as the first two elements of tuple will be ignored completely.
{_Var, _Var, Some} = {1, 2, 3}
This matching will fail, however: though _Var
won't have to be used, it should be 'filled' with the same value! As 1 is not equal to 2, the condition fails here.