Cukeup nyc ian dees on elixir, erlang, and cucumberl

1,241 views

Published on

Elixir, Erlang, and Cucumberl
Elixir is a new Ruby-inspired programming language that uses the powerful concurrent machinery of Erlang behind the scenes. Cucumberl is a port of Cucumber to Erlang. Let's see what happens when we put them together.

In this talk, we'll discuss:
How Erlang's concurrency makes it easier to write robust programs
Elixir's approachable syntax
How to test Erlang and Elixir programs using Cucumberl
Attendees will walk away with a solid introduction to the principles of Erlang, and an appreciation of the way Elixir brings the joy of Ruby to the solidity of the Erlang runtime.

Published in: Technology, News & Politics
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,241
On SlideShare
0
From Embeds
0
Number of Embeds
139
Actions
Shares
0
Downloads
5
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Cukeup nyc ian dees on elixir, erlang, and cucumberl

  1. 1. Cucumber and Elixir Ian Dees • @undees CukeUp! NYC 2013
  2. 2. Why Elixir? The sad state of concurrency
  3. 3. int HandleMessage(MessageType type, unsigned long arg1, unsigned long arg2) { switch (type) { case SOME_MESSAGE: INFO* info = *((INFO*)arg2); doSomethingWith(info.field); return MEANINGFUL_ERROR_CODE; // ... } // ... }
  4. 4. Semaphore& s = resourceSemaphore(); s.acquire(); laboriouslyCopyDataFromResource(); s.release(); doSomethingWithData();
  5. 5. • Dangerous and hard-to-use message types • Corruption- and deadlock-prone locks
  6. 6. It doesn’t have to be this way!
  7. 7. A taste of Elixir http://elixir-lang.org Ruby style, Erlang substance
  8. 8. Pattern matching
  9. 9. defmodule Ackermann do def ack(0, n), do: n + 1 def ack(m, 0), do: ack(m - 1, 1) def ack(m, n), do: ack(m - 1, ack(m, n - 1)) end IO.puts Ackermann.ack(3, 9)
  10. 10. Actor-style concurrency
  11. 11. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  12. 12. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  13. 13. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  14. 14. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  15. 15. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  16. 16. pid = spawn(ShoutyEcho, :echo_loop, []) pid <- {self, "Your name here"} receive do {:ok, response} -> IO.puts response after 500 -> IO.puts "Done" end
  17. 17. pid = spawn(ShoutyEcho, :echo_loop, []) pid <- {self, "Your name here"} receive do {:ok, response} -> IO.puts response after 500 -> IO.puts "Done" end
  18. 18. pid = spawn(ShoutyEcho, :echo_loop, []) pid <- {self, "Your name here"} receive do {:ok, response} -> IO.puts response after 500 -> IO.puts "Done" end
  19. 19. pid = spawn(ShoutyEcho, :echo_loop, []) pid <- {self, "Your name here"} receive do {:ok, response} -> IO.puts response after 500 -> IO.puts "Done" end
  20. 20. Cucumberl https://github.com/membase/cucumberl
  21. 21. Feature: Gray Code Scenario: Reset Given the LEDs read "ooo"
  22. 22. -module(graycode). -export([given/3, main/0]). given([the, leds, read, _Input], State, _) -> {ok, State}. main() -> cucumberl:run("./features/graycode.feature").
  23. 23. $ cucumberl Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" 1 scenarios 1 steps
  24. 24. Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" When I reset the counter
  25. 25. ---------NO-STEP-------- a step definition snippet... 'when'([i,reset,the,counter], State, _) -> undefined.
  26. 26. ---------NO-STEP-------- a step definition snippet... 'when'([i,reset,the,counter], State, _) -> undefined.
  27. 27. -module(graycode). -export([given/3, 'when'/3, main/0]). %% ... 'when'([i, reset, the, counter], State, _) -> {ok, State}. %% ...
  28. 28. $ cucumberl Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" When I reset the counter 1 scenarios 2 steps
  29. 29. I know what you’re thinking...
  30. 30. What happens with the next “When” step?
  31. 31. Feature: Gray Code Scenario: ... ... When I reset the counter Scenario: ... ... When I press the button
  32. 32. Pattern matching!
  33. 33. 'when'([i, reset, the, counter], State, _) -> {ok, State}; 'when'([i, press, the, button], State, _) -> {ok, State}.
  34. 34. $ find . -type f ./ebin/graycode.beam ./features/graycode.feature ./src/graycode.erl
  35. 35. $ find . -type f ./ebin/graycode.beam ./features/graycode.feature ./src/graycode.erl
  36. 36. Just a .beam file!
  37. 37. And now in Elixir!
  38. 38. Feature: Gray Code Scenario: Reset Given the LEDs read "ooo"
  39. 39. -module(graycode). -export([given/3, main/0]). given([the, leds, read, _Input], State, _) -> {ok, State}. main() -> cucumberl:run("./features/graycode.feature").
  40. 40. defmodule :graycode do def given([:the, :leds, :read, input], _state, _) do {:ok, input} end def main() do :cucumberl.run("./features/graycode.feature") end end
  41. 41. $ iex c("src/graycode.ex", "ebin")
  42. 42. $ find . -type f ./ebin/graycode.beam ./features/graycode.feature ./src/graycode.ex
  43. 43. $ cucumberl Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" 1 scenarios 1 steps
  44. 44. Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" When I reset the counter
  45. 45. ---------NO-STEP-------- a step definition snippet... 'when'([i,reset,the,counter], State, _) -> undefined.
  46. 46. ---------NO-STEP-------- a step definition snippet... 'when'([i,reset,the,counter], State, _) -> undefined.
  47. 47. def 'when'([:i, :reset, :the, :counter], _state, _) do {:ok, '...'} end ➡ == Compilation error on file src/graycode.ex == ** (SyntaxError) ./src/graycode.ex:6: syntax error before: ')'
  48. 48. How to translate?
  49. 49. Hacking Cucumberl
  50. 50. %% cucumberl_gen.erl When = process_clauses('when', lists:reverse( sets:to_list(dict:fetch('when', Dict)))), ➡ When_ = process_clauses(when_, lists:reverse( sets:to_list(dict:fetch(when_, Dict)))),
  51. 51. %% cucumberl_gen.erl When = process_clauses('when', lists:reverse( sets:to_list(dict:fetch('when', Dict)))), ➡ When_ = process_clauses(when_, lists:reverse( sets:to_list(dict:fetch(when_, Dict)))),
  52. 52. %% cucumberl_parser.erl string_to_atoms(StrWords) -> lists:map(fun (Y) -> list_to_atom(string:to_lower(Y)) end, string:tokens(StrWords, " ")). ➡ list_to_valid_atom("when") -> list_to_atom("when_"); list_to_valid_atom(Str) -> list_to_atom(Str). string_to_atoms(StrWords) -> lists:map(fun (Y) -> list_to_valid_atom(string:to_lower(Y)) end, string:tokens(StrWords, " ")).
  53. 53. %% cucumberl_parser.erl string_to_atoms(StrWords) -> lists:map(fun (Y) -> list_to_atom(string:to_lower(Y)) end, string:tokens(StrWords, " ")). ➡ list_to_valid_atom("when") -> list_to_atom("when_"); list_to_valid_atom(Str) -> list_to_atom(Str). string_to_atoms(StrWords) -> lists:map(fun (Y) -> list_to_valid_atom(string:to_lower(Y)) end, string:tokens(StrWords, " ")).
  54. 54. def when_([:i, :press, :the, :button], state, _) do {:ok, _next(state)} end
  55. 55. $ cucumberl Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" When I reset the counter 1 scenarios 2 steps
  56. 56. def then([:the, :leds, :should, :read, expected], state, _) do {expected === state, state} end
  57. 57. Scenario Outline: Counter Given the LEDs read "<n>" When I press the button Then the LEDs should read "<nplus1>" Examples: | n | nplus1 | | ... | ..o | | ..o | .oo | | .oo | .o. | | .o. | oo. | | oo. | ooo | | ooo | o.o | | o.o | o.. | | o.. | ... |
  58. 58. def when_([:i, :press, :the, :button], state, _) do {:ok, _next(state)} end defp _next(leds) do case leds do '...' -> '..o' '..o' -> '.oo' '.oo' -> '.o.' '.o.' -> 'oo.' 'oo.' -> 'ooo' 'ooo' -> 'o.o' 'o.o' -> 'o..' 'o..' -> '...' end end
  59. 59. Caveats
  60. 60. 1. Cucumberl has no idea about the Elixir runtime
  61. 61. 2.Who will do what about When?
  62. 62. https://github.com/undees/cukeup

×