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.