Erlang basics · Lesson 06 (open contents)
Parse a number safely
Trim a binary, turn it into an integer, and catch invalid input.
Parse valid text and catch invalid text
string:trim/1 names a function in documentation. string:trim(Text) calls it with one argument.
%% Bind a complete parser to ParseInteger
ParseInteger =
fun(Text) ->
try binary_to_integer(string:trim(Text)) of
Number -> {ok, Number}
catch
error:badarg -> {error, not_an_integer}
end
end.
%% Run both paths
{ParseInteger(<<" 42 ">>), ParseInteger(<<"not-a-number">>)}.- The valid input is trimmed to
<<"42">>, parsed, and returned as{ok, 42}. - The invalid input raises
error:badarginside thetryexpression. - The catch clause turns that error into
{error, not_an_integer}.
Read from the first line down
string:trim/1andbinary_to_integer/1are name-and-arity forms used in documentation. Calls use parentheses and do not include/1.- A successful integer reaches the
ofclause and becomes{ok, Number}. - Invalid text raises
error:badarg, so the matching catch clause returns{error, not_an_integer}. - Both paths return tagged tuples that the next piece of code can match.
Symbols are not secret signs
string:trim/1The name-and-arity form used in documentation: module string, function trim, one argument.
binary_to_integer/1A one-argument function that parses an integer binary or raises badarg.
fun(Text) -> ... endCreate a full anonymous function whose argument is called Text.
catch error:badarg ->Handle only an error whose class is error and whose reason is badarg.
Match each name to its meaning
arity
The number of arguments a function takes. /1 says that string:trim/1 and binary_to_integer/1 each take one argument.
anonymous function
A function written with fun ... end and bound to a variable such as ParseInteger.
try/of/catch
Run an expression, handle its normal result after of, and handle a named error after catch.
Why these forms are useful
string:trim/1 removes whitespace from both ends of a text binary. binary_to_integer/1 turns clean integer text into an integer.
Invalid integer text makes binary_to_integer/1 raise the error reason badarg. A try ... of ... catch ... end expression can turn that expected error into data.
Bind the full anonymous function to ParseInteger. Valid and invalid calls then return tagged tuples instead of making the shell stop at an exception.
Why this shape?
Why put /1 after a function name?
BEAM identifies an entry point by module, function name, and argument count. trim/1 means the trim function that takes one argument.
The same name with another argument count is another function. Default arguments generate arities at compile time; they do not make calls loosely sized.
Coming from Java, Python, or JavaScript
Java
- Familiar starting point
- Methods can overload by parameter types and count.
- What BEAM changes
- BEAM first finds a name and arity, then clauses can match data shapes.
- False friend
run/1andrun/2are distinct entry points.
Python
- Familiar starting point
- One function often uses defaults or
*args. - What BEAM changes
- Arity is part of a function's identity and appears in exports and docs.
- False friend
- Leaving out an argument does not discover another arity automatically.
JavaScript
- Familiar starting point
- Functions often tolerate missing or extra arguments.
- What BEAM changes
- A BEAM call must find the exact arity.
- False friend
&1is a capture placeholder; it is not another spelling of/1.
Close the answer and try
Complete SafeNumber so <<" 7 ">> returns {ok, 7} and <<"seven">> returns {error, not_an_integer}.
SafeNumber =
fun(Text) ->
try ____(string:____(Text)) of
Number -> {ok, Number}
catch
____ -> {error, not_an_integer}
end
end.
{SafeNumber(<<" 7 ">>), SafeNumber(<<"seven">>)}.Target result: The result should be {{ok, 7}, {error, not_an_integer}}.
Stuck? Read one hint
Use binary_to_integer, trim, and the catch pattern error:badarg.
After you run it, see one answer
%% Handle only the conversion error we expect
SafeNumber =
fun(Text) ->
try binary_to_integer(string:trim(Text)) of
Number -> {ok, Number}
catch
error:badarg -> {error, not_an_integer}
end
end.
{SafeNumber(<<" 7 ">>), SafeNumber(<<"seven">>)}.Think about it: Why does the catch clause use `error:badarg` instead of `_ : _`?
The parser expects one conversion error. Matching only error:badarg keeps unrelated errors visible so they can be fixed.
Remember these three lines
- 1
module:function/arityorfunction/aritynames a function in documentation; parentheses make a call. - 2
Bind a full anonymous function with
fun ... end. - 3
Catch the expected
error:badargand return a tagged result.