Intro to elixir metaprogramming

37
Intro to Elixir metaprogramming First Kyiv Elixir meetup, June 23, 2016

Transcript of Intro to elixir metaprogramming

Intro to Elixir metaprogramming

First Kyiv Elixir meetup, June 23, 2016

Hello!I am Anton Mishchuk from Lviv ▧ Ruby Dev at Matic (and we are hiring)▧ Fan of Elixir programming language▧ ESpec creator & maintainer▧ GitHub: antonmi

2

Elixir is Erlang with pretty syntax and metaprogramming!

What is Elixir?

3

▧ Elixir AST▧ Quote and unquote▧ Macroses▧ DSL▧ Introspection

What will be about

4

Why metaprogramming

▧ Extending language▧ Boilerplate removing▧ Creating DSL

5

Initial code parsing

Elixir code

Initial AST

Expansion

Expanded AST

Byte-code generation

Byte-code

Compilation process

Magic is here!

9

Compile-time metaprogramming

▧ Code will not be redefined▧ Static code analysis still works▧ No performance penalty

10

Elixir AST. Quoting

‘quote’ macro gets the representation of any expression.

11

Elixir AST. Quoting

12

▧ The first element is an atom identifying the operation or another tuple in the same representation

▧ The second element is a keyword list containing metadata, like numbers and contexts

▧ The third element is either a list of arguments for the function call or an atom. When this element is an atom, it means the tuple represents a variable

Elixir AST - 3 element tuple

13

Elixir AST string representation

‘Macro.to_string’ converts the given expression to a binary

14

Elixir AST evaluation

‘Code.eval_string’ and ‘Code.eval_quoted’

15

Elixir AST. Unquoting

Unquoting is a mechanism to inject code chunks into quoted expressions.i.e. inject one AST fragment into another

Let’s try an example:

16

Elixir AST. Unquoting

Trying to evaluate ‘final_expr’

I want to build AST which adds 1 + 2

17

Elixir AST. Unquoting‘unquote’ helps to inject AST fragment

18

Magic functions - Macros

▧ Macro (which stands for "macroinstruction") is a programmable pattern which translates a certain sequence of input into a preset sequence of output

▧ Macros receive the input AST and must produce the output AST

▧ The compiler will then simply replace the macro call with the AST returned from that macro

▧ Works only at compile time

19

▧ ‘defmodule’, ‘defmacro’, ‘def’, defstruct ▧ ‘require’, ‘import’, ‘use’▧ ‘If’, ‘unless’, ‘cond’▧ etc, etc

Macros are everywhere

87% of Elixir code written on Elixir

20

Macros. ExampleCalculator

21

Macros. Example

The result is expect. Nothing special.Because we see completely compiled

code in the iex console

22

Macros. ExampleRemember, macros receive quoted

expression and return them

Let’s do what compiler did step by step

23

Macros. Dynamic function definition example

24

Macros. ‘require’ and ‘import’We should tell the compiler which module should be compiled before we can use it.

25

‘use’ macroThe simplest way to bring external functionality into the current lexical scope

26

‘Use’ for DSL‘Use Ecto.Migration’

‘Ecto.Migration.__using__’

27

‘Use’ for DSL‘use GenServer’

28

‘Use’ for DSL‘GenServer.__using__’

29

‘Use’ for DSL‘use ESpec’

30

‘Use’ for DSL‘ESpec.__using__’

31

OMG! How to handle all the stuff?

▧ What function/macro I can use in current scope?

▧ Where does this function/macro come from?

32

Elixir introspection

▧ __ENV__ : Returns a Macro.ENV struct containing current environment information

▧ __MODULE__ : Returns the current module name as an atom

▧ __DIR__ : Returns the current directory▧ __CALLER__ : Returns the caller’s

environment information as a Macro.ENV struct

33

Elixir introspection‘__ENV__’ in iex

34

And don’t forget about help‘h IEx.Helpers.b’

35

What is next?

36

With great power comes great responsibility!

Thank you!

37