{"id":11014,"date":"2024-07-21T14:32:44","date_gmt":"2024-07-21T14:32:44","guid":{"rendered":"https:\/\/putridparrot.com\/blog\/?p=11014"},"modified":"2024-07-21T14:32:44","modified_gmt":"2024-07-21T14:32:44","slug":"elixir-use-and-using","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/elixir-use-and-using\/","title":{"rendered":"Elixir, use and using"},"content":{"rendered":"<p>I didn&#8217;t include much information in my post <a href=\"https:\/\/putridparrot.com\/blog\/\">More modules in Elixer<\/a> around the <em>use<\/em> macro and that&#8217;s because it really requires a post on it&#8217;s own. So here we go&#8230;<\/p>\n<p>If you&#8217;ve uses Phoenix (partially covered in <a href=\"https:\/\/putridparrot.com\/blog\/elixir-and-phoenix\/\" rel=\"noopener\" target=\"_blank\">Elixir and Phoenix<\/a>) you&#8217;ll have probably noticed that when we created the controller we gained access to functions such as <em>json<\/em> and when we setup the router we had a long list of <em>except:<\/em> atoms. This is because using <em>use<\/em> bought functions into the modules from Phoenix automatically, i.e. new, edit, create etc. functions.<\/p>\n<p>The <em>use<\/em> macro is quite powerful, it essentially calls the __using__ macro within another module. The __using__ macro allows us to inject code from the other module. <\/p>\n<p>Let&#8217;s see this in action&#8230;<\/p>\n<p>We&#8217;ll start by creating a module which will include functionality that can be injected into another module<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndefmodule MyUse do\r\n  defmacro __using__(_opts) do\r\n    quote do\r\n      def my_injected_fn() do\r\n        &quot;Hello World&quot;\r\n      end\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<p>In the above example, we create the macro with the <em>my_injected_fn<\/em>. The neat bit is the <em>__using__<\/em> which injects this code into a module which uses the <em>MyUse<\/em> module, for example<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndefmodule MyModule do\r\n  use MyUse\r\n\r\n  def test_use() do\r\n    my_injected_fn()\r\n  end\r\nend\r\n<\/pre>\n<p>This will inject all macros, but in the Phoenix example we want to inject only certain pieces from a module. <\/p>\n<p>Before we move on let&#8217;s quickly address a couple of things in the code above. The <em>quote<\/em> macro tranforms the block of code into an AST (Abstract Syntax Tree), we can see an example of this by type the following into iex <em>quote do: MyModule.testuse()<\/em> and it will display something like <em>{{:., [], [{:__aliases__, [alias: false], [:MyModule]}, :testuse]}, [], []}<\/em>. It&#8217;s probably quite obvious that <em>defmacro<\/em> defines a macro and the <em>__using__<\/em> calback macro is what allows us to extend other modules (as already mentioned).<\/p>\n<p>Let&#8217;s change the <em>MyUse<\/em> module to allow us to inject specific functionality.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndefmodule MyUse do\r\n  defmacro __using__(which) when is_atom(which) do\r\n    apply(__MODULE__, which, &#x5B;])\r\n  end\r\n\r\n  def injector do\r\n    quote do\r\n      def my_injected_fn() do\r\n        &quot;Hello World&quot;\r\n      end\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<p>We&#8217;re now using the macro __using__ to select which bits of functionality we want to inject into another module. Admittedly in this example we just have a single piece of code to be injected, but bare with me.<\/p>\n<p>So now to use this in our other modules we write the following<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndefmodule MyModule do\r\n  use MyUse, :injector\r\n\r\n  def test_use() do\r\n    my_injected_fn()\r\n  end\r\nend\r\n<\/pre>\n<p>This will inject the <em>injector<\/em> defined code.<\/p>\n<p>Let&#8217;s be honest this is not that useful with one function, so let&#8217;s extend the <em>MyUse<\/em> with a couple of functions (in my case, just to demonstrate things I&#8217;ve given them the same name  but in most modules you&#8217;ll probably not be doing this<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndefmodule MyUse do\r\n  defmacro __using__(which) when is_atom(which) do\r\n    apply(__MODULE__, which, &#x5B;])\r\n  end\r\n\r\n  def injector1 do\r\n    quote do\r\n      def my_injected_fn() do\r\n        &quot;Hello World 1&quot;\r\n      end\r\n    end\r\n  end\r\n\r\n  def injector2 do\r\n    quote do\r\n      def my_injected_fn() do\r\n        &quot;Hello World 2&quot;\r\n      end\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<p>What we&#8217;re going to do, is in the calling module, we can select injector1 OR injector2 an without changing the calling function name (as it&#8217;s unchanged in the <em>MyUse<\/em> module)<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndefmodule MyModule do\r\n  use MyUse, :injector1\r\n\r\n  def test_use() do\r\n    my_injected_fn()\r\n  end\r\nend\r\n<\/pre>\n<p>This will display &#8220;Hello World1&#8221; when evaluated. Switching the :injector2 will display &#8220;Hello World 2.<\/p>\n<p>As mentioned it&#8217;s unlikely you&#8217;ve normally do this, it&#8217;s much more likely you might include different functions, maybe along these lines<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndefmodule MyUse do\r\n  defmacro __using__(which) when is_atom(which) do\r\n    apply(__MODULE__, which, &#x5B;])\r\n  end\r\n\r\n  def injector1 do\r\n    quote do\r\n      def hello1() do\r\n        &quot;Hello World 1&quot;\r\n      end\r\n    end\r\n  end\r\n\r\n  def injector2 do\r\n    quote do\r\n      def hello2() do\r\n        &quot;Hello World 2&quot;\r\n      end\r\n    end\r\n  end\r\nend\r\n<\/pre>\n<p>Now we can inject these via <em>use<\/em>, like this<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndefmodule MyModule do\r\n  use MyUse, :injector1\r\n  use MyUse, :injector2\r\n\r\n  def test_use() do\r\n    IO.puts hello1()\r\n    IO.puts hello2()\r\n  end\r\nend\r\n<\/pre>\n<p><em>Note: I&#8217;m still quite new to Elixir, the usage of two use clauses seems a little odd, there may be a better way to define such things.<\/em><\/p>\n<p>I mentioned you could use <em>import<\/em> in much the same way, except <em>use<\/em> allows us to inject aliases, imports other use modules etc. <\/p>\n<p><strong>References<\/strong> <\/p>\n<p><a href=\"https:\/\/brooklinmyers.medium.com\/using-use-usefully-in-elixir-and-phoenix-b59a5ea08ad2\" rel=\"noopener\" target=\"_blank\">The \u2018use\u2019 Macro in Elixir.<\/a><br \/>\n<a href=\"https:\/\/medium.com\/@Mike_Andr\/understanding-elixirs-macros-by-phoenix-example-e99827a60987\" rel=\"noopener\" target=\"_blank\">Understanding Elixir\u2019s Macros by Phoenix example<\/a><br \/>\n<a href=\"https:\/\/blog.appsignal.com\/2021\/10\/26\/how-to-use-macros-in-elixir.html\" rel=\"noopener\" target=\"_blank\">How to Use Macros in Elixir<\/a><br \/>\n<a href=\"https:\/\/github.com\/phoenixframework\/phoenix\/blob\/293791fcd8570efc5375638267648459d9b125b3\/lib\/phoenix\/controller.ex#L234\" rel=\"noopener\" target=\"_blank\">Phoenix repo on GitHub<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I didn&#8217;t include much information in my post More modules in Elixer around the use macro and that&#8217;s because it really requires a post on it&#8217;s own. So here we go&#8230; If you&#8217;ve uses Phoenix (partially covered in Elixir and Phoenix) you&#8217;ll have probably noticed that when we created the controller we gained access to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[730],"tags":[],"class_list":["post-11014","post","type-post","status-publish","format-standard","hentry","category-elixir"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11014","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=11014"}],"version-history":[{"count":3,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11014\/revisions"}],"predecessor-version":[{"id":11017,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/11014\/revisions\/11017"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=11014"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=11014"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=11014"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}