Advertisement
Guest User

Untitled

a guest
Mar 3rd, 2017
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.97 KB | None | 0 0
  1. defmodule Protocolz do
  2. defmacro defimplz(protocolo, [for: modulo_do_struct], [do: block]) do
  3. quote do
  4. defmodule (Module.concat([unquote(protocolo), unquote(modulo_do_struct)])) do
  5. unquote(block)
  6. end
  7. end
  8. end
  9.  
  10. defmacro defprotocolz(protocolo, [do: block]) do
  11. corpo_do_protocolo = Macro.postwalk block, [], fn
  12. ast = {:def, _, [{nome_da_funcao, _, argumentos}]}, acc ->
  13. quoted_def =
  14. quote do
  15. def unquote(nome_da_funcao)(unquote_splicing(argumentos)) do
  16. Protocolz.__dispatch__(unquote(protocolo),
  17. unquote(nome_da_funcao),
  18. unquote_splicing(argumentos)
  19. )
  20. end
  21. end
  22. {ast, [quoted_def | acc]}
  23.  
  24. ast, acc ->
  25. {ast, acc}
  26. end
  27.  
  28. quote do
  29. defmodule unquote(protocolo) do
  30. unquote(corpo_do_protocolo)
  31. end
  32. end
  33. end
  34.  
  35. def __dispatch__(protocolo, nome_da_funcao, dado) do
  36. modulo_do_struct = dado.__struct__
  37. modulo_da_implementacao =
  38. Module.concat(protocolo, modulo_do_struct)
  39.  
  40. :erlang.apply(modulo_da_implementacao, nome_da_funcao, [dado])
  41. end
  42. end
  43.  
  44. defmodule App do
  45. import Protocolz, only: [defimplz: 3, defprotocolz: 2]
  46.  
  47. defmodule SecretMessage, do: (defstruct [:password, :username, :wathever])
  48. defmodule PublicMessage, do: (defstruct [:username, :wathevis])
  49.  
  50. defprotocolz MyLogger do
  51. def log(message)
  52. end
  53.  
  54. defimplz MyLogger, for: SecretMessage do
  55. def log(message) do
  56. "password=SECRET username=#{message.username} wathever=#{message.wathever}"
  57. end
  58. end
  59.  
  60. defimplz MyLogger, for: PublicMessage do
  61. def log(message) do
  62. "username=#{message.username} wathever=#{message.wathevis}"
  63. end
  64. end
  65.  
  66. def main do
  67. public = %PublicMessage{username: "mimi"}
  68. IO.puts MyLogger.log(public)
  69.  
  70. secret = %SecretMessage{password: "eita", username: "mimi"}
  71. IO.puts MyLogger.log(secret)
  72. end
  73. end
  74.  
  75. App.main
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement