Skip to content

Commit de1233d

Browse files
committed
testing details for README
1 parent 8de5dc3 commit de1233d

File tree

1 file changed

+89
-5
lines changed

1 file changed

+89
-5
lines changed

README.md

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
# Metaprogamming Elixir by Chris McCord
1+
# Metaprogamming Elixir
2+
3+
## by Chris McCord (author of the Phoenix framework)
24

35
_Write less code, get more done (and have fun!)_ :purple_heart:
46

5-
## Abstract
7+
### Abstract
68

79
Reading this book to learn about how macros work and following some of the relevant
810
examples. This README will serve as my notes, therefore you shouldn't take them at face
911
value as the notes will make sense for me as I cherry pick a sentence or an analogy.
1012
Moreover, don't expect direct quotes, changing the sentences vocbulary helps me personally.
1113

12-
## Chapter 1 - The language of macros
14+
<details>
15+
16+
<summary>
17+
18+
### Chapter 1 - The language of macros
19+
20+
</summary>
1321

1422
- Macros are code that write code.
1523
- Elixir itself is made with macros, as a result you can extend the language itself
@@ -57,7 +65,83 @@ iex> quote do: div(10, 2)
5765
#### Trying It All Together
5866

5967
"Let's write a macro that can print the spoken form of an Elixir mathematical expression, such as 5 + 2, when calculating a result.
60-
In most languages, we would have to parse a string expression into something digestible by our program. With Elixr, we can access
68+
In most languages, we would have to parse a string expression into something digestible by our program. With Elixir, we can access
6169
the representation of expressions directly with macros."
6270

63-
[First macro](math.exs)
71+
[First macro - `math.exs`](math.exs)
72+
73+
<!-- <details>
74+
<summary> [First macro - `math.exs`](math.exs) </summary>
75+
```elixir
76+
defmodule Math do
77+
@moduledoc false
78+
79+
defmacro say({:+, _, [lhs, rhs]}) do
80+
quote do
81+
lhs = unquote(lhs)
82+
rhs = unquote(rhs)
83+
result = lhs + rhs
84+
IO.puts("#{lhs} plus #{rhs} is #{result}")
85+
result
86+
end
87+
end
88+
89+
defmacro say({:*, _, [lhs, rhs]}) do
90+
quote do
91+
lhs = unquote(lhs)
92+
rhs = unquote(rhs)
93+
result = lhs * rhs
94+
IO.puts("#{lhs} times #{rhs} is #{result}")
95+
result
96+
end
97+
end
98+
end
99+
```
100+
</details> -->
101+
102+
Note when you use this in iex you need to first `c "math.exs"` then `require Math` but i've included it in [.iex.exs](.iex.exs) to save time.
103+
Automagically adding these when you open iex with `iex math.exs`.
104+
105+
In this example. We take what we know from the AST representations so far from the `quote` we used. We then create `defmacro`-s. We can still
106+
have many function clauses with macros. With that, we create two macros called `say` and we pattern match on the AST with the defining feature
107+
being the operator at the start of the AST, `{:+, ...}`, and use a new keyword called `unquote`. From the docs:
108+
109+
```elixir
110+
iex(1)> h unquote
111+
112+
defmacro unquote(expr)
113+
114+
Unquotes the given expression from inside a macro.
115+
116+
## Examples
117+
118+
Imagine the situation you have a variable value and you want to inject it
119+
inside some quote. The first attempt would be:
120+
121+
value = 13
122+
quote do
123+
sum(1, value, 3)
124+
end
125+
126+
Which would then return:
127+
128+
{:sum, [], [1, {:value, [], quoted}, 3]}
129+
130+
Which is not the expected result. For this, we use unquote:
131+
132+
iex> value = 13
133+
iex> quote do
134+
...> sum(1, unquote(value), 3)
135+
...> end
136+
{:sum, [], [1, 13, 3]}
137+
```
138+
139+
I assume from this then when you pass variables to a macro they need to be `unqoute`-d, incontrast to passing a value directly.
140+
Which I'm not following as Elixir is pass-by-value so wouldn't the value just be known?
141+
142+
Yes that's correct because we are dealing with ASTs not the data it represents; therefore the pass-by-value argument doesn't hold.
143+
Much like interpolation from Ecto and the difference between `"Hello world"` and `"Hello #{world}`.
144+
145+
Back to the `math.exs`example.
146+
147+
</details>

0 commit comments

Comments
 (0)