Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- defmodule Protocolz do
- defmacro defimplz(protocolo, [for: modulo_do_struct], [do: block]) do
- quote do
- defmodule (Module.concat([unquote(protocolo), unquote(modulo_do_struct)])) do
- unquote(block)
- end
- end
- end
- defmacro defprotocolz(protocolo, [do: block]) do
- corpo_do_protocolo = Macro.postwalk block, [], fn
- ast = {:def, _, [{nome_da_funcao, _, argumentos}]}, acc ->
- quoted_def =
- quote do
- def unquote(nome_da_funcao)(unquote_splicing(argumentos)) do
- Protocolz.__dispatch__(unquote(protocolo),
- unquote(nome_da_funcao),
- unquote_splicing(argumentos)
- )
- end
- end
- {ast, [quoted_def | acc]}
- ast, acc ->
- {ast, acc}
- end
- quote do
- defmodule unquote(protocolo) do
- unquote(corpo_do_protocolo)
- end
- end
- end
- def __dispatch__(protocolo, nome_da_funcao, dado) do
- modulo_do_struct = dado.__struct__
- modulo_da_implementacao =
- Module.concat(protocolo, modulo_do_struct)
- :erlang.apply(modulo_da_implementacao, nome_da_funcao, [dado])
- end
- end
- defmodule App do
- import Protocolz, only: [defimplz: 3, defprotocolz: 2]
- defmodule SecretMessage, do: (defstruct [:password, :username, :wathever])
- defmodule PublicMessage, do: (defstruct [:username, :wathevis])
- defprotocolz MyLogger do
- def log(message)
- end
- defimplz MyLogger, for: SecretMessage do
- def log(message) do
- "password=SECRET username=#{message.username} wathever=#{message.wathever}"
- end
- end
- defimplz MyLogger, for: PublicMessage do
- def log(message) do
- "username=#{message.username} wathever=#{message.wathevis}"
- end
- end
- def main do
- public = %PublicMessage{username: "mimi"}
- IO.puts MyLogger.log(public)
- secret = %SecretMessage{password: "eita", username: "mimi"}
- IO.puts MyLogger.log(secret)
- end
- end
- App.main
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement