Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Intro to Elixir macro
Search
tony612
May 22, 2017
Programming
2
150
Intro to Elixir macro
keynote at Elixir Meetup 2017.5.21
https://www.meetup.com/Elixir-Shanghai/events/238614338/
tony612
May 22, 2017
Tweet
Share
More Decks by tony612
See All by tony612
My simple reverse proxy in Elixir
tony612
1
710
Protobuf in Elixir
tony612
2
710
The way to grpc-elixir
tony612
2
1.5k
Why I love Elixir
tony612
7
1.3k
GitHub is the new Sexy
tony612
0
110
Other Decks in Programming
See All in Programming
AIコーディング道場勉強会#2 君(エンジニア)たちはどう生きるか
misakiotb
1
250
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
260
PostgreSQLのRow Level SecurityをPHPのORMで扱う Eloquent vs Doctrine #phpcon #track2
77web
2
360
Create a website using Spatial Web
akkeylab
0
300
Code as Context 〜 1にコードで 2にリンタ 34がなくて 5にルール? 〜
yodakeisuke
0
110
イベントストーミング図からコードへの変換手順 / Procedure for Converting Event Storming Diagrams to Code
nrslib
1
430
Hypervel - A Coroutine Framework for Laravel Artisans
albertcht
1
100
「ElixirでIoT!!」のこれまでとこれから
takasehideki
0
370
Elixir で IoT 開発、 Nerves なら簡単にできる!?
pojiro
1
150
Haskell でアルゴリズムを抽象化する / 関数型言語で競技プログラミング
naoya
17
4.9k
FormFlow - Build Stunning Multistep Forms
yceruto
1
190
XSLTで作るBrainfuck処理系
makki_d
0
210
Featured
See All Featured
A designer walks into a library…
pauljervisheath
207
24k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Music & Morning Musume
bryan
46
6.6k
Docker and Python
trallard
44
3.4k
YesSQL, Process and Tooling at Scale
rocio
173
14k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
48
2.8k
KATA
mclloyd
29
14k
How STYLIGHT went responsive
nonsquared
100
5.6k
Reflections from 52 weeks, 52 projects
jeffersonlam
351
20k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
17
940
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
Navigating Team Friction
lara
187
15k
Transcript
*OUSPUP&MJYJSNBDSP !UPOZ
0WFSWJFX ˙ 8IBU’TNBDSP ˙ 8IZNBDSP ˙ )PXJTNBDSPJNQMFNFOUFEJO&MJYJS ˙
)PXUPVTF ˙ 8IFOUPVTF
8IBU’TNBDSP
"NBDSPJTBOPSEJOBSZQJFDFPG-JTQDPEFUIBU PQFSBUFTPOBOPUIFSQJFDFPGQVUBUJWF-JTQ DPEF USBOTMBUJOHJUJOUP BWFSTJPODMPTFSUP FYFDVUBCMF-JTQ .BDSPJO-JTQ IUUQDMDPPLCPPLTPVSDFGPSHFOFUNBDSPTIUNM
"NBDSPJTBOPSEJOBSZQJFDFPG&MJYJSDPEF UIBUPQFSBUFTPOBOPUIFSQJFDFPGRVPUFE&MJYJS DPEF USBOTMBUJOHJUJOUPRVPUFE&MJYJS .BDSPJO&MJYJS
EFGNBDSP defmodule MyLogic do defmacro unless(expr, opts) do quote do
if !unquote(expr), unquote(opts) end end end require MyLogic MyLogic.unless false do IO.puts "It works" end
&MJYJSDPEFUP"45 sum(1, 2, 3) => {:sum, [], [1, 2, 3]}
x => {:x, [], Elixir} %{1 => 2} => {:%{}, [], [{1, 2}]} Foo.run(1, 2) => {{:., [], [{:__aliases__, [alias: false], [:Foo]}, :run]}, [], [1, 2]}
RVPUF quote do defmodule Foo do def foo do 1
end end end {:defmodule, [context: Elixir, import: Kernel], [{:__aliases__, [alias: false], [:Foo]}, [do: {:def, [context: Elixir, import: Kernel], [{:foo, [context: Elixir], Elixir}, [do: 1]]}]]}
.FUBQSPHSBNNJOH XJLJQFEJB ˙ $PNQVUFSQSPHSBNTIBWFUIFBCJMJUZUPUSFBU QSPHSBNTBTUIFJSEBUB ˙ "QSPHSBNDBOCFEFTJHOFEUPSFBE HFOFSBUF BOBMZTFPSUSBOTGPSNPUIFSQSPHSBNT
8IZNBDSP
.FUBQSPHSBNNJOH XJLJQFEJB ˙ .JOJNJ[FUIFBNPVOUPGDPEFUPFYQSFTTB TPMVUJPO BOEUIVTSFEVDJOHUIFEFWFMPQNFOU UJNF ˙ .PWFDPNQVUBUJPOTGSPNSVOUJNFUPDPNQJMF UJNF
˙ (FOFSBUFDPEFVTJOHDPNQJMFUJNF DPNQVUBUJPOT
MFTTDPEF NPSFFFDUJWF defmodule MyRouter do use Plug.Router plug :match #
middleware plug :dispatch # middleware get "/hello" do # logic for a route send_resp(conn, 200, "world") end end
DPNQVUFBUDPNQJMFUJNF # config.yml web_port: 8080 Config.get(:web_port) => 8080 OPUBHPPEFYBNQMF
(FOFSBUFDPEF iex> String.upcase("Elixir Shànghăi") "ELIXIR SHÀNGHĂI" IUUQTHJUIVCDPNFMJYJSMBOHFMJYJSCMPCNBTUFS MJCFMJYJSVOJDPEFVOJDPEFFY-
)PXJTNBDSPJNQMFNFOUFE JO&MJYJS
$PNQJMJOHPG&MJYJS
"OFYBNQMF defmodule Foo do defmacro add1(x) do quote do x
+ 1 end end end Foo.add1(2)
$PEFUP"45 quote do: Foo.add1(2) => { {:., [], [{:__aliases__, [alias:
false], [:Foo]}, :add1]}, [], [2]}
.BDSPFYQBOTJPO require Foo Macro.expand(quote(do: Foo.add1(2)), __ENV__) => {:+, [context: Foo,
import: Kernel], [{:x, [], Foo}, 1]} quote do: Foo.add1(2) => { {:., [], [{:__aliases__, [alias: false], [:Foo]}, :add1]}, [], [2]}
Macro.to_string({:+, [context: Foo, import: Kernel], [{:x, [], Foo}, 1]}) =>
"x + 1" "45UPDPEF
4PPVSDPEFDIBOHFTBGUFSFYQBOTJPO Foo.add1(2) => x + 1
None
)PXUPVTF
5IJOLPGUIFOBMDPEF BGUFSFYQBOTJPO %FOFNBDSPTUPHFOFSBUFUIFDPEF 8SJUFBOESVOVOJUUFTUT PSSVOJOJFY 3FQFBU
&YBNQMFBTJNQMF'4.MJC VTJOH%4-
6TBHFPGUIFMJC defmodule Door do trans :push, "closed", "opened" trans :pull,
"opened", "closed" end state0 = "closed" state1 = Door.push(state0) # "opened" state2 = Door.pull(state1) # "closed"
5IFFYQBOEFEDPEF defmodule Door do def push("closed") do "opened" end def
pull("opened") do "closed" end end
4PXFOFFE 5IFBCJMJUZUPJOKFDUNBDSPUSBOT 6TFUSBOTUPHFOFSBUFGVODUJPOT
IUUQTIFYEPDTQNFMJYJS,FSOFMIUNMVTF VTFUPJOKFDUBNPEVMF
defmodule Door do use FSM trans :push, "closed", "opened" trans
:pull, "opened", "closed" end # expanded => defmodule Door do import FSM.DSL, only: [trans: 3] # ... end
defmodule FSM do defmacro __using__(opts) do quote do import FSM.DSL,
only: [trans: 3] end end end defmodule FSM.DSL do defmacro trans(name, from, to) do # ... end end
*NQMFNFOUUSBOTJO'4.%4- defmacro trans(name, from, to) do quote do def name(from)
do to end end end 5IJTJTXSPOH
(FOFSBUFEDPEFXJMMCF defmodule Door do def name(from) do to end def
name(from) do to end end 5IJTJTXSPOH
VORVPUFUPDPNQVUFFYQSFTTJPO CFGPSFNBDSPFYQBOTJPO defmacro trans(name, from, to) do quote do def
unquote(name)(unquote(from)) do unquote(to) end end end
5IFDPEFDBOCFSVOJOJFY IUUQTHJTUHJUIVCDPN UPOZDDGFCCDBCFB MFGTNFYT
"OBEWBODFEGFBUVSF -JTUBMMFWFOUTPGUIF'4.
defmodule Door do use FSM trans :push, "closed", "opened" trans
:pull, "opened", "closed" end Door.__events__ # => [:push, :pull]
˙ 8FDBOVTFNPEVMFBUUSJCVUFTUPTBWFBMMFWFOUT ˙ #VUNPEVMFBUUSJCVUFTDBO’UCFBDDFTTFEJO SVOUJNF ˙ 4PXFOFFEBGVODUJPOUPTBWFUIFBUUSJCVUFTJOB NPEVMFKVTUCFGPSFDPNQJMJOH DPNQJMFEUP CZUFTDPEF
IUUQTIFYEPDTQNFMJYJS.PEVMFIUNMNPEVMFDPNQJMFDBMMCBDLT
defmodule Door do @before_compile FSM.DSL # ... # expanded def
__events__ do # ... end end
defmodule FSM do defmacro __using__(opts) do quote do @before_compile FSM.DSL
end end end defmodule FSM.DSL do defmacro __before_compile__(env) do quote do def __events__ do # ... end end end end
6TFNPEVMFBUUSJCVUFTUPMJTUFWFOUT defmodule FSM do defmacro __using__(opts) do quote do Module.register_attribute(__MODULE__,
:events, accumulate: true) end end end defmacro trans(name, from, to) do quote do @events unquote(name) # ... end end
BOEEFOF@@FWFOUT@@ CFGPSFDPNQJMJOH defmodule FSM.DSL do defmacro __before_compile__(env) do fields =
Module.get_attribute(env.module, :events) quote do def __events__ do unquote(Enum.reverse(fields)) end end end end
5IFDPEFDBOCFSVOJOJFY IUUQTHJTUHJUIVCDPN UPOZDDGFCCDBCFBMFGTN FYT
8IFOUPVTFNBDSP
˙ 8IFOZPVOFFEUIFCFOFUTPGNBDSPT ˙ 8IFOGVODUJPOTDBO’UTPMWFZPVSQSPCMFNT ˙ 8IFOZPVXSJUFBMJCBOEXBOUUPQSPWJEF “GSJFOEMZ”"1* ˙ .BDSPTTIPVMEPOMZCFVTFEBTBMBTUSFTPSU
IUUQFMJYJSMBOHPSHHFUUJOHTUBSUFENFUBNBDSPTIUNMXSJUFNBDSPTSFTQPOTJCMZ 8SJUFNBDSPTSFTQPOTJCMZBOELFFQZPVS NBDSPEFOJUJPOTTIPSU
IUUQFMJYJSMBOHPSHHFUUJOHTUBSUFENFUBNBDSPTIUNM &YQMJDJUJTCFUUFSUIBOJNQMJDJU$MFBSDPEF JTCFUUFSUIBODPODJTFDPEF
2"