add .formatter.exs + format
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
defmodule Equalities do
|
||||
use Koans
|
||||
|
||||
@intro """
|
||||
@intro """
|
||||
Welcome to the Elixir koans.
|
||||
Let these be your first humble steps towards learning a new language.
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ defmodule Atoms do
|
||||
koan "It is surprising to find out that booleans are atoms" do
|
||||
assert is_atom(true) == ___
|
||||
assert is_boolean(false) == ___
|
||||
assert :true == ___
|
||||
assert :false == ___
|
||||
assert true == ___
|
||||
assert false == ___
|
||||
end
|
||||
|
||||
koan "Like booleans, the nil value is also an atom" do
|
||||
assert is_atom(nil) == ___
|
||||
assert :nil == ___
|
||||
assert nil == ___
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,13 +6,11 @@ defmodule Maps do
|
||||
@person %{
|
||||
first_name: "Jon",
|
||||
last_name: "Snow",
|
||||
age: 27,
|
||||
age: 27
|
||||
}
|
||||
|
||||
koan "Maps represent structured data, like a person" do
|
||||
assert @person == %{first_name: ___,
|
||||
last_name: "Snow",
|
||||
age: 27 }
|
||||
assert @person == %{first_name: ___, last_name: "Snow", age: 27}
|
||||
end
|
||||
|
||||
koan "Fetching a value returns a tuple with ok when it exists" do
|
||||
|
||||
@@ -49,7 +49,7 @@ defmodule Structs do
|
||||
|
||||
koan "Use the update_in macro to modify a nested value" do
|
||||
airline = %Airline{plane: %Plane{maker: :boeing, passengers: 200}}
|
||||
assert update_in(airline.plane.passengers, fn(x) -> (x + 2) end) == ___
|
||||
assert update_in(airline.plane.passengers, fn x -> x + 2 end) == ___
|
||||
end
|
||||
|
||||
koan "Use the put_in macro with atoms to replace a nested value in a non-struct" do
|
||||
|
||||
@@ -17,7 +17,7 @@ defmodule Sigils do
|
||||
end
|
||||
|
||||
koan "The lowercase ~s sigil supports string interpolation" do
|
||||
assert ~s[1 + 1 = #{1+1}] == ___
|
||||
assert ~s[1 + 1 = #{1 + 1}] == ___
|
||||
end
|
||||
|
||||
koan "The ~S sigil is similar to ~s but doesn't do interpolation" do
|
||||
@@ -29,7 +29,7 @@ defmodule Sigils do
|
||||
end
|
||||
|
||||
koan "The ~w sigil also allows interpolation" do
|
||||
assert ~w(Hello 1#{1+1}3) == ___
|
||||
assert ~w(Hello 1#{1 + 1}3) == ___
|
||||
end
|
||||
|
||||
koan "The ~W sigil behaves to ~w as ~S behaves to ~s" do
|
||||
|
||||
@@ -41,7 +41,7 @@ defmodule PatternMatching do
|
||||
|
||||
koan "Lists must match exactly" do
|
||||
assert_raise ___, fn ->
|
||||
[a, b] = [1,2,3]
|
||||
[a, b] = [1, 2, 3]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -71,9 +71,9 @@ defmodule PatternMatching do
|
||||
|
||||
koan "And they will only run the code that matches the argument" do
|
||||
name = fn
|
||||
("duck") -> "Donald"
|
||||
("mouse") -> "Mickey"
|
||||
(_other) -> "I need a name!"
|
||||
"duck" -> "Donald"
|
||||
"mouse" -> "Mickey"
|
||||
_other -> "I need a name!"
|
||||
end
|
||||
|
||||
assert name.("mouse") == ___
|
||||
@@ -84,10 +84,11 @@ defmodule PatternMatching do
|
||||
koan "Errors are shaped differently than successful results" do
|
||||
dog = %{type: "dog"}
|
||||
|
||||
result = case Map.fetch(dog, :type) do
|
||||
{:ok, value} -> value
|
||||
:error -> "not present"
|
||||
end
|
||||
result =
|
||||
case Map.fetch(dog, :type) do
|
||||
{:ok, value} -> value
|
||||
:error -> "not present"
|
||||
end
|
||||
|
||||
assert result == ___
|
||||
end
|
||||
@@ -133,10 +134,11 @@ defmodule PatternMatching do
|
||||
pinned_variable = 1
|
||||
|
||||
example = fn
|
||||
(^pinned_variable) -> "The number One"
|
||||
(2) -> "The number Two"
|
||||
(number) -> "The number #{number}"
|
||||
^pinned_variable -> "The number One"
|
||||
2 -> "The number Two"
|
||||
number -> "The number #{number}"
|
||||
end
|
||||
|
||||
assert example.(1) == ___
|
||||
assert example.(2) == ___
|
||||
assert example.(3) == ___
|
||||
@@ -144,17 +146,20 @@ defmodule PatternMatching do
|
||||
|
||||
koan "Pinning works anywhere one would match, including 'case'" do
|
||||
pinned_variable = 1
|
||||
result = case 1 do
|
||||
^pinned_variable -> "same"
|
||||
other -> "different #{other}"
|
||||
end
|
||||
|
||||
result =
|
||||
case 1 do
|
||||
^pinned_variable -> "same"
|
||||
other -> "different #{other}"
|
||||
end
|
||||
|
||||
assert result == ___
|
||||
end
|
||||
|
||||
koan "Trying to rebind a pinned variable will result in an error" do
|
||||
a = 1
|
||||
assert_raise MatchError, fn() ->
|
||||
|
||||
assert_raise MatchError, fn ->
|
||||
^a = ___
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,6 +12,7 @@ defmodule Functions do
|
||||
end
|
||||
|
||||
def multiply(a, b), do: a * b
|
||||
|
||||
koan "Single line functions are cool, but mind the comma and the colon!" do
|
||||
assert 6 == multiply(2, ___)
|
||||
end
|
||||
@@ -41,8 +42,8 @@ defmodule Functions do
|
||||
assert sum_up(1) == ___
|
||||
end
|
||||
|
||||
def bigger(a,b) when a > b, do: "#{a} is bigger than #{b}"
|
||||
def bigger(a,b) when a <= b, do: "#{a} is not bigger than #{b}"
|
||||
def bigger(a, b) when a > b, do: "#{a} is bigger than #{b}"
|
||||
def bigger(a, b) when a <= b, do: "#{a} is not bigger than #{b}"
|
||||
|
||||
koan "Intricate guards are possible, but be mindful of the reader" do
|
||||
assert bigger(10, 5) == ___
|
||||
@@ -58,13 +59,13 @@ defmodule Functions do
|
||||
end
|
||||
|
||||
koan "Little anonymous functions are common, and called with a dot" do
|
||||
multiply = fn (a,b) -> a * b end
|
||||
assert multiply.(2,3) == ___
|
||||
multiply = fn a, b -> a * b end
|
||||
assert multiply.(2, 3) == ___
|
||||
end
|
||||
|
||||
koan "You can even go shorter, by using capture syntax `&()` and positional arguments" do
|
||||
multiply = &(&1 * &2)
|
||||
assert multiply.(2,3) == ___
|
||||
assert multiply.(2, 3) == ___
|
||||
end
|
||||
|
||||
koan "Prefix a string with & to build a simple anonymous greet function" do
|
||||
@@ -77,7 +78,7 @@ defmodule Functions do
|
||||
assert three_times.("foo") == ___
|
||||
end
|
||||
|
||||
def times_five_and_then(number, fun), do: fun.(number*5)
|
||||
def times_five_and_then(number, fun), do: fun.(number * 5)
|
||||
def square(number), do: number * number
|
||||
|
||||
koan "You can pass functions around as arguments. Place an '&' before the name and state the arity" do
|
||||
@@ -90,10 +91,11 @@ defmodule Functions do
|
||||
end
|
||||
|
||||
koan "The result of a function can be piped into another function as its first argument" do
|
||||
result = "full-name"
|
||||
|> String.split("-")
|
||||
|> Enum.map(&String.capitalize/1)
|
||||
|> Enum.join(" ")
|
||||
result =
|
||||
"full-name"
|
||||
|> String.split("-")
|
||||
|> Enum.map(&String.capitalize/1)
|
||||
|> Enum.join(" ")
|
||||
|
||||
assert result == ___
|
||||
end
|
||||
|
||||
@@ -12,12 +12,14 @@ defmodule Enums do
|
||||
end
|
||||
|
||||
def less_than_five?(n), do: n < 5
|
||||
|
||||
koan "Elements can have a lot in common" do
|
||||
assert Enum.all?([1, 2, 3], &less_than_five?/1) == ___
|
||||
assert Enum.all?([4, 6, 8], &less_than_five?/1) == ___
|
||||
end
|
||||
|
||||
def even?(n), do: rem(n, 2) == 0
|
||||
|
||||
koan "Sometimes you just want to know if there are any elements fulfilling a condition" do
|
||||
assert Enum.any?([1, 2, 3], &even?/1) == ___
|
||||
assert Enum.any?([1, 3, 5], &even?/1) == ___
|
||||
@@ -30,6 +32,7 @@ defmodule Enums do
|
||||
end
|
||||
|
||||
def multiply_by_ten(n), do: 10 * n
|
||||
|
||||
koan "Map converts each element of a list by running some function with it" do
|
||||
assert Enum.map([1, 2, 3], &multiply_by_ten/1) == ___
|
||||
end
|
||||
@@ -67,6 +70,7 @@ defmodule Enums do
|
||||
end
|
||||
|
||||
def divisible_by_five?(n), do: rem(n, 5) == 0
|
||||
|
||||
koan "...but you don't quite find it..." do
|
||||
assert Enum.find([1, 2, 3], &divisible_by_five?/1) == ___
|
||||
end
|
||||
@@ -76,6 +80,6 @@ defmodule Enums do
|
||||
end
|
||||
|
||||
koan "Collapse an entire list of elements down to a single one by repeating a function." do
|
||||
assert Enum.reduce([1, 2, 3], 0, fn(element, accumulator) -> element + accumulator end) == ___
|
||||
assert Enum.reduce([1, 2, 3], 0, fn element, accumulator -> element + accumulator end) == ___
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,9 +18,11 @@ defmodule Processes do
|
||||
end
|
||||
|
||||
koan "New processes are spawned functions" do
|
||||
value = spawn(fn -> receive do
|
||||
end
|
||||
end)
|
||||
value =
|
||||
spawn(fn ->
|
||||
receive do
|
||||
end
|
||||
end)
|
||||
|
||||
assert is_pid(value) == ___
|
||||
end
|
||||
@@ -39,7 +41,7 @@ defmodule Processes do
|
||||
end
|
||||
|
||||
koan "Processes can send and receive messages" do
|
||||
send self(), "hola!"
|
||||
send(self(), "hola!")
|
||||
|
||||
receive do
|
||||
msg -> assert msg == ___
|
||||
@@ -58,8 +60,8 @@ defmodule Processes do
|
||||
end
|
||||
|
||||
koan "Received messages are queued, first in first out" do
|
||||
send self(), "hola!"
|
||||
send self(), "como se llama?"
|
||||
send(self(), "hola!")
|
||||
send(self(), "como se llama?")
|
||||
|
||||
assert_receive ___
|
||||
assert_receive ___
|
||||
@@ -68,20 +70,20 @@ defmodule Processes do
|
||||
koan "A common pattern is to include the sender in the message, so that it can reply" do
|
||||
greeter = fn ->
|
||||
receive do
|
||||
{:hello, sender} -> send sender, :how_are_you?
|
||||
{:hello, sender} -> send(sender, :how_are_you?)
|
||||
end
|
||||
end
|
||||
|
||||
pid = spawn(greeter)
|
||||
|
||||
send pid, {:hello, self()}
|
||||
send(pid, {:hello, self()})
|
||||
assert_receive ___
|
||||
end
|
||||
|
||||
def yelling_echo_loop do
|
||||
receive do
|
||||
{caller, value} ->
|
||||
send caller, String.upcase(value)
|
||||
send(caller, String.upcase(value))
|
||||
yelling_echo_loop()
|
||||
end
|
||||
end
|
||||
@@ -89,18 +91,19 @@ defmodule Processes do
|
||||
koan "Use tail recursion to receive multiple messages" do
|
||||
pid = spawn_link(&yelling_echo_loop/0)
|
||||
|
||||
send pid, {self(), "o"}
|
||||
send(pid, {self(), "o"})
|
||||
assert_receive ___
|
||||
|
||||
send pid, {self(), "hai"}
|
||||
send(pid, {self(), "hai"})
|
||||
assert_receive ___
|
||||
end
|
||||
|
||||
def state(value) do
|
||||
receive do
|
||||
{caller, :get} ->
|
||||
send caller, value
|
||||
send(caller, value)
|
||||
state(value)
|
||||
|
||||
{caller, :set, new_value} ->
|
||||
state(new_value)
|
||||
end
|
||||
@@ -108,38 +111,45 @@ defmodule Processes do
|
||||
|
||||
koan "Processes can be used to hold state" do
|
||||
initial_state = "foo"
|
||||
pid = spawn(fn ->
|
||||
state(initial_state)
|
||||
end)
|
||||
|
||||
send pid, {self(), :get}
|
||||
pid =
|
||||
spawn(fn ->
|
||||
state(initial_state)
|
||||
end)
|
||||
|
||||
send(pid, {self(), :get})
|
||||
assert_receive ___
|
||||
|
||||
send pid, {self(), :set, "bar"}
|
||||
send pid, {self(), :get}
|
||||
send(pid, {self(), :set, "bar"})
|
||||
send(pid, {self(), :get})
|
||||
assert_receive ___
|
||||
end
|
||||
|
||||
koan "Waiting for a message can get boring" do
|
||||
parent = self()
|
||||
spawn(fn -> receive do
|
||||
after
|
||||
5 -> send parent, {:waited_too_long, "I am impatient"}
|
||||
end
|
||||
end)
|
||||
|
||||
spawn(fn ->
|
||||
receive do
|
||||
after
|
||||
5 -> send(parent, {:waited_too_long, "I am impatient"})
|
||||
end
|
||||
end)
|
||||
|
||||
assert_receive ___
|
||||
end
|
||||
|
||||
koan "Trapping will allow you to react to someone terminating the process" do
|
||||
parent = self()
|
||||
pid = spawn(fn ->
|
||||
Process.flag(:trap_exit, true)
|
||||
send parent, :ready
|
||||
receive do
|
||||
{:EXIT, _pid, reason} -> send parent, {:exited, reason}
|
||||
end
|
||||
end)
|
||||
|
||||
pid =
|
||||
spawn(fn ->
|
||||
Process.flag(:trap_exit, true)
|
||||
send(parent, :ready)
|
||||
|
||||
receive do
|
||||
{:EXIT, _pid, reason} -> send(parent, {:exited, reason})
|
||||
end
|
||||
end)
|
||||
|
||||
receive do
|
||||
:ready -> true
|
||||
|
||||
@@ -10,23 +10,26 @@ defmodule Tasks do
|
||||
end
|
||||
|
||||
koan "If you don't need a result, use start_link/1" do
|
||||
{result, _pid} = Task.start_link(fn -> 1+1 end)
|
||||
{result, _pid} = Task.start_link(fn -> 1 + 1 end)
|
||||
assert result == ___
|
||||
end
|
||||
|
||||
koan "Yield returns nil if the task isn't done yet" do
|
||||
handle = Task.async(fn ->
|
||||
:timer.sleep(100)
|
||||
3 * 3
|
||||
end)
|
||||
handle =
|
||||
Task.async(fn ->
|
||||
:timer.sleep(100)
|
||||
3 * 3
|
||||
end)
|
||||
|
||||
assert Task.yield(handle, 10) == ___
|
||||
end
|
||||
|
||||
koan "Tasks can be aborted with shutdown" do
|
||||
handle = Task.async(fn ->
|
||||
:timer.sleep(100)
|
||||
3 * 3
|
||||
end)
|
||||
handle =
|
||||
Task.async(fn ->
|
||||
:timer.sleep(100)
|
||||
3 * 3
|
||||
end)
|
||||
|
||||
%Task{pid: pid} = handle
|
||||
Task.shutdown(handle)
|
||||
@@ -41,10 +44,11 @@ defmodule Tasks do
|
||||
end
|
||||
|
||||
koan "You can yield to multiple tasks at once and extract the results" do
|
||||
squares = [1, 2, 3, 4]
|
||||
|> Enum.map(fn(number) -> Task.async(fn -> number * number end) end)
|
||||
|> Task.yield_many(100)
|
||||
|> Enum.map(fn({_task,{:ok, result}}) -> result end)
|
||||
squares =
|
||||
[1, 2, 3, 4]
|
||||
|> Enum.map(fn number -> Task.async(fn -> number * number end) end)
|
||||
|> Task.yield_many(100)
|
||||
|> Enum.map(fn {_task, {:ok, result}} -> result end)
|
||||
|
||||
assert squares == ___
|
||||
end
|
||||
|
||||
@@ -5,36 +5,38 @@ defmodule Agents do
|
||||
|
||||
koan "Agents maintain state, so you can ask them about it" do
|
||||
{:ok, pid} = Agent.start_link(fn -> "Hi there" end)
|
||||
assert Agent.get(pid, &(&1)) == ___
|
||||
assert Agent.get(pid, & &1) == ___
|
||||
end
|
||||
|
||||
koan "Agents may also be named so that you don't have to keep the pid around" do
|
||||
Agent.start_link(fn -> "Why hello" end, name: AgentSmith)
|
||||
assert Agent.get(AgentSmith, &(&1)) == ___
|
||||
assert Agent.get(AgentSmith, & &1) == ___
|
||||
end
|
||||
|
||||
koan "Update to update the state" do
|
||||
Agent.start_link(fn() -> "Hi there" end, name: __MODULE__)
|
||||
Agent.start_link(fn -> "Hi there" end, name: __MODULE__)
|
||||
|
||||
Agent.update(__MODULE__, fn(old) ->
|
||||
Agent.update(__MODULE__, fn old ->
|
||||
String.upcase(old)
|
||||
end)
|
||||
assert Agent.get(__MODULE__, &(&1)) == ___
|
||||
|
||||
assert Agent.get(__MODULE__, & &1) == ___
|
||||
end
|
||||
|
||||
koan "Use get_and_update when you need to read and change a value in one go" do
|
||||
Agent.start_link(fn() -> ["Milk"] end, name: __MODULE__)
|
||||
Agent.start_link(fn -> ["Milk"] end, name: __MODULE__)
|
||||
|
||||
old_list = Agent.get_and_update(__MODULE__, fn(old) ->
|
||||
{old, ["Bread" | old]}
|
||||
end)
|
||||
old_list =
|
||||
Agent.get_and_update(__MODULE__, fn old ->
|
||||
{old, ["Bread" | old]}
|
||||
end)
|
||||
|
||||
assert old_list == ___
|
||||
assert Agent.get(__MODULE__, &(&1)) == ___
|
||||
assert Agent.get(__MODULE__, & &1) == ___
|
||||
end
|
||||
|
||||
koan "Somebody has to switch off the light at the end of the day" do
|
||||
{:ok, pid} = Agent.start_link(fn() -> ["Milk"] end, name: __MODULE__)
|
||||
{:ok, pid} = Agent.start_link(fn -> ["Milk"] end, name: __MODULE__)
|
||||
|
||||
Agent.stop(__MODULE__)
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ defmodule GenServers do
|
||||
# GenServer implementation
|
||||
|
||||
def handle_call(:get_password, _from, current_password) do
|
||||
{:reply, current_password, current_password}
|
||||
{:reply, current_password, current_password}
|
||||
end
|
||||
|
||||
def handle_call(:get_manufacturer, _from, current_state) do
|
||||
@@ -73,6 +73,7 @@ defmodule GenServers do
|
||||
case password do
|
||||
password when password === current_password ->
|
||||
{:reply, {:ok, "Laptop unlocked!"}, current_password}
|
||||
|
||||
_ ->
|
||||
{:reply, {:error, "Incorrect password!"}, current_password}
|
||||
end
|
||||
@@ -82,6 +83,7 @@ defmodule GenServers do
|
||||
case old_password do
|
||||
old_password when old_password == current_password ->
|
||||
{:noreply, new_password}
|
||||
|
||||
_ ->
|
||||
{:noreply, current_password}
|
||||
end
|
||||
@@ -147,7 +149,7 @@ defmodule GenServers do
|
||||
{_, response} = Laptop.unlock("EL!73")
|
||||
assert response == ___
|
||||
|
||||
{_, response} = Laptop.owner_name
|
||||
{_, response} = Laptop.owner_name()
|
||||
assert response == ___
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ defmodule Protocols do
|
||||
|
||||
@intro "Want to follow the rules? Adhere to the protocol!"
|
||||
|
||||
defprotocol School, do: def enroll(person)
|
||||
defprotocol(School, do: def(enroll(person)))
|
||||
|
||||
defimpl School, for: Any do
|
||||
def enroll(_) do
|
||||
@@ -16,9 +16,9 @@ defmodule Protocols do
|
||||
defstruct name: ""
|
||||
end
|
||||
|
||||
defmodule Musician, do: defstruct name: "", instrument: ""
|
||||
defmodule Dancer, do: defstruct name: "", dance_style: ""
|
||||
defmodule Baker, do: defstruct name: ""
|
||||
defmodule(Musician, do: defstruct(name: "", instrument: ""))
|
||||
defmodule(Dancer, do: defstruct(name: "", dance_style: ""))
|
||||
defmodule(Baker, do: defstruct(name: ""))
|
||||
|
||||
defimpl School, for: Musician do
|
||||
def enroll(musician) do
|
||||
|
||||
Reference in New Issue
Block a user