Merge pull request #66 from ukutaht/improve_enum_koans

Improve enum koans
This commit is contained in:
Uku Taht
2016-04-11 13:54:47 +01:00
7 changed files with 33 additions and 89 deletions

View File

@@ -1,5 +1,12 @@
defmodule Koans do defmodule Koans do
defp valid_name(name) do
Regex.match?(~r/([A-Z]|\.\.\.).+/, name)
end
defmacro koan(name, body) do defmacro koan(name, body) do
if not valid_name(name) do
raise "Name does not start with a capital ltter: #{name}"
end
compiled_name = String.to_atom(name) compiled_name = String.to_atom(name)
number_of_args = Blanks.count(body) number_of_args = Blanks.count(body)
quote do quote do

View File

@@ -1,52 +1,51 @@
defmodule Arithmetic do defmodule Arithmetic do
use Koans use Koans
koan "it can add numbers" do koan "It can add numbers" do
assert 3 + :__ == 7 assert 3 + :__ == 7
end end
koan "it can substract numbers" do koan "It can substract numbers" do
assert 7 - 4 == :__ assert 7 - 4 == :__
end end
koan "it can multiply" do koan "It can multiply" do
assert 3 * 4 == :__ assert 3 * 4 == :__
end end
koan "floats and integers can be equal..." do koan "Floats and integers can be equal..." do
assert 3.0 == :__ assert 3.0 == :__
end end
koan "..unless they are not precisely the same" do koan "...unless they are not precisely the same" do
assert 3.2 != :__ assert 3.2 != :__
end end
koan "it does floating point division" do koan "It does floating point division" do
assert 5 / 2 == :__ assert 5 / 2 == :__
end end
koan "it does integer division" do koan "It does integer division" do
numerator = 5 numerator = 5
denominator = 2 denominator = 2
assert div(numerator, denominator) == :__ assert div(numerator, denominator) == :__
end end
koan "it calculates the remainder of a division" do koan "It calculates the remainder of a division" do
numerator = 5 numerator = 5
denominator = 2 denominator = 2
assert rem(numerator, denominator) == :__ assert rem(numerator, denominator) == :__
end end
koan "it finds the maximum in a list" do koan "It finds the maximum in a list" do
assert Enum.max([1,2,3,4]) == :__ assert Enum.max([1,2,3,4]) == :__
end end
koan "it finds the minimum in a list" do koan "It finds the minimum in a list" do
assert Enum.min([1,2,3,4]) == :__ assert Enum.min([1,2,3,4]) == :__
end end
koan "it can compare numbers" do koan "It can compare numbers" do
assert 5 > :__ assert 5 > :__
end end
end end

View File

@@ -5,60 +5,33 @@ defmodule Enums do
assert Enum.count([1,2,3]) == :__ assert Enum.count([1,2,3]) == :__
end end
koan "The same applies for counting elements in a map" do koan "Depending on the type, it counts pairs" do
assert Enum.count(%{ :a => :foo, :b => :bar}) == :__ assert Enum.count(%{ :a => :foo, :b => :bar}) == :__
end end
koan "Or a keyword list" do
assert Enum.count([a: 77, b: 23, c: 12, d: 33, e: 90, f: 113]) == :__
end
def less_than_five?(n), do: n < 5 def less_than_five?(n), do: n < 5
koan "Elements can have a lot in common" do koan "Elements can have a lot in common" do
assert Enum.all?([1,2,3], &less_than_five?/1) == :__ assert Enum.all?([1,2,3], &less_than_five?/1) == :__
end assert Enum.all?([6,7,8,9], &less_than_five?/1) == :__
def less_than_two?(n), do: n < 2
koan "If one if different, all elements are not alike" do
assert Enum.all?([1, 2, 3, 2], &less_than_two?/1) == :__
end end
def even?(n), do: rem(n, 2) == 0 def even?(n), do: rem(n, 2) == 0
koan "Sometimes you you just want to know if there are any elements fullfilling a condition" do
koan "sometimes you you just want to know if there are any elements fullfilling a condition" do
assert Enum.any?([1,2,3], &even?/1) == :__ assert Enum.any?([1,2,3], &even?/1) == :__
end assert Enum.any?([1,3,5], &even?/1) == :__
def divisible_by_five?(n), do: rem(n, 5) == 0
koan "if not a single element fits the bill, any? returns false" do
assert Enum.any?([1,2,3], &divisible_by_five?/1) == :__
end end
koan "Sometimes you just want to know if an element is part of the party" do koan "Sometimes you just want to know if an element is part of the party" do
assert Enum.member?([1,2,3], 1) == :__ input = [1,2,3]
end assert Enum.member?(input, 1) == :__
assert Enum.member?(input, 30) == :__
koan "And sometimes your invited guests don't show up and miss the party" do
assert Enum.member?([1,2,3], 30) == :__
end end
def multiply_by_ten(n), do: 10 * n def multiply_by_ten(n), do: 10 * n
koan "Map converts each element of a list by running some function with it" do
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) == :__ assert Enum.map([1,2,3], &multiply_by_ten/1) == :__
end end
koan "You can even return a list with entirely different types" do
assert Enum.map([1,2,3], &even?/1) == :__
end
koan "But keep in mind that the original list remains unchanged" do
input = [1,2,3,4]
assert Enum.map(input, &even?/1) == :__
assert input == :__
end
def odd?(n), do: rem(n, 2) == 1 def odd?(n), do: rem(n, 2) == 1
koan "Filter allows you to only keep what you really care about" do koan "Filter allows you to only keep what you really care about" do
@@ -77,45 +50,21 @@ defmodule Enums do
assert Enum.take([1,2,3,4,5], 10) == :__ assert Enum.take([1,2,3,4,5], 10) == :__
end end
koan "Take what you can..." do
assert Enum.take_while([1,2,3,4,5,6,7], &less_than_five?/1) == :__
end
koan "Just like taking, you can also drop elements" do koan "Just like taking, you can also drop elements" do
assert Enum.drop([-1,0,1,2,3], 2) == :__ assert Enum.drop([-1,0,1,2,3], 2) == :__
end end
def negative?(n), do: n < 0
koan "Drop elements until you are happy" do
assert Enum.drop_while([-1,0,1,2,3], &negative?/1) == :__
end
koan "Forming groups makes uns stronger" do
odd_or_even = fn element -> if rem(element, 2) == 0 do :even else :odd end end
assert Enum.group_by([1,2,3,4], odd_or_even) == :__
end
koan "You get as many groups as you can have different results" do
assert Enum.group_by([1,2,3,4,5,6], fn element -> rem(element, 3) end) == :__
end
koan "Zip-up in pairs!" do koan "Zip-up in pairs!" do
numbers = [1,2,3] numbers = [1,2,3]
letters = [:a, :b, :c] letters = [:a, :b, :c]
assert Enum.zip(numbers, letters) == :__ assert Enum.zip(numbers, letters) == :__
end end
koan "Sorry, but if you don't have a pair you are left out" do
more_numbers = [1,2,3] ++ [4,5]
letters = [:a, :b, :c]
assert Enum.zip(more_numbers, letters) == :__
end
koan "When you want to find that one pesky element" do koan "When you want to find that one pesky element" do
assert Enum.find([1,2,3], &even?/1) == :__ assert Enum.find([1,2,3], &even?/1) == :__
end end
def divisible_by_five?(n), do: rem(n, 5) == 0
koan "...but you don't quite find it..." do koan "...but you don't quite find it..." do
assert Enum.find([1,2,3], &divisible_by_five?/1) == :__ assert Enum.find([1,2,3], &divisible_by_five?/1) == :__
end end

View File

@@ -28,7 +28,7 @@ defmodule Tasks do
assert Task.shutdown(handle) == :__ assert Task.shutdown(handle) == :__
end end
koan "shutdown will give you an answer if it has it" do koan "Shutdown will give you an answer if it has it" do
handle = Task.async(fn -> 3 * 3 end) handle = Task.async(fn -> 3 * 3 end)
:timer.sleep(10) :timer.sleep(10)
assert Task.shutdown(handle) == {:ok, :__} assert Task.shutdown(handle) == {:ok, :__}

View File

@@ -156,26 +156,15 @@ defmodule KoansHarnessTest do
answers = [ answers = [
3, 3,
2, 2,
6, {:multiple, [true, false]},
true, {:multiple, [true, false]},
false, {:multiple, [true, false]},
true,
false,
true,
false,
[10,20,30], [10,20,30],
[false, true, false],
{:multiple, [ [false, true, false, true], [1,2,3,4] ] },
[1,3], [1,3],
[2], [2],
[1,2,3], [1,2,3],
[1,2,3,4,5], [1,2,3,4,5],
[1,2,3,4],
[1,2,3], [1,2,3],
[0,1,2,3],
%{ :odd => [3,1], :even => [4,2] },
%{ 0 => [6, 3], 1 => [4, 1], 2 => [5, 2]},
[{1, :a}, {2, :b}, {3, :c}],
[{1, :a}, {2, :b}, {3, :c}], [{1, :a}, {2, :b}, {3, :c}],
2, 2,
nil, nil,

View File

@@ -1,7 +1,7 @@
defmodule PassingKoan do defmodule PassingKoan do
use Koans use Koans
koan "hi there" do koan "Hi there" do
assert 1 == 1 assert 1 == 1
end end
end end

View File

@@ -1,7 +1,7 @@
defmodule SampleKoan do defmodule SampleKoan do
use Koans use Koans
koan "thinking more than once" do koan "Thinking more than once" do
assert 3 == :__ assert 3 == :__
assert 4 == :__ assert 4 == :__
end end