Cukeup nyc ian dees on elixir, erlang, and cucumberl
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Cukeup nyc ian dees on elixir, erlang, and cucumberl

on

  • 866 views

Elixir, Erlang, and Cucumberl ...

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.

Statistics

Views

Total Views
866
Views on SlideShare
738
Embed Views
128

Actions

Likes
0
Downloads
2
Comments
0

4 Embeds 128

http://skillsmatter.com 121
http://ngoding.co 3
http://smash 2
http://smash2 2

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Cukeup nyc ian dees on elixir, erlang, and cucumberl Presentation Transcript

  • 1. Cucumber and Elixir Ian Dees • @undees CukeUp! NYC 2013
  • 2. Why Elixir? The sad state of concurrency
  • 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. Semaphore& s = resourceSemaphore(); s.acquire(); laboriouslyCopyDataFromResource(); s.release(); doSomethingWithData();
  • 5. • Dangerous and hard-to-use message types • Corruption- and deadlock-prone locks
  • 6. It doesn’t have to be this way!
  • 7. A taste of Elixir http://elixir-lang.org Ruby style, Erlang substance
  • 8. Pattern matching
  • 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. Actor-style concurrency
  • 11. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  • 12. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  • 13. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  • 14. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  • 15. defmodule ShoutyEcho do def echo_loop do receive do {sender, msg} -> sender <- {:ok, String.upcase(msg)} echo_loop end end end
  • 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. pid = spawn(ShoutyEcho, :echo_loop, []) pid <- {self, "Your name here"} receive do {:ok, response} -> IO.puts response after 500 -> IO.puts "Done" end
  • 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. pid = spawn(ShoutyEcho, :echo_loop, []) pid <- {self, "Your name here"} receive do {:ok, response} -> IO.puts response after 500 -> IO.puts "Done" end
  • 20. Cucumberl https://github.com/membase/cucumberl
  • 21. Feature: Gray Code Scenario: Reset Given the LEDs read "ooo"
  • 22. -module(graycode). -export([given/3, main/0]). given([the, leds, read, _Input], State, _) -> {ok, State}. main() -> cucumberl:run("./features/graycode.feature").
  • 23. $ cucumberl Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" 1 scenarios 1 steps
  • 24. Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" When I reset the counter
  • 25. ---------NO-STEP-------- a step definition snippet... 'when'([i,reset,the,counter], State, _) -> undefined.
  • 26. ---------NO-STEP-------- a step definition snippet... 'when'([i,reset,the,counter], State, _) -> undefined.
  • 27. -module(graycode). -export([given/3, 'when'/3, main/0]). %% ... 'when'([i, reset, the, counter], State, _) -> {ok, State}. %% ...
  • 28. $ cucumberl Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" When I reset the counter 1 scenarios 2 steps
  • 29. I know what you’re thinking...
  • 30. What happens with the next “When” step?
  • 31. Feature: Gray Code Scenario: ... ... When I reset the counter Scenario: ... ... When I press the button
  • 32. Pattern matching!
  • 33. 'when'([i, reset, the, counter], State, _) -> {ok, State}; 'when'([i, press, the, button], State, _) -> {ok, State}.
  • 34. $ find . -type f ./ebin/graycode.beam ./features/graycode.feature ./src/graycode.erl
  • 35. $ find . -type f ./ebin/graycode.beam ./features/graycode.feature ./src/graycode.erl
  • 36. Just a .beam file!
  • 37. And now in Elixir!
  • 38. Feature: Gray Code Scenario: Reset Given the LEDs read "ooo"
  • 39. -module(graycode). -export([given/3, main/0]). given([the, leds, read, _Input], State, _) -> {ok, State}. main() -> cucumberl:run("./features/graycode.feature").
  • 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. $ iex c("src/graycode.ex", "ebin")
  • 42. $ find . -type f ./ebin/graycode.beam ./features/graycode.feature ./src/graycode.ex
  • 43. $ cucumberl Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" 1 scenarios 1 steps
  • 44. Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" When I reset the counter
  • 45. ---------NO-STEP-------- a step definition snippet... 'when'([i,reset,the,counter], State, _) -> undefined.
  • 46. ---------NO-STEP-------- a step definition snippet... 'when'([i,reset,the,counter], State, _) -> undefined.
  • 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. How to translate?
  • 49. Hacking Cucumberl
  • 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. %% 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. %% 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. %% 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. def when_([:i, :press, :the, :button], state, _) do {:ok, _next(state)} end
  • 55. $ cucumberl Feature: Gray Code Scenario: Reset Given the LEDs read "ooo" When I reset the counter 1 scenarios 2 steps
  • 56. def then([:the, :leds, :should, :read, expected], state, _) do {expected === state, state} end
  • 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. 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. Caveats
  • 60. 1. Cucumberl has no idea about the Elixir runtime
  • 61. 2.Who will do what about When?
  • 62. https://github.com/undees/cukeup