@@ -484,8 +484,8 @@ defmodule Kernel.SpecialForms do
484484 """
485485 defmacro __DIR__
486486
487- @ doc """
488- Allows you to get the representation of any expression.
487+ @doc % S """
488+ Gets the representation of any expression.
489489
490490 ## Examples
491491
@@ -522,7 +522,7 @@ defmodule Kernel.SpecialForms do
522522 * `:bind_quoted` - Passes a binding to the macro. Whenever a binding is given,
523523 `unquote` is automatically disabled;
524524
525- ## Macro literals
525+ ## Quote literals
526526
527527 Besides the tuple described above, Elixir has a few literals that
528528 when quoted return themselves. They are:
@@ -531,43 +531,111 @@ defmodule Kernel.SpecialForms do
531531 1 #=> Integers
532532 2.0 #=> Floats
533533 [1, 2] #=> Lists
534- "binaries " #=> Binaries
534+ "strings " #=> Strings
535535 {key, value} #=> Tuple with two elements
536536
537- ## Hygiene and context
537+ ## Quote and macros
538+
539+ `quote` is commonly used with macros for code generation. As an exercise,
540+ let's define a macro that multiplies a number by itself (squared). Note
541+ there is no reason to define such as a macro (and it would actually be
542+ seen as a bad practice), but it is simple enough that allows us to focus
543+ on the important aspects of quotes and macros:
544+
545+ defmodule Math do
546+ defmacro squared(x) do
547+ quote do
548+ unquote(x) * unquote(x)
549+ end
550+ end
551+ end
552+
553+ We can invoke it as:
554+
555+ import Math
556+ IO.puts "Got #{ squared ( 5 ) } "
557+
558+ At first, there is nothing in this example that actually reveals it is a
559+ macro. But what is happening is that, at compilation time, `squared(5)`
560+ becomes `5 * 5`. We can see this behaviour in practice though
561+ because our macro actually has a bug:
562+
563+ import Math
564+ my_number = fn ->
565+ IO.puts "Returning 5"
566+ 5
567+ end
568+ IO.puts "Got #{ squared ( my_number . ( ) ) } "
569+
570+ The example above will print:
571+
572+ Returning 5
573+ Returning 5
574+ 25
575+
576+ Notice how "Returning 5" was printed twice, instead of just once. This is
577+ because a macro receives an expression and not a value (which is what we
578+ would expect in a regular function). This means that:
538579
539- Elixir macros are hygienic by means of deferred resolution.
540- This means variables, aliases and imports defined inside the
541- quoted refer to the context that defined the macro and not
542- the context where the macro is expanded.
580+ squared(my_number.())
543581
544- For this mechanism to work, every quoted code is attached
545- to a context. Consider the following example:
582+ Actually expands to:
546583
547- defmodule ContextSample do
548- def hello do
549- quote do: world
584+ my_number.() * my_number.()
585+
586+ Which invokes the function twice, explaining why we get the printed value
587+ twice! In the majority of the cases, this is actually unexpected behaviour,
588+ and that's why one of the first things you need to keep in mind when it
589+ comes to macros is to **not unquote the same value more than once**.
590+
591+ Let's fix our macro:
592+
593+ defmodule Math do
594+ defmacro squared(x) do
595+ quote do
596+ x = unquote(x)
597+ x * x
598+ end
599+ end
600+ end
601+
602+ Now invoking `square(my_number.())` as before will print the value just
603+ once.
604+
605+ In fact, this pattern is so common that most of the times you will want
606+ to use the `bind_quoted` option with `quote`:
607+
608+ defmodule Math do
609+ defmacro squared(x) do
610+ quote bind_quoted: [x: x] do
611+ x * x
612+ end
550613 end
551614 end
552615
553- ContextSample.hello
554- #=> {:world,[],ContextSample}
616+ `:bind_quoted` will translate to the same example as above. `:bind_quoted`
617+ can be used in many cases and is seen as good practice, not only because
618+ it helps us from running into common mistakes but also because it allows
619+ us to leverage other tools exposed by macros, as unquote fragments discussed
620+ in some sections below.
621+
622+ Before we finish this brief introduction, you will notice that, even though
623+ we defined a variable `x` inside our quote:
624+
625+ quote do
626+ x = unquote(x)
627+ x * x
628+ end
555629
556- Notice how the third element of the returned tuple is the
557- module name. This means that the variable is associated to the
558- `ContextSample` module and only code generated by this module
559- will be able to access that particular `world` variable. Not
560- only variables hygiene, but also imports and aliases hygiene
561- are delimited by context.
630+ When we call:
562631
563- While this means macros from the same module could have
564- conflicting variables, it also allows different quotes from
565- the same module to access them.
632+ import Math
633+ squared(5)
634+ x #=> ** (RuntimeError) undefined function or variable: x
566635
567- The context can be disabled or changed by explicitly setting
568- the `context` option. All hygiene mechanisms are based on such
569- context and we are going to explore each of them in the following
570- subsections.
636+ We can see that `x` did not leak to the user context. This happens
637+ because Elixir macros are hygienic, a topic we will discuss at length
638+ in the next sections as well.
571639
572640 ### Hygiene in variables
573641
@@ -622,7 +690,7 @@ defmodule Kernel.SpecialForms do
622690
623691 Hygiene.write
624692 Hygiene.read
625- #=> no variable a
693+ #=> ** (RuntimeError) undefined function or variable: a
626694
627695 For such, you can explicitly pass the current module scope as
628696 argument:
@@ -839,8 +907,8 @@ defmodule Kernel.SpecialForms do
839907 One solution for this problem is to disable unquoting in the
840908 macro, however, doing that would make it impossible to inject
841909 `kv` representation into the tree. That's when the `:bind_quoted`
842- option comes to the rescue. By using `:bind_quoted`, we can
843- automatically disable unquoting while still injecting the
910+ option comes to the rescue (again!) . By using `:bind_quoted`, we
911+ can automatically disable unquoting while still injecting the
844912 desired variables into the tree:
845913
846914 defmacro defkv(kv) do
0 commit comments