Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ClojurianからみたElixir

799 views

Published on

Elixir from a Clojurian's Perspective
Clojure使い(Clojurian)としてElixirに入門した話です(*> ᴗ •*)ゞ

Published in: Software
  • Be the first to comment

ClojurianからみたElixir

  1. 1. Clojurian ElixirClojurian Elixir
  2. 2. lagénorhynquelagénorhynque (defprofile lagénorhynque :id @lagenorhynque :reading "/laʒenɔʁɛ̃k/" :aliases [" "] :languages [Clojure Haskell English français] :interests [programming language-learning law mathematics] :commits ["github.com/lagenorhynque/duct.module.pedestal"] :contributes ["github.com/japan-clojurians/clojure-site-ja"])
  3. 3. 6 Lisp6 Lisp (*> ᴗ •*)(*> ᴗ •*) Clojure : REST API cf. BOOTH https://booth.pm/ja/items/1317263
  4. 4. 1. Clojure Elixir 2. Elixir 3. Clojure 4. Clojure
  5. 5. Clojure ElixirClojure Elixir
  6. 6. ClojureClojure : : 2007 : : Java VM (JVM) Lisp / Rich Hickey 1.10.0
  7. 7. ElixirElixir : : 2011 : : Erlang VM (EVM; BEAM) Ruby Clojure José Valim 1.8.2
  8. 8. e.g. 20e.g. 20 ClojureClojure ;; REPL (read-eval-print loop) user> (->> (iterate (fn [[a b]] [b (+ a b)]) [0 1]) (map first) (take 20)) (0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)
  9. 9. ElixirElixir # IEx (Interactive Elixir) iex(1)> Stream.iterate({0, 1}, fn {a, b} -> {b, a+b} end) |> ...(1)> Stream.map(&elem(&1, 0)) |> ...(1)> Enum.take(20) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181] # iex(2)> Stream.unfold({0, 1}, fn {a, b} -> {a, {b, a+b}} end) |> ...(2)> Enum.take(20) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
  10. 10. ElixirElixir à la Clojure?
  11. 11. Clojure 2Clojure 2
  12. 12. cf. :cf. : Programming Clojure, Third EditionProgramming Clojure, Third Edition
  13. 13. ElixirElixir
  14. 14. cf. :cf. : Programming Elixir ≥ 1.6Programming Elixir ≥ 1.6
  15. 15. Ruby, Io, Prolog, Scala, Erlang, Clojure, Haskell 7 77 7
  16. 16. Lua, Factor, Elixir, Elm, Julia, MiniKanren, Idris Seven More Languages in Seven WeeksSeven More Languages in Seven Weeks
  17. 17. Chapter 3, 4, 6: Clojure Chapter 5: Elixir Seven Concurrency Models in Seven WeeksSeven Concurrency Models in Seven Weeks
  18. 18. Mastering Clojure MacrosMastering Clojure Macros
  19. 19. Metaprogramming ElixirMetaprogramming Elixir
  20. 20. Elixir Erlang/OTPElixir Erlang/OTP ElixirElixir
  21. 21. ElixirElixir ElixirElixir
  22. 22. ElixirElixir Getting StartedGetting Started
  23. 23. Erlang/Elixir Syntax: A Crash CourseErlang/Elixir Syntax: A Crash Course
  24. 24. ClojureClojure
  25. 25. ClojureClojure ElixirElixir cf. (Clojure ) user> '(1 2 3) ; ※ (1 2 3) user> [1 2 3] ; [1 2 3] user> {:a 1 :b 2 :c 3} ; {:a 1, :b 2, :c 3} iex(2)> [1, 2, 3] # [1, 2, 3] iex(3)> {1, 2, 3} # {1, 2, 3} iex(4)> %{a: 1, b: 2, c: 3} # %{a: 1, b: 2, c: 3}
  26. 26. // ClojureClojure ElixirElixir user> (ns example) ; `example` nil example> (defn square [x] ; `square` (* x x)) #'example/square example> (in-ns 'user) ; `user` #namespace[user] user> iex(5)> defmodule Example do # `Example` ...(5)> def square(x) do # `square` ...(5)> x * x ...(5)> end ...(5)> end {:module, Example, <<70, 79, 82, 49, 0, 0, 4, 100, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 14, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:square, 1}}
  27. 27. ClojureClojure ElixirElixir user> (example/square 3) ; `example` `square` 9 user> (map example/square (range 1 (inc 10))) (1 4 9 16 25 36 49 64 81 100) iex(6)> Example.square(3) # `Example` `square` 9 iex(7)> Enum.map(1..10, &Example.square/1) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  28. 28. // ClojureClojure ElixirElixir user> (map (fn [x] (* x x)) (range 1 (inc 10))) (1 4 9 16 25 36 49 64 81 100) user> (map #(* % %) (range 1 (inc 10))) (1 4 9 16 25 36 49 64 81 100) iex(8)> Enum.map(1..10, fn(x) -> x * x end) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] iex(8)> Enum.map(1..10, &(&1 * &1)) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  29. 29. ­>>­>> (threading macro) vs(threading macro) vs |>|> (pipe operator)(pipe operator) ClojureClojure ElixirElixir cf. user> (->> (range 1 (inc 10)) (map #(* % %)) (filter odd?) (apply +)) 165 iex(9)> require Integer Integer iex(10)> 1..10 |> ...(10)> Enum.map(&(&1 * &1)) |> ...(10)> Enum.filter(&Integer.is_odd/1) |> ...(10)> Enum.sum 165
  30. 30. ClojureClojure ElixirElixir user> (defprotocol Shape ; `Shape` (area [x])) ; `area` Shape iex(1)> defprotocol Shape do # `Shape` ...(1)> def area(x) # `area` ...(1)> end {:module, Shape, ..., {:__protocol__, 1}}
  31. 31. // ClojureClojure user> (defrecord Triangle [x h] ; `Triangle` Shape ; (area [{:keys [x h]}] (/ (* x h) 2))) user.Triangle user> (area (map->Triangle {:x 3 :h 2})) 3 user> (defrecord Rectangle [x y] ; `Rectangle` Shape ; (area [{:keys [x y]}] (* x y))) user.Rectangle user> (area (map->Rectangle {:x 2 :y 3})) 6
  32. 32. ElixirElixir iex(2)> defmodule Triangle do # `Triangle` ...(2)> defstruct [:x, :h] ...(2)> end {:module, Triangle, ..., %Triangle{h: nil, x: nil}} iex(3)> defimpl Shape, for: Triangle do # ...(3)> def area(%Triangle{x: x, h: h}), do: x * h / 2 ...(3)> end {:module, Shape.Triangle, ..., {:__impl__, 1}} iex(4)> Shape.area(%Triangle{x: 3, h: 2}) 3.0 iex(5)> defmodule Rectangle do # `Rectangle` ...(5)> defstruct [:x, :y] ...(5)> end {:module, Rectangle, ..., %Rectangle{x: nil, y: nil}} iex(6)> defimpl Shape, for: Rectangle do # ...(6)> def area(%Rectangle{x: x, y: y}), do: x * y ...(6)> end {:module, Shape.Rectangle, ..., {:__impl__, 1}} iex(7)> Shape.area(%Rectangle{x: 2, y: 3}) 6
  33. 33. ClojureClojure ElixirElixir user> (defrecord Circle [r]) ; `Circle` user.Circle user> (area (map->Circle {:r 3})) Execution error (IllegalArgumentException) at user/eval5412$fn$G (REPL:47). No implementation of method: :area of protocol: #'user/Shape fou nd for class: user.Circle iex(8)> defmodule Circle do # `Circle` ...(8)> defstruct [:r] ...(8)> end {:module, Circle, ..., %Circle{r: nil}} iex(9)> Shape.area(%Circle{r: 3}) ** (Protocol.UndefinedError) protocol Shape not implemented for %Circle{r: 3} iex:2: Shape.impl_for!/1 iex:3: Shape.area/1
  34. 34. ClojureClojure ElixirElixir user> (extend-protocol Shape ; Circle (area [{:keys [r]}] (* Math/PI r r))) nil user> (area (map->Circle {:r 3})) 28.274333882308138 iex(10)> defimpl Shape, for: Circle do # ...(10)> def area(%Circle{r: r}), do: :math.pi() * r * r ...(10)> end {:module, Shape.Circle, ..., {:__impl__, 1}} iex(11)> Shape.area(%Circle{r: 3}) 28.274333882308138
  35. 35. ASTAST ClojureClojure user> '(when (= 1 1) (println "Truthy!")) (when (= 1 1) (println "Truthy!")) ;; user> (quote (when (= 1 1) (println "Truthy!"))) (when (= 1 1) (println "Truthy!"))
  36. 36. ElixirElixir iex(1)> quote do ...(1)> if 1 == 1 do ...(1)> IO.puts "Truthy!" ...(1)> end ...(1)> end {:if, [context: Elixir, import: Kernel], [ {:==, [context: Elixir, import: Kernel], [1, 1]}, [ do: {{:., [], [{:__aliases__, [alias: false], [:IO]}, :puts ]}, [], ["Truthy!"]} ] ]}
  37. 37. ClojureClojure user> (ns example) nil example> (defmacro my-when-not [test & body] `(if ~test nil (do ~@body))) #'example/my-when-not example> (in-ns 'user) #namespace[user] user>
  38. 38. ElixirElixir iex(2)> defmodule Example do ...(2)> defmacro my_unless(test, do: body) do ...(2)> quote do ...(2)> if unquote(test), do: nil, else: unquote(body) ...(2)> end ...(2)> end ...(2)> end {:module, Example, ..., {:my_unless, 2}}
  39. 39. ClojureClojure user> (example/my-when-not (= 1 2) (println "Falsy!") 42) Falsy! 42 user> (example/my-when-not (= 1 1) (println "Falsy!") 42) nil
  40. 40. ElixirElixir iex(3)> require Example Example iex(4)> Example.my_unless 1 == 2 do ...(4)> IO.puts "Falsy!" ...(4)> 42 ...(4)> end Falsy! 42 iex(5)> Example.my_unless 1 == 1 do ...(5)> IO.puts "Falsy!" ...(5)> 42 ...(5)> end nil
  41. 41. ClojureClojure user> (macroexpand-1 ; 1 '(example/my-when-not (= 1 2) (println "Falsy!") 42)) (if (= 1 2) nil (do (println "Falsy!") 42))
  42. 42. ElixirElixir iex(6)> quote do ...(6)> Example.my_unless 1 == 2 do ...(6)> IO.puts "Falsy!" ...(6)> 42 ...(6)> end ...(6)> end |> Macro.expand_once(__ENV__) |> # 1 ...(6)> Macro.to_string |> IO.puts # AST if(1 == 2) do nil else IO.puts("Falsy!") 42 end :ok
  43. 43. ClojureClojure
  44. 44. vs cf. (by Rich Hickey) REPL cf. REPL (REPL-driven development) Simple Made Easy
  45. 45. Elixirists Clojurians (?)Elixirists Clojurians (?)
  46. 46. Further ReadingFurther Reading
  47. 47. : : https://clojure.org https://japan- clojurians.github.io/clojure-site-ja/ https://elixir-lang.org https://elixir-lang.jp Getting Started Erlang/Elixir Syntax: A Crash Course
  48. 48. : : Clojure 2 Programming Clojure, Third Edition Elixir Programming Elixir ≥ 1.6 7 7 Seven More Languages in Seven Weeks
  49. 49. Seven Concurrency Models in Seven Weeks Scala/Akka (Chapter 5) Mastering Clojure Macros Metaprogramming Elixir
  50. 50. Elixir Erlang/OTP Elixir Elixir Elixir
  51. 51. : https://scrapbox.io/lagenorhynque/Elixir lagenorhynque/programming-elixir

×