Elixir basics · Lesson 28 (open contents)
Keep the public API small
Separate file access, parsing, and pure summary logic.
Run this first
Run it once, change one input, and compare the new result.
# Expose a small parser and one summary call
defmodule Cleaner do
@levels %{"INFO" => :info, "WARN" => :warn, "ERROR" => :error}
def parse_line(line) do
case String.split(String.trim(line), ~r/\s+/, parts: 2) do
[""] -> :skip
[level, message] ->
case Map.fetch(@levels, level) do
{:ok, tag} -> {:ok, {tag, message}}
:error -> {:error, :invalid_line}
end
_ -> {:error, :invalid_line}
end
end
def run(records), do: {:ok, count(records)}
defp count(records), do: Enum.frequencies_by(records, fn {level, _message} -> level end)
end
Cleaner.run([{:info, "ready"}, {:warn, "hot"}, {:info, "done"}])- The API returns
{:ok, %{info: 2, warn: 1}}.
Read from the first line down
- Read
def run/1: Expose one project entry point. - Read
defp: Keep an implementation helper private. - Read
Enum.reduce/3: Build the summary in a pure fold.
Symbols are not secret signs
def run/1Expose one project entry point.
defpKeep an implementation helper private.
Enum.reduce/3Build the summary in a pure fold.
Match each name to its meaning
public API
A small public API gives callers fewer contracts to learn and protects internal changes.
pure core
Pure functions transform supplied data without opening files or changing outside state.
boundary module
A boundary module performs IO and converts its errors into project results.
Why these forms are useful
Run the example first. Predict one result, then change one input and run it again.
A small public API gives callers fewer contracts to learn and protects internal changes.
Pure functions transform supplied data without opening files or changing outside state.
Close the answer and try
Add a public total/1 that returns the number of records.
def total(records), do: ____Target result: Return the list length.
Stuck? Read one hint
Use length/1.
After you run it, see one answer
def total(records), do: length(records)Think about it: Should callers invoke `count/1`?
No. defp keeps it private so the module can change its implementation.
Remember these three lines
- 1
Expose a narrow API.
- 2
Keep transformations pure.
- 3
Put IO and error conversion at boundaries.