Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the purpose of this gen_server.erl code?

Tags:

erlang

unregister_name({local,Name}) ->
    _ = (catch unregister(Name));
unregister_name({global,Name}) ->
    _ = global:unregister_name(Name);
unregister_name({via, Mod, Name}) ->
    _ = Mod:unregister_name(Name);
unregister_name(Pid) when is_pid(Pid) ->
    Pid.

This is from gen_server.erl. If _ always matches and the match always evaluates to the right hand side expression, what are the _ = expression() lines doing here?

like image 952
Michael Terry Avatar asked Jan 01 '15 04:01

Michael Terry


3 Answers

Typically _ = ... matches are used to quiet dialyzer warnings about unmatched function return values when its -Wunmatched_returns option is used. As the documentation explains:

-Wunmatched_returns
    Include warnings for function calls which ignore a structured return value or
    do not match against one of many possible return value(s).

By explicitly matching the return value against the _ "don't care" variable, you can use this useful dialyzer option without having to see warnings for return values you don't care about.

like image 100
Steve Vinoski Avatar answered Nov 15 '22 11:11

Steve Vinoski


In Erlang, last expression of function is its return value, so someone might be tempted to check, what global:unregister_name/1 or Mod:unregister_name(Name) return and try to pattern match on that.

The _ = expression() doesn't do anything in particular, but hints, that this return value should be ignored (for example, because they are not documented and might be subject to change). However in the last expression, Pid is returned explicitly. This means, that you can pattern match like this:

case unregister_name(Something) of
    Pid when is_pid(Pid) -> foo();
    _ -> bar()
end.

To sum up: those lines aren't doing anything there, but when someone else is reading the source code, they show original programmer intent.

Unfortunately, this particular function is not exported and in the original module never used in pattern match, so I don't have an example to back this up :)

like image 21
tkowal Avatar answered Nov 15 '22 09:11

tkowal


And I'll note that I've since come across this:

The Power of Ten – Rules for Developing Safety Critical Code

Gerard J. Holzmann

NASA/JPL Laboratory for Reliable Software Pasadena, CA

91109

[...]

  1. Rule: The return value of non-void functions must be checked by each calling function, and the validity of parameters must be checked inside each function.

    Rationale: This is possibly the most frequently violated rule, and therefore somewhat more suspect as a general rule. In its strictest form, this rule means that even the return value of printf statements and file close statements must be checked. One can make a case, though, that if the response to an error would rightfully be no different than the response to success, there is little point in explicitly checking a return value. This is often the case with calls to printf and close. In cases like these, it can be acceptable to explicitly cast the function return value to (void) – thereby indicating that the programmer explicitly and not accidentally decides to ignore a return value. In more dubious cases, a comment should be present to explain why a return value is irrelevant. In most cases, though, the return value of a function should not be ignored, especially if error return values must be propagated up the function call chain. Standard libraries famously violate this rule with potentially grave consequences. See, for instance, what happens if you accidentally execute strlen(0), or strcat(s1, s2, -1) with the standard C string library – it is not pretty. By keeping the general rule, we make sure that exceptions must be justified, with mechanical checkers flagging violations. Often, it will be easier to comply with the rule than to explain why noncompliance might be acceptable.

like image 35
Michael Terry Avatar answered Nov 15 '22 10:11

Michael Terry