Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add new koans for control-flow
  • Loading branch information
iamvery committed Sep 1, 2025
commit d1ced0c7f391660a5f7b2f9673475893d2c8b00d
156 changes: 156 additions & 0 deletions lib/koans/21_control_flow.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
defmodule ControlFlow do
@moduledoc false
use Koans

@intro "Control Flow - Making decisions and choosing paths"

koan "If statements evaluate conditions" do
result = if true, do: "yes", else: "no"
assert result == ___
end

koan "If can be written in block form" do
result =
if 1 + 1 == 2 do
"math works"
else
"math is broken"
end

assert result == ___
end

koan "Unless is the opposite of if" do
result = unless false, do: "will execute", else: "will not execute"
assert result == ___
end

koan "Nil and false are falsy, everything else is truthy" do
assert if(nil, do: "truthy", else: "falsy") == ___
assert if(false, do: "truthy", else: "falsy") == ___
assert if(0, do: "truthy", else: "falsy") == ___
assert if("", do: "truthy", else: "falsy") == ___
assert if([], do: "truthy", else: "falsy") == ___
end

koan "Case matches against patterns" do
result =
case {1, 2, 3} do
{4, 5, 6} -> "no match"
{1, x, 3} -> "matched with x = #{x}"
end

assert result == ___
end

koan "Case can have multiple clauses with different patterns" do
check_number = fn x ->
case x do
0 -> "zero"
n when n > 0 -> "positive"
n when n < 0 -> "negative"
end
end

assert check_number.(5) == ___
assert check_number.(0) == ___
assert check_number.(-3) == ___
end

koan "Case clauses are tried in order until one matches" do
check_list = fn list ->
case list do
[] -> "empty"
[_] -> "one element"
[_, _] -> "two elements"
_ -> "many elements"
end
end

assert check_list.([]) == ___
assert check_list.([:a]) == ___
assert check_list.([:a, :b]) == ___
assert check_list.([:a, :b, :c, :d]) == ___
end

koan "Cond evaluates conditions until one is truthy" do
temperature = 25

weather =
cond do
temperature < 0 -> "freezing"
temperature < 10 -> "cold"
temperature < 25 -> "cool"
temperature < 30 -> "warm"
true -> "hot"
end

assert weather == ___
end

koan "Cond requires at least one clause to be true" do
safe_divide = fn x, y ->
cond do
y == 0 -> {:error, "division by zero"}
true -> {:ok, x / y}
end
end

assert safe_divide.(10, 2) == ___
assert safe_divide.(10, 0) == ___
end

koan "Case can destructure complex patterns" do
parse_response = fn response ->
case response do
{:ok, %{status: 200, body: body}} -> "Success: #{body}"
{:ok, %{status: status}} when status >= 400 -> "Client error: #{status}"
{:ok, %{status: status}} when status >= 500 -> "Server error: #{status}"
{:error, reason} -> "Request failed: #{reason}"
end
end

assert parse_response.({:ok, %{status: 200, body: "Hello"}}) == ___
assert parse_response.({:ok, %{status: 404}}) == ___
assert parse_response.({:error, :timeout}) == ___
end

koan "Guards in case can use complex expressions" do
categorize = fn number ->
case number do
n when is_integer(n) and n > 0 and rem(n, 2) == 0 -> "positive even integer"
n when is_integer(n) and n > 0 and rem(n, 2) == 1 -> "positive odd integer"
n when is_integer(n) and n < 0 -> "negative integer"
n when is_float(n) -> "float"
_ -> "other"
end
end

assert categorize.(4) == ___
assert categorize.(3) == ___
assert categorize.(-5) == ___
assert categorize.(3.14) == ___
assert categorize.("hello") == ___
end

koan "Multiple conditions can be checked in sequence" do
process_user = fn user ->
if user.active do
if user.verified do
if user.premium do
"premium verified active user"
else
"verified active user"
end
else
"unverified active user"
end
else
"inactive user"
end
end

user = %{active: true, verified: true, premium: false}
assert process_user.(user) == ___
end
end
24 changes: 24 additions & 0 deletions test/koans/control_flow_koans_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule ControlFlowTests do
use ExUnit.Case
import TestHarness

test "Control Flow" do
answers = [
"yes",
"math works",
"will execute",
{:multiple, ["falsy", "falsy", "truthy", "truthy", "truthy"]},
"matched with x = 2",
{:multiple, ["positive", "zero", "negative"]},
{:multiple, ["empty", "one element", "two elements", "many elements"]},
"warm",
{:multiple, [{:ok, 5}, {:error, "division by zero"}]},
{:multiple, ["Success: Hello", "Client error: 404", "Request failed: timeout"]},
{:multiple,
["positive even integer", "positive odd integer", "negative integer", "float", "other"]},
"verified active user"
]

test_all(ControlFlow, answers)
end
end