From 51b3739f4640cfd11c9e0a9c495c5955cda48c85 Mon Sep 17 00:00:00 2001 From: Felipe Sere Date: Sat, 6 Feb 2016 12:30:11 +0000 Subject: [PATCH 1/2] Basic koans for the Enum module. --- lib/koans/06_enum.ex | 85 ++++++++++++++++++++++++++++++++++++++++++++ lib/runner.ex | 3 +- 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 lib/koans/06_enum.ex diff --git a/lib/koans/06_enum.ex b/lib/koans/06_enum.ex new file mode 100644 index 0000000..e2202e7 --- /dev/null +++ b/lib/koans/06_enum.ex @@ -0,0 +1,85 @@ +defmodule Enums do + use Koans + + koan "can tell you how many elements there are" do + assert Enum.count([1,2,3,4]) == 4 + end + + koan "enumerable can tell you if all elements have a certain property" do + assert Enum.all?([1,2,3], fn element -> element < 5 end) + + refute Enum.all?([1, 2, 3], fn element -> element > 5 end) + end + + koan "can tell you if there is _some_ element in the list for which a property holds" do + assert Enum.any?([1,2,3], fn element -> rem(element, 2) == 0 end) + + Enum.any?([1,2,3], fn element -> rem(element, 5) == 0 end) + end + + koan "can tell if an element is in the enumerable" do + assert Enum.member?([1,2,3], 1) + + refute Enum.member?([1,2,3], 30) + end + + koan "converts elements by calling a function for each element" do + assert Enum.map([1,2,3], fn element -> element * 10 end) == [10,20,30] + assert Enum.map([1,2,3], fn element -> rem(element, 2) == 0 end) == [false, true, false] + end + + koan "only keeps elements that match a certain criteria" do + assert Enum.filter([1,2,3], fn element -> rem(element, 2) == 1 end) == [1,3] + end + + koan "removes elements that match a certain criteria" do + assert Enum.reject([1,2,3], fn element -> rem(element, 2) == 1 end) == [2] + end + + koan "can take a number of elements" do + assert Enum.take([1,2,3,4,5], 3) == [1,2,3] + assert Enum.take([1,2,3,4,5], 10) == [1,2,3,4,5] + end + + koan "can take as long as a property holds" do + assert Enum.take_while([1,2,3,4,5], fn element -> element < 4 end) == [1,2,3] + end + + koan "can drop a number of elements" do + assert Enum.drop([-1,0,1,2,3], 2) == [1,2,3] + end + + koan "can drop as long as a property holds" do + assert Enum.drop_while([-1,0,1,2,3], fn element -> element <= 0 end) == [1,2,3] + end + + koan "can group elements by things they have in common" do + assert Enum.group_by([1,2,3,4,5,6], fn element -> rem(element, 3) end) == %{ 0 => [6, 3], 1 => [4, 1], 2 => [5, 2]} + + 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) == %{ :odd => [3,1], :even => [4,2] } + end + + koan "can merge two lists by picking pairs" do + numbers = [1,2,3] + letters = [:a, :b, :c] + + assert Enum.zip(numbers, letters) == [{1, :a}, {2, :b}, {3, :c}] + + more_numbers = numbers ++ [4,5] + assert Enum.zip(more_numbers, letters) == [{1, :a}, {2, :b}, {3, :c}] + end + + koan "can find elements by properties" do + assert Enum.find([1,2,3], fn element -> rem(element,2) == 0 end) == 2 + assert Enum.find([1,2,3], fn element -> rem(element,5) == 0 end) == nil + assert Enum.find([1,2,3], :no_such_element, fn element -> rem(element,5) == 0 end) == :no_such_element + end + + koan "can reduce stuff" do + assert Enum.reduce([1,2,3], 0, fn(element, accumulator) -> element + accumulator end) == 6 + + assert Enum.reduce(["1", "2", "3"], "", fn(element, accumulator) -> element <> accumulator end) == "321" + end +end diff --git a/lib/runner.ex b/lib/runner.ex index a8f3664..9a049b4 100644 --- a/lib/runner.ex +++ b/lib/runner.ex @@ -4,7 +4,8 @@ defmodule Runner do Strings, Lists, Maps, - Functions + Functions, + Enums ] def run do From b1baf1955bcadb96c44f04c5604d1845997c44b4 Mon Sep 17 00:00:00 2001 From: Felipe Sere Date: Mon, 8 Feb 2016 21:14:55 +0000 Subject: [PATCH 2/2] Make the enum koans a tad more entretaining. --- lib/koans/06_enum.ex | 85 +++++++++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/lib/koans/06_enum.ex b/lib/koans/06_enum.ex index e2202e7..0ebbcf2 100644 --- a/lib/koans/06_enum.ex +++ b/lib/koans/06_enum.ex @@ -1,83 +1,120 @@ defmodule Enums do use Koans - koan "can tell you how many elements there are" do + koan "knowing how many elements are in a list is important for book-keeping!" do assert Enum.count([1,2,3,4]) == 4 end - koan "enumerable can tell you if all elements have a certain property" do + koan "..the same applies for counting elements in a map..." do + assert Enum.count(%{ :a => 1, :b => 2, :c => 3, :d => 4}) == 4 + end + + koan "..or a keyword list..." do + assert Enum.count([a: 1, b: 2, c: 3, d: 4]) == 4 + end + + koan "all? can tell you if all your element have something in common!" do assert Enum.all?([1,2,3], fn element -> element < 5 end) - - refute Enum.all?([1, 2, 3], fn element -> element > 5 end) end - koan "can tell you if there is _some_ element in the list for which a property holds" do + koan "the key aspec is _all_ : if one if different, all? will let you know!" do + refute Enum.all?([1, 2, 3], fn element -> element <= 2 end) + end + + koan "sometimes you you just want to know if there is _some_ element with a certain trait." do assert Enum.any?([1,2,3], fn element -> rem(element, 2) == 0 end) - - Enum.any?([1,2,3], fn element -> rem(element, 5) == 0 end) end - koan "can tell if an element is in the enumerable" do - assert Enum.member?([1,2,3], 1) + koan "if not a single element fits the bill, any? returns false" do + refute Enum.any?([1,2,3], fn element -> rem(element, 5) == 0 end) + end + koan "Sometimes you just want to know if an element is part of the party" do + assert Enum.member?([1,2,3], 1) + end + + koan "And sometimes your invited guests don't show up and miss the party" do refute Enum.member?([1,2,3], 30) end - koan "converts elements by calling a function for each element" do + koan "map converts each element of a list by running some function with it" do assert Enum.map([1,2,3], fn element -> element * 10 end) == [10,20,30] + end + + koan "You can even return a list with entirely different types!" do assert Enum.map([1,2,3], fn element -> rem(element, 2) == 0 end) == [false, true, false] end - koan "only keeps elements that match a certain criteria" do + koan "But keep in mind that the original list remains unchanged!" do + input = [1,2,3] + assert Enum.map(input, fn element -> rem(element, 2) == 0 end) == [false, true, false] + assert input == [1,2,3] + end + + koan "Filter allows you to only keep what you really care about." do assert Enum.filter([1,2,3], fn element -> rem(element, 2) == 1 end) == [1,3] end - koan "removes elements that match a certain criteria" do + koan "Reject will help you throw out unwanted cruft." do assert Enum.reject([1,2,3], fn element -> rem(element, 2) == 1 end) == [2] end - koan "can take a number of elements" do + koan "You three there, follow me!" do assert Enum.take([1,2,3,4,5], 3) == [1,2,3] + end + + koan "...you can ask for a lot, but Enum won't hand you more than you give" do assert Enum.take([1,2,3,4,5], 10) == [1,2,3,4,5] end - koan "can take as long as a property holds" do + koan "Take what you can..." do assert Enum.take_while([1,2,3,4,5], fn element -> element < 4 end) == [1,2,3] end - koan "can drop a number of elements" do + koan "Just like taking, you can also drop elements" do assert Enum.drop([-1,0,1,2,3], 2) == [1,2,3] end - koan "can drop as long as a property holds" do + koan "...and drop elements until you are happy." do assert Enum.drop_while([-1,0,1,2,3], fn element -> element <= 0 end) == [1,2,3] end - koan "can group elements by things they have in common" do - assert Enum.group_by([1,2,3,4,5,6], fn element -> rem(element, 3) end) == %{ 0 => [6, 3], 1 => [4, 1], 2 => [5, 2]} - + 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) == %{ :odd => [3,1], :even => [4,2] } end - koan "can merge two lists by picking pairs" do + 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) == %{ 0 => [6, 3], 1 => [4, 1], 2 => [5, 2]} + + end + + koan "Zip-up in pairs!" do numbers = [1,2,3] letters = [:a, :b, :c] - assert Enum.zip(numbers, letters) == [{1, :a}, {2, :b}, {3, :c}] + end - more_numbers = numbers ++ [4,5] + 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) == [{1, :a}, {2, :b}, {3, :c}] end - koan "can find elements by properties" do + koan "When you want to find that one pesky element..." do assert Enum.find([1,2,3], fn element -> rem(element,2) == 0 end) == 2 + end + + koan "...but you don't quite find it..." do assert Enum.find([1,2,3], fn element -> rem(element,5) == 0 end) == nil + end + + koan "...you can settle for a consolation prize" do assert Enum.find([1,2,3], :no_such_element, fn element -> rem(element,5) == 0 end) == :no_such_element end - koan "can reduce stuff" do + 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) == 6 assert Enum.reduce(["1", "2", "3"], "", fn(element, accumulator) -> element <> accumulator end) == "321"