Erlang basics · Lesson 26 (open contents)
01 · Open erl02 · Meet common terms03 · Tell two kinds of text apart04 · Bind a variable once05 · Split and filter a list06 · Parse a number safely07 · Choose one path with case08 · Let a function keep going09 · Put code in a module10 · Compare terms and Boolean results11 · Read and update nested maps12 · Build and inspect UTF-8 binaries13 · Let clauses choose the function path14 · Solve a list twice15 · Choose with patterns, guards, and errors16 · Describe a module and one record17 · Put one tested module in Rebar318 · Return success or failure as data19 · Read and write one file safely20 · Build a data pipeline with functions21 · Keep records behind a module boundary22 · Define a module contract23 · Describe the data contract24 · Test small rules and whole flows25 · Shape builds and make a command26 · Write the project promise27 · Parse one real line28 · Keep the public API small29 · Make the promise executable30 · Package the edge and leave clues31 · Prove the project is done
ERLANG · PROJECT · LESSON 2635 minutes

Write the project promise

Turn a log-cleaner idea into exact input, output, and error examples.

01 · Start with the whole example

Run this first

Run it once, change one input, and compare the new result.

Erlang
%% Describe observable behavior before modules
Examples = [
  #{input => <<"  INFO ready  ">>, output => {ok, {info, <<"ready">>}}},
  #{input => <<>>, output => skip},
  #{input => <<"BROKEN">>, output => {error, invalid_line}}
],
length(Examples).
Check the result first
  • The brief contains 3 executable examples.
02 · Take the code apart

Read from the first line down

  1. Read #{input => ..., output => ...}: Store one executable example as a map.
  2. Read skip: Label a line the project intentionally ignores.
  3. Read invalid: Label input the project must report.
03 · Meet the new symbols

Symbols are not secret signs

#{input => ..., output => ...}

Store one executable example as a map.

skip

Label a line the project intentionally ignores.

invalid

Label input the project must report.

04 · Ideas inside the code

Match each name to its meaning

01

acceptance example

A concrete input and expected output makes a requirement testable.

02

scope

Scope records what this small project will and will not do.

03

invariant

An invariant is a rule that must hold for every accepted result.

05 · Make the idea clear

Why these forms are useful

Run the example first. Predict one result, then change one input and run it again.

A concrete input and expected output makes a requirement testable.

Scope records what this small project will and will not do.

06 · Change it yourself

Close the answer and try

Add an example for WARN hot.

Practice starting point
#{input => <<"WARN hot">>, output => ____}

Target result: Use {ok,{warn,<<"hot">>}}.

Stuck? Read one hint

Keep the same tagged tuple shape.

After you run it, see one answer
One answer
#{input => <<"WARN hot">>, output => {ok, {warn, <<"hot">>}}}
Think about it: Why write examples before modules?

They keep implementation choices from quietly changing promised behavior.

Take with you

Remember these three lines

  1. 1

    Start with observable examples.

  2. 2

    Keep the first scope small.

  3. 3

    Write invariants before optimizations.

Lesson completeRun the code once, then mark this lesson as done.