diff --git a/pe/chapter5.erl b/pe/chapter5.erl new file mode 100644 index 0000000..a8d95e0 --- /dev/null +++ b/pe/chapter5.erl @@ -0,0 +1,23 @@ +%% chapter 5: maps and records +-module(chapter5). +-include("records.hrl"). +-export([make_urgent/1, count_characters/1]). + +%% Maps are defined with a #{ Key => Value, ... } syntax +%% =>: update existing key or add new key +%% :=: update existing key + +make_urgent(M) -> + M#{status := urgent}. + +%% Valid: make_urgent(#{status => reminder, who => kyle}). +%% Invalid: make_urgent(#{who => kyle}). + +count_characters(Str) -> + count_characters(Str, #{}). +count_characters([H|T], #{ H := N }=X) -> + count_characters(T, X#{H := N + 1}); +count_characters([H|T], X) -> + count_characters(T, X#{H => 1}); +count_characters([], X) -> X. + diff --git a/pe/error_test.erl b/pe/error_test.erl new file mode 100644 index 0000000..89db829 --- /dev/null +++ b/pe/error_test.erl @@ -0,0 +1,45 @@ +-module(error_test). +-export([generate_exc/1, demo1/0, demo2/0, demo3/0, catcher/1]). + +generate_exc(1) -> a; +generate_exc(2) -> throw(a); +generate_exc(3) -> exit(a); +generate_exc(4) -> {'EXIT', a}; +generate_exc(5) -> error(a). + +demo1() -> + [catcher(I) || I <- lists:seq(1, 5)]. + +demo2() -> + [{I, (catch generate_exc(I))} || I <- [1,2,3,4,5]]. + +catcher(N) -> + try generate_exc(N) of + Val -> {N, normal, Val} + catch + throw:X -> {N, caught, thrown, X}; + exit:X -> {N, caught, exited, X}; + error:X -> {N, caught, error, X} + end. + + +%% NB: catch _ -> ... assumes default tag throw, need to specify +%% catch _:_ -> ... + +demo3() -> + try generate_exc(5) + catch + error:X -> + {X, erlang:get_stacktrace()} + end. + +%% In Erlang, when an error is detected internally by the system or is +%% detected by program logic, the correct approach is to crash +%% immediately and generate a meaningful error message. We crash +%% immediately so as not to make matters worse. The error message should +%% be written to a permanent error log and be sufficiently detailed so +%% that we can figure out what went wrong later. +%% +%% Second, fail politely means that only the programmer should see the +%% detailed error messages produced when a program crashes. A user of the +%% program should never see these messages. diff --git a/pe/math_functions.erl b/pe/math_functions.erl new file mode 100644 index 0000000..c9df946 --- /dev/null +++ b/pe/math_functions.erl @@ -0,0 +1,32 @@ +-module(math_functions). +-export([even/1, odd/1, filter/2, split/1, splitacc/1]). + +even(N) -> + N rem 2 == 0. + +odd(N) -> + N rem 2 /= 0. + +filter(F, [H|T]) -> + case F(H) of + true -> [H | filter(F, T)]; + false -> filter(F, T) + end; +filter(_, []) -> + []. + +split(L) -> + {filter(fun (N) -> even(N) end, L), + filter(fun (N) -> odd(N) end, L)}. + +splitacc_inner([], Even, Odd) -> {Even, Odd}; +splitacc_inner([H|T], Even, Odd) -> + case even(H) of + true -> + splitacc_inner(T, [H|Even], Odd); + false -> + splitacc_inner(T, Even, [H|Odd]) + end. + + +splitacc(L) -> splitacc_inner(L, [], []). diff --git a/pe/records.hrl b/pe/records.hrl new file mode 100644 index 0000000..2db8abe --- /dev/null +++ b/pe/records.hrl @@ -0,0 +1 @@ +-record(todo, {status=reminder, who=kyle, text}).