From c970ed01ddf05019ff414c5e4fcd96b56c59df0e Mon Sep 17 00:00:00 2001 From: gemcfadyen Date: Wed, 25 May 2016 17:44:42 +0100 Subject: [PATCH 1/5] Protocol examples updated to use Structs --- lib/koans/16_protocols.ex | 50 +++++++++++++++++++++++++++++ lib/runner.ex | 1 + mix.lock | 4 +-- test/koans/protocols_koans_test.exs | 14 ++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 lib/koans/16_protocols.ex create mode 100644 test/koans/protocols_koans_test.exs diff --git a/lib/koans/16_protocols.ex b/lib/koans/16_protocols.ex new file mode 100644 index 0000000..7c510a2 --- /dev/null +++ b/lib/koans/16_protocols.ex @@ -0,0 +1,50 @@ +defmodule Protocols do + use Koans + + defprotocol School do + def enrol(person) + end + + defmodule Student do + defstruct name: "" + end + + defmodule Dancer do + defstruct name: "", dance_style: "" + end + + defmodule Baker do + defstruct name: "" + end + + defimpl School, for: Student do + def enrol(student) do + "#{student.name} enrolled at secondary school" + end + end + + defimpl School, for: Dancer do + def enrol(dancer) do + "#{dancer.name} enrolled for #{dancer.dance_style}" + end + end + + defmodule EveningSchool do end + + koan "Sharing an interface is the secret at school" do + student = %Student{name: "Emily"} + assert School.enrol(student) == ___ + end + + koan "Dancers share but belong to a different school" do + dancer = %Dancer{name: "Darcy", dance_style: "ballet"} + assert School.enrol(dancer) == ___ + + end + + koan "If you don't comply you can't get in" do + assert_raise ___, fn -> + School.enrol(%Baker{name: "Delia"}) + end + end +end diff --git a/lib/runner.ex b/lib/runner.ex index 401db50..62061ee 100644 --- a/lib/runner.ex +++ b/lib/runner.ex @@ -15,6 +15,7 @@ defmodule Runner do Processes, Tasks, Agents, + Protocols, ] def koan?(koan), do: Enum.member?(@modules, koan) diff --git a/mix.lock b/mix.lock index e28c9aa..0a97bce 100644 --- a/mix.lock +++ b/mix.lock @@ -1,2 +1,2 @@ -%{"exfswatch": {:hex, :exfswatch, "0.1.1"}, - "fs": {:hex, :fs, "0.9.2"}} +%{"exfswatch": {:hex, :exfswatch, "0.1.1", "7ccf6fc9b443d04dada3e50b21f910b4d0e4546ce7772dc6d4181fb929ea186f", [:mix], [{:fs, "~> 0.9", [hex: :fs, optional: false]}]}, + "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []}} diff --git a/test/koans/protocols_koans_test.exs b/test/koans/protocols_koans_test.exs new file mode 100644 index 0000000..94c1ea5 --- /dev/null +++ b/test/koans/protocols_koans_test.exs @@ -0,0 +1,14 @@ +defmodule ProtocolsTests do + use ExUnit.Case + import TestHarness + + test "Protocols" do + answers = [ + "Emily enrolled at secondary school", + "Darcy enrolled for ballet", + Protocol.UndefinedError + ] + + test_all(Protocols, answers) + end +end From 143b2bb7ffab3910178f9e9fe815744d28e2ec64 Mon Sep 17 00:00:00 2001 From: gemcfadyen Date: Thu, 26 May 2016 09:14:53 +0100 Subject: [PATCH 2/5] collapse two koans into one --- lib/koans/16_protocols.ex | 31 ++++++++--------------------- test/koans/protocols_koans_test.exs | 3 +-- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/lib/koans/16_protocols.ex b/lib/koans/16_protocols.ex index 7c510a2..96bb935 100644 --- a/lib/koans/16_protocols.ex +++ b/lib/koans/16_protocols.ex @@ -1,45 +1,30 @@ defmodule Protocols do use Koans - defprotocol School do - def enrol(person) - end + @intro "Protocols" - defmodule Student do - defstruct name: "" - end + defprotocol School, do: def enrol(person) + defmodule Student, do: defstruct name: "" + defmodule Baker, do: defstruct name: "" defmodule Dancer do defstruct name: "", dance_style: "" end - defmodule Baker do - defstruct name: "" - end - defimpl School, for: Student do - def enrol(student) do - "#{student.name} enrolled at secondary school" - end + def enrol(student), do: "#{student.name} enrolled at secondary school" end defimpl School, for: Dancer do - def enrol(dancer) do - "#{dancer.name} enrolled for #{dancer.dance_style}" - end + def enrol(dancer), do: "#{dancer.name} enrolled for #{dancer.dance_style}" end - defmodule EveningSchool do end - koan "Sharing an interface is the secret at school" do student = %Student{name: "Emily"} - assert School.enrol(student) == ___ - end - - koan "Dancers share but belong to a different school" do dancer = %Dancer{name: "Darcy", dance_style: "ballet"} - assert School.enrol(dancer) == ___ + assert School.enrol(student) == ___ + assert School.enrol(dancer) == ___ end koan "If you don't comply you can't get in" do diff --git a/test/koans/protocols_koans_test.exs b/test/koans/protocols_koans_test.exs index 94c1ea5..579094d 100644 --- a/test/koans/protocols_koans_test.exs +++ b/test/koans/protocols_koans_test.exs @@ -4,8 +4,7 @@ defmodule ProtocolsTests do test "Protocols" do answers = [ - "Emily enrolled at secondary school", - "Darcy enrolled for ballet", + {:multiple, ["Emily enrolled at secondary school", "Darcy enrolled for ballet"]}, Protocol.UndefinedError ] From e9ab72744898660165375c26b8f9b2534668aeb5 Mon Sep 17 00:00:00 2001 From: gemcfadyen Date: Fri, 27 May 2016 10:09:33 +0100 Subject: [PATCH 3/5] Adds a koan to demonstrate the use of deriving a default behaviour --- lib/koans/16_protocols.ex | 32 +++++++++++++++++++++-------- test/koans/protocols_koans_test.exs | 3 ++- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/koans/16_protocols.ex b/lib/koans/16_protocols.ex index 96bb935..1322ad5 100644 --- a/lib/koans/16_protocols.ex +++ b/lib/koans/16_protocols.ex @@ -5,14 +5,25 @@ defmodule Protocols do defprotocol School, do: def enrol(person) - defmodule Student, do: defstruct name: "" - defmodule Baker, do: defstruct name: "" - defmodule Dancer do - defstruct name: "", dance_style: "" + defimpl School, for: Any do + def enrol(person) do + "#{person.name} enrolled at school" + end end - defimpl School, for: Student do - def enrol(student), do: "#{student.name} enrolled at secondary school" + defmodule Student do + @derive School + defstruct name: "" + end + + defmodule Musician, do: defstruct name: "", instrument: "" + defmodule Dancer, do: defstruct name: "", dance_style: "" + defmodule Baker, do: defstruct name: "" + + defimpl School, for: Musician do + def enrol(musician) do + "#{musician.name} signed up for #{musician.instrument}" + end end defimpl School, for: Dancer do @@ -20,13 +31,18 @@ defmodule Protocols do end koan "Sharing an interface is the secret at school" do - student = %Student{name: "Emily"} + musician = %Musician{name: "Andre", instrument: "violin"} dancer = %Dancer{name: "Darcy", dance_style: "ballet"} - assert School.enrol(student) == ___ + assert School.enrol(musician) == ___ assert School.enrol(dancer) == ___ end + koan "Sometimes we all use the same" do + student = %Student{name: "Emily"} + assert School.enrol(student) == ___ + end + koan "If you don't comply you can't get in" do assert_raise ___, fn -> School.enrol(%Baker{name: "Delia"}) diff --git a/test/koans/protocols_koans_test.exs b/test/koans/protocols_koans_test.exs index 579094d..a773786 100644 --- a/test/koans/protocols_koans_test.exs +++ b/test/koans/protocols_koans_test.exs @@ -4,7 +4,8 @@ defmodule ProtocolsTests do test "Protocols" do answers = [ - {:multiple, ["Emily enrolled at secondary school", "Darcy enrolled for ballet"]}, + {:multiple, ["Andre signed up for violin", "Darcy enrolled for ballet"]}, + "Emily enrolled at school", Protocol.UndefinedError ] From 5b2ff206fab1d1235ce75ae985e9e6fae5fb2498 Mon Sep 17 00:00:00 2001 From: gemcfadyen Date: Fri, 27 May 2016 10:17:21 +0100 Subject: [PATCH 4/5] update the default case to use a generic message --- lib/koans/16_protocols.ex | 4 ++-- test/koans/protocols_koans_test.exs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/koans/16_protocols.ex b/lib/koans/16_protocols.ex index 1322ad5..e547929 100644 --- a/lib/koans/16_protocols.ex +++ b/lib/koans/16_protocols.ex @@ -6,8 +6,8 @@ defmodule Protocols do defprotocol School, do: def enrol(person) defimpl School, for: Any do - def enrol(person) do - "#{person.name} enrolled at school" + def enrol(_) do + "Pupil enrolled at school" end end diff --git a/test/koans/protocols_koans_test.exs b/test/koans/protocols_koans_test.exs index a773786..88dcbb7 100644 --- a/test/koans/protocols_koans_test.exs +++ b/test/koans/protocols_koans_test.exs @@ -5,7 +5,7 @@ defmodule ProtocolsTests do test "Protocols" do answers = [ {:multiple, ["Andre signed up for violin", "Darcy enrolled for ballet"]}, - "Emily enrolled at school", + "Pupil enrolled at school", Protocol.UndefinedError ] From d9ee4ccea89b84c3a9e563661ce0bd6e07698f07 Mon Sep 17 00:00:00 2001 From: gemcfadyen Date: Fri, 27 May 2016 10:24:35 +0100 Subject: [PATCH 5/5] Adds an introduction --- lib/koans/16_protocols.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/koans/16_protocols.ex b/lib/koans/16_protocols.ex index e547929..b8d5b4d 100644 --- a/lib/koans/16_protocols.ex +++ b/lib/koans/16_protocols.ex @@ -1,7 +1,7 @@ defmodule Protocols do use Koans - @intro "Protocols" + @intro "Wan't to follow the rules? Adhere to the protocol!" defprotocol School, do: def enrol(person)