Sure does: http://erlang.org/doc/apps/dialyzer/dialyzer_chapter.html
> I'm not sure how that competes with types much less is so different from any other runtime conditional.
You can write:
f(5) ->
"got a 5";
f(X) when is_integer(X), X > 1000 ->
"got an integer greater than 1000";
f(X) ->
"not 5 and not an integer greater than 1000".
Sure you can do it with an if statement in some languages. Except in Erlang can also have the same guards on process message receive expressions. There would have to process all messages then check the type and somehow re-insert it back into the message queue.http://learnyousomeerlang.com/dialyzer
Erlang is a dynamic, strongly typed language. Dynamic means the compiler doesn't do static type checks. "Strongly typed" means once a variable has a type it usually doesn't get automatically coerced to other types. So adding a string "5" and an integer 1 doesn't return a string "6" or integer 6 but throws an exception.
In addition to the compiler there is also a tool called Dialyzer. It's based on the idea of Success Types (paper on it: http://www.it.uu.se/research/group/hipe/papers/succ_types.pd...).
It checks for type inconsistencies, violations, etc just like a compiler in a traditional statically typed language. But it doesn't emit optimized code based on it. So say it deduced that a variable can only be an integer between 1 and 10 it doesn't have a way to emit some optimized assembly code based on that information. Besides the types it automatically infers, additional typing constraints can be specified by the user.
So for the guard in question, if say the second clause of right_age(_) -> wasn't there and it saw calls to the function with X=105, then Dialyzer would come back with an error with something like:
your_module:105: Clause guard cannot succeed.