Elixir basics · Lesson 07 (open contents)
Parse a number safely
Trim text, turn it into an integer, and return a clear error for 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 parse_integer
parse_integer = fn text ->
try do
clean = String.trim(text)
{:ok, String.to_integer(clean)}
rescue
ArgumentError -> {:error, :not_an_integer}
end
end
# Run both paths
{parse_integer.(" 42 "), parse_integer.("not-a-number")}- The valid input is trimmed to
"42", parsed, and returned as{:ok, 42}. - The invalid input raises
ArgumentErrorinside thetryblock. - The rescue clause turns that exception into
{:error, :not_an_integer}.
Read from the first line down
String.trim/1andString.to_integer/1are documentation names. Calls use parentheses and do not include/1.String.to_integer(clean)returns an integer for valid text and raisesArgumentErrorfor invalid text.- The rescue clause handles that expected exception and leaves unrelated exceptions visible.
- Both paths return tagged tuples:
{:ok, integer}or{:error, :not_an_integer}.
Symbols are not secret signs
String.trim/1The name-and-arity form used in documentation: module String, function trim, one argument.
String.to_integer/1A one-argument function that parses integer text or raises ArgumentError.
fn text -> ... endCreate a full anonymous function whose argument is called text.
rescue ArgumentError ->Handle only an ArgumentError raised inside the try block.
Match each name to its meaning
arity
The number of arguments a function takes. /1 says that both String.trim/1 and String.to_integer/1 take one argument.
anonymous function
A function written with fn ... end and bound to a name such as parse_integer.
try/rescue
Run code that may raise, then turn a named exception into a normal result.
Why these forms are useful
String.trim/1 removes whitespace from both ends of a string. String.to_integer/1 turns clean integer text into an integer, but raises ArgumentError when the text is invalid.
An anonymous function lets us keep those steps together. Bind it to parse_integer, then call it with a dot: parse_integer.(text).
try/rescue handles the expected conversion error. The parser returns a tagged tuple for both paths, so the caller gets data instead of a crash.
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 safe_number so " 7 " returns {:ok, 7} and "seven" returns {:error, :not_an_integer}.
safe_number = fn text ->
try do
clean = String.____(text)
{:ok, String.____(clean)}
rescue
____ -> {:error, :not_an_integer}
end
end
{safe_number.(" 7 "), safe_number.("seven")}Target result: The result should be {{:ok, 7}, {:error, :not_an_integer}}.
Stuck? Read one hint
Use trim, to_integer, and the exception name ArgumentError.
After you run it, see one answer
# Handle only the conversion error we expect
safe_number = fn text ->
try do
clean = String.trim(text)
{:ok, String.to_integer(clean)}
rescue
ArgumentError -> {:error, :not_an_integer}
end
end
{safe_number.(" 7 "), safe_number.("seven")}Think about it: Why does the rescue clause name `ArgumentError` instead of catching every exception?
The parser expects one conversion error. Handling only ArgumentError keeps unrelated mistakes visible so they can be fixed.
Remember these three lines
- 1
Module.function/arityis a documentation name;Module.function(argument)is a call. - 2
Bind a full anonymous function with
fn ... endand call it with.(). - 3
Rescue the expected conversion error and return a tagged result.