<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Contact Stack</title>
    <description>The latest articles on DEV Community by Contact Stack (@contact-stack).</description>
    <link>https://dev.to/contact-stack</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F2098%2F007ece07-d6a4-48cf-bca5-0ddaf78b339c.png</url>
      <title>DEV Community: Contact Stack</title>
      <link>https://dev.to/contact-stack</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/contact-stack"/>
    <language>en</language>
    <item>
      <title>Adding a custom watcher to Phoenix</title>
      <dc:creator>Michael Jones</dc:creator>
      <pubDate>Wed, 29 Apr 2020 17:47:48 +0000</pubDate>
      <link>https://dev.to/contact-stack/adding-a-custom-watcher-to-phoenix-1e10</link>
      <guid>https://dev.to/contact-stack/adding-a-custom-watcher-to-phoenix-1e10</guid>
      <description>&lt;p&gt;At &lt;a href="http://www.contact-stack.com"&gt;Contact-Stack&lt;/a&gt;, we've recently added &lt;a href="https://elm-lang.org/"&gt;Elm&lt;/a&gt; to one of our &lt;a href="http://www.phoenixframework.org/"&gt;Phoenix&lt;/a&gt; projects. Elm is a fantastic language with a clear syntax, functional design, immutable data and a helpful compiler. &lt;/p&gt;

&lt;p&gt;For reasons of mild personal preference, we opted to not use &lt;a href="https://github.com/elm-community/elm-webpack-loader"&gt;elm-webpack-loader&lt;/a&gt; when integrating the Elm code with the current Javascript setup that we already have from Phoenix. Though ideally, we would still like the experience we have when we edit the Javascript, ie. it is rebuilt and Phoenix reloads the current browser with the newly built assets.&lt;/p&gt;

&lt;p&gt;Unfortunately for us the Elm compiler doesn't have a 'watch' mode so we can't rely on that. We need a separate process to run the Elm compiler whenever there is a change. I cannot find it now but I've seen comments from &lt;a href="https://twitter.com/rtfeldman"&gt;Richard Feldman&lt;/a&gt;, a prominent member of the Elm community, suggesting that the &lt;a href="https://github.com/paulmillr/chokidar"&gt;Chokidar&lt;/a&gt; project can be used to set up a simple watcher which runs the Elm compiler. Chokidar is a node project that does a great job of wrapping some of the node standard library functionality to provide a robust watcher. It is used by a number of high profile node projects, including &lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt;, to provide file watching functionality.&lt;/p&gt;

&lt;p&gt;For reference, the exact build command that I would like run is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;elm make src/Main.elm --output=../priv/static/js/elm.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From within the &lt;code&gt;assets&lt;/code&gt; directory in the standard Phoenix project layout.&lt;/p&gt;

&lt;p&gt;Now to start, we might consider adding the &lt;a href="https://github.com/kimmobrunfeldt/chokidar-cli"&gt;&lt;code&gt;chokidar-cli&lt;/code&gt;&lt;/a&gt; which allows you to set up watchers with a simple command. We can add chokidar-cli with &lt;code&gt;yarn add -D chokidar&lt;/code&gt; and then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chokidar "**/*.elm" -i node_modules -c "elm make src/Main.elm --output=../priv/static/js/elm.js"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we run that in the &lt;code&gt;assets&lt;/code&gt; directory it works great so maybe that's a good start. We add &lt;code&gt;-i node_modules&lt;/code&gt; as for some reason chokidar starts tracking some files in &lt;code&gt;node_modules&lt;/code&gt; too and we don't need it to. &lt;/p&gt;

&lt;p&gt;How do we go about adding it to Phoenix? If we look in the &lt;code&gt;config/dev.exs&lt;/code&gt; we see a block that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config :contact_stack, ContactStackWeb.Endpoint,                                                                                                           
  http: [port: 4000],                                                                                                                                      
  debug_errors: true,                                                                                                                                      
  code_reloader: true,                                                                                                                                     
  check_origin: false,                                                                                                                                     
  watchers: [                                                                                                                                              
    node: [                                                                                                                                                
      "node_modules/webpack/bin/webpack.js",                                                                                                               
      "--mode",                                                                                                                                            
      "development",                                                                                                                                       
      "--watch-stdin",                                                                                                                                     
      cd: Path.expand("../assets", __DIR__)                                                                                                                
    ]                                                                                                                                                      
  ]                                                                                                                                                        
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The relevant entry, as you might guess, is the &lt;code&gt;watchers&lt;/code&gt; list. This is a list of key-value pairs that each provide a program and a set of arguments for Phoenix to run as part of its watcher functionality. So in this case, it is going to run &lt;code&gt;node&lt;/code&gt; with that list of arguments which will result in it running &lt;code&gt;webpack&lt;/code&gt; in development mode. The last part is to ask Phoenix to run it in the &lt;code&gt;assets&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;So we could try to extend this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;   watchers: [
     node: [
       "node_modules/webpack/bin/webpack.js",
       "--mode",
       "development",
       "--watch-stdin",
       cd: Path.expand("../assets", __DIR__)
&lt;span class="gi"&gt;+    ],
+    node: [
+      "node_modules/.bin/chokidar",
+      "**/*.elm",
+      "-i",
+      "node_modules",
+      "-c",
+      "elm make src/Main.elm --output=../priv/static/js/elm.js",
+      cd: Path.expand("../assets", __DIR__)
&lt;/span&gt;     ]
   ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And actually, this seems to work great. We run this and, every time we save an Elm file, Phoenix runs the Elm compiler with the command we've provided. &lt;/p&gt;

&lt;p&gt;Unfortunately, if we kill the Phoenix server and check the running processes on our machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;^C
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
$ ps -ef | grep chokidar
michael  17499     1  0 16:16 ?        00:00:00 /home/michael/.nave/installed/12.14.0/bin/node node_modules/.bin/chokidar "**/*.elm" -c "elm make src/Main.elm --output=../priv/static/js/elm.js"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that the Chokidar process is still running. This is not great. We want to be able to freely restart our Phoenix dev server as often as we like without building up a back log of Chokidar processes which are all watching our Elm files and each running the Elm compiler on every change.&lt;/p&gt;

&lt;p&gt;So why is this happening? Well, I'm guessing that Phoenix uses &lt;a href="https://hexdocs.pm/elixir/Port.html"&gt;Elixir's Port functionality&lt;/a&gt; to run the watcher subprocesses and Elixir's Ports functionality as a &lt;a href="https://hexdocs.pm/elixir/Port.html#module-zombie-operating-system-processes"&gt;big warning about zombie processes&lt;/a&gt; that are left over when the main Elixir system process has stopped. It seems that Elixir doesn't, or perhaps can't, proactivity kill subprocesses that it has started when closing down. Rather it relies on those subprocesses noticing that their standard input has been closed and exiting themselves. I haven't come across this mechanism outside of Elixir but it might well be common. And if we glance up at the &lt;code&gt;webpack&lt;/code&gt; watcher config again we'll see that they're using a &lt;a href="https://webpack.js.org/api/cli/#watch-options"&gt;&lt;code&gt;--watch-stdin&lt;/code&gt;&lt;/a&gt; flag. Coincidence? Probably not.&lt;/p&gt;

&lt;p&gt;Unfortunately, &lt;code&gt;chokidar-cli&lt;/code&gt; doesn't have a &lt;code&gt;--watch-stdin&lt;/code&gt; flag nor any search results for &lt;code&gt;stdin&lt;/code&gt; &lt;a href="https://github.com/kimmobrunfeldt/chokidar-cli/search?q=stdin&amp;amp;type=Code"&gt;in the code&lt;/a&gt; so it seems like we can't rely on that. &lt;/p&gt;

&lt;p&gt;But &lt;code&gt;webpack&lt;/code&gt; is written in Javascript running on node so it must be possible and the main &lt;a href="https://www.npmjs.com/package/chokidar"&gt;&lt;code&gt;chokidar&lt;/code&gt; package&lt;/a&gt; is a library that allows you to easily access the file-watching functionality.&lt;/p&gt;

&lt;p&gt;If we go splunking through the webpack code looking for references to standard input then we come across &lt;a href="https://github.com/webpack/webpack-cli/blob/145c552d1ace3303607fe4d204106fe9437e24a0/packages/webpack-cli/lib/utils/Compiler.js#L176-L181"&gt;these lines&lt;/a&gt; in the webpack-cli project. Now I don't perfectly understand what is going on here but it seems that it is listening for a &lt;code&gt;'end'&lt;/code&gt; event on the standard input stream and using &lt;code&gt;process.exit()&lt;/code&gt; to close the whole program if it happens. That seems to fit with what Elixir's Ports expect.&lt;/p&gt;

&lt;p&gt;If we combine that with some relatively basic &lt;code&gt;chokidar&lt;/code&gt; library usage as they outline in the README then we get something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chokidar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chokidar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;execSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;child_process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Exit the process when standard input closes due to:&lt;/span&gt;
&lt;span class="c1"&gt;//   https://hexdocs.pm/elixir/1.10.2/Port.html#module-zombie-operating-system-processes&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;standard input end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Set up chokidar to watch all elm files and rebuild the elm app ignoring process errors&lt;/span&gt;
&lt;span class="nx"&gt;chokidar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;**/*.elm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ignored&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node_modules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;execSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./node_modules/.bin/elm make src/Main.elm --output=../priv/static/js/elm.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if we save it in a file called &lt;code&gt;assets/watch-elm.js&lt;/code&gt;. And then we change our &lt;code&gt;config/dev.exs&lt;/code&gt; config to read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    node: [
      "./watch-elm.js",
       cd: Path.expand("../assets", __DIR__)
    ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can run &lt;code&gt;mix phx.server&lt;/code&gt; and see that not only does the Elm compiler get run correctly on changes but when we kill our dev server the watcher process dies too. Success!&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Adding new watcher processes to Phoenix is relatively easy in some ways but this matter of watching standard-input is a bit confusing and is probably handled quite differently in different languages.&lt;/p&gt;

&lt;h1&gt;
  
  
  Notes
&lt;/h1&gt;

&lt;p&gt;The Phoenix documentation does provide a helper bash script that you can use to wrap an executable and which does the 'listening for standard input to close' for you. I have used that successfully when having to run a subprocess during Elixir tests but I wasn't unable to get it working on first try in this situation. Possibly the complexities of the extra escaping of the command line arguments got the better of me. I'm not sure.      &lt;/p&gt;

</description>
      <category>elixir</category>
      <category>phoenix</category>
      <category>node</category>
      <category>chokidar</category>
    </item>
    <item>
      <title>Mixing Gleam &amp; Elixir</title>
      <dc:creator>Michael Jones</dc:creator>
      <pubDate>Fri, 20 Mar 2020 12:33:26 +0000</pubDate>
      <link>https://dev.to/contact-stack/mixing-gleam-elixir-3fe3</link>
      <guid>https://dev.to/contact-stack/mixing-gleam-elixir-3fe3</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: This was very much an initial exploration. There is now an official project with a &lt;a href="https://github.com/gleam-lang/mix_gleam/"&gt;mix_gleam&lt;/a&gt; plugin. Please check that out!&lt;/p&gt;




&lt;p&gt;At &lt;a href="https://www.contact-stack.com"&gt;Contact Stack&lt;/a&gt;, we've chosen Elixir &amp;amp; Phoenix as the core of our tech stack and we're happy with the choice. But... we do miss having a really good type system and a helpful compiler (like with &lt;a href="https://elm-lang.org/"&gt;Elm&lt;/a&gt;) to guide us through development.&lt;/p&gt;

&lt;p&gt;Elixir targets the BEAM virtual machine and there are few statically typed languages that target the BEAM as well. Here we're going to look into a simple set up for integrating &lt;a href="https://gleam.run/"&gt;Gleam&lt;/a&gt; into your Elixir project using a &lt;a href="https://hexdocs.pm/mix/1.10.2/Mix.Task.Compiler.html"&gt;Mix Compiler Task&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Gleam is a statically typed functional programming language which uses a syntax that is more approachable to, say, Javascript, C or Java programmers than some ML flavoured languages. The Gleam compiler is written in Rust and outputs Erlang source files which can then be compiled to BEAM by the Erlang compiler.&lt;/p&gt;

&lt;p&gt;Mix is a multi-functional build tool for Elixir projects. It can manage dependencies, run tests, execute tasks and compile your Elixir code. It also supports compiling erlang files by default and can be extended with Mix Compiler Tasks to compile other languages. We're going to create a Mix Compiler Task for Gleam so that Mix can use the Gleam compiler to build Gleam files.&lt;/p&gt;

&lt;p&gt;You can try the steps below yourself and check out the demonstration repository: &lt;a href="https://github.com/michaeljones/gleam-phoenix-mix"&gt;https://github.com/michaeljones/gleam-phoenix-mix&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Here we go!&lt;/p&gt;

&lt;p&gt;We're assuming you have the &lt;code&gt;gleam&lt;/code&gt; compiler available in your environment to execute. Run this to check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gleam --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't, then you can follow the &lt;a href="https://gleam.run/getting-started/installing-gleam.html"&gt;installation instructions&lt;/a&gt; over in the Gleam docs.&lt;/p&gt;

&lt;p&gt;Now we're going to go through setting up a &lt;a href="http://www.phoenixframework.org/"&gt;Phoenix&lt;/a&gt; project from scratch. We won't go into the details but just so we have a clear base to work with.&lt;/p&gt;

&lt;p&gt;Run the following commands to set up an empty phoenix project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir gleam-phoenix-mix
cd gleam-phoenix-mix
mix phx.new . --app my_app
mix ecto.create
cd assets 
npm install
cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to create our mix compiler task. We put this in a &lt;code&gt;lib/mix/tasks/compile&lt;/code&gt; directory to reflect the module name that we need to give it which is &lt;code&gt;Mix.Tasks.Compile.Gleam&lt;/code&gt;. So we create our new directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p lib/mix/tasks/compile/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add the follow code in a file called &lt;code&gt;lib/mix/tasks/compile/gleam.ex&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Mix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Compile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Gleam&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Mix&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Compiler&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"gleam"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="ss"&gt;:ok&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All this is really doing is running the gleam compiler directly with the 'build' argument to get it to build all the gleam files it can find. &lt;/p&gt;

&lt;p&gt;Run the elixir compiler so that we compile that mix task before we try to use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix compile.elixir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to make gleam happy we need to set up a &lt;code&gt;.toml&lt;/code&gt; config file for it. So we create a file called &lt;code&gt;gleam.toml&lt;/code&gt; in the root of the project with the follow content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name = "my_app"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we create a &lt;code&gt;src&lt;/code&gt; directory for the gleam files. The Gleam compiler expects the gleam files to be in a &lt;code&gt;src&lt;/code&gt; directory. This is different to elixir/mix which expects them in the &lt;code&gt;lib&lt;/code&gt; directory by default. Elixir/mix can be configured but Gleam can't at the time of writing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then create our Gleam module by making a file called &lt;code&gt;src/hello_world.gleam&lt;/code&gt; with the following code in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn hello() {
  "Hello, from gleam!"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we make the following change to the &lt;code&gt;mix.exs&lt;/code&gt; file to add our compiler task to the list of compilers being run when you do &lt;code&gt;mix compile&lt;/code&gt; and to make sure mix's erlang compiler looks in the &lt;code&gt;gen&lt;/code&gt; folder&lt;br&gt;
for erlang files. The &lt;code&gt;gleam&lt;/code&gt; compiler compiles &lt;code&gt;.gleam&lt;/code&gt; files from the &lt;code&gt;src&lt;/code&gt; folder into &lt;code&gt;.erl&lt;/code&gt; files in the &lt;code&gt;gen&lt;/code&gt; folder so we need the erlang compiler to find them there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;       elixir: "~&amp;gt; 1.5",
       elixirc_paths: elixirc_paths(Mix.env()),
&lt;span class="gi"&gt;+      erlc_paths: ["src", "gen"],
&lt;/span&gt;&lt;span class="gd"&gt;-      compilers: [:phoenix, :gettext] ++ Mix.compilers(),
&lt;/span&gt;&lt;span class="gi"&gt;+      compilers: [:phoenix, :gettext, :gleam] ++ Mix.compilers(),
&lt;/span&gt;       start_permanent: Mix.env() == :prod,
       aliases: aliases(),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I assume that Mix runs the compilers from the start to the end of the list. So we want the &lt;code&gt;:gleam&lt;/code&gt; entry to be before the &lt;code&gt;:erlang&lt;/code&gt; entry that's in &lt;code&gt;Mix.compilers()&lt;/code&gt; so that the Erlang compiler will run after the Gleam compile and compile the Erlang files that the Gleam compiler creates.&lt;/p&gt;

&lt;p&gt;As a simple demonstration of interop between Elixir &amp;amp; the compiled gleam files, make the following change to &lt;code&gt;lib/my_app_web/controllers/page_controller.ex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; defmodule MyAppWeb.PageController do
   use MyAppWeb, :controller

   def index(conn, _params) do
&lt;span class="gd"&gt;-    render(conn, "index.html")
&lt;/span&gt;&lt;span class="gi"&gt;+    render(conn, "index.html", title: :hello_world.hello())
&lt;/span&gt;   end
 end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works because Gleam modules are compiled to Erlang modules and, in Elixir, Erlang modules are accessible via the atom that is their name.&lt;/p&gt;

&lt;p&gt;And then we make the following change to &lt;code&gt;lib/my_app_web/templates/page/index.html.eex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; &amp;lt;section class="phx-hero"&amp;gt;
&lt;span class="gd"&gt;-  &amp;lt;h1&amp;gt;&amp;lt;%= gettext "Welcome to %{name}!", name: "Phoenix" %&amp;gt;&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+  &amp;lt;h1&amp;gt;&amp;lt;%= @title %&amp;gt;&amp;lt;/h1&amp;gt;
&lt;/span&gt;   &amp;lt;p&amp;gt;A productive web framework that&amp;lt;br/&amp;gt;does not compromise speed or maintainability.&amp;lt;/p&amp;gt;
 &amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix compile
mix phx.server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And load &lt;code&gt;http://localhost:4000&lt;/code&gt; in our browser to see "Hello, from gleam!" in the centre of the standard Phoenix welcome page.&lt;/p&gt;

&lt;p&gt;Remember, if you're curious you can check out the final result at this demonstration repo on Github: &lt;a href="https://github.com/michaeljones/gleam-phoenix-mix"&gt;https://github.com/michaeljones/gleam-phoenix-mix&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;It is exciting to see that it isn't too hard to incorporate Gleam code into an Elixir project using Mix. It is great that Mix is built with this kind of extensibility in mind. There are definitely more questions to answer and rough edges to smooth out but it is exciting to have an avenue to using a strongly typed language on the BEAM.  &lt;/p&gt;

</description>
      <category>elixir</category>
      <category>gleam</category>
      <category>mix</category>
    </item>
    <item>
      <title>Introducing Dialyzer &amp; type-specs to an Elixir Project</title>
      <dc:creator>Michael Jones</dc:creator>
      <pubDate>Tue, 17 Mar 2020 14:35:45 +0000</pubDate>
      <link>https://dev.to/contact-stack/introducing-dialyzer-type-specs-to-an-elixir-project-312d</link>
      <guid>https://dev.to/contact-stack/introducing-dialyzer-type-specs-to-an-elixir-project-312d</guid>
      <description>&lt;p&gt;At &lt;a href="https://www.contact-stack.com"&gt;Contact Stack&lt;/a&gt; we use &lt;a href="https://elixir-lang.org/"&gt;Elixir&lt;/a&gt; &amp;amp; &lt;a href="http://www.phoenixframework.org/"&gt;Phoenix&lt;/a&gt; as the core of the backend. I am fascinated by the design &amp;amp; power of the BEAM, the virtual machine that Elixir targets, and I want to learn more about it. I also love strongly &amp;amp; statically typed languages, particularly due to my recent history working with &lt;a href="https://elm-lang.org/"&gt;Elm&lt;/a&gt; which has a great type system and a helpful compiler.&lt;/p&gt;

&lt;p&gt;Elixir is dynamically typed language which leaves me a little nervous about the long term future of the project. I really like types and I find them incredibly useful when the code base grows larger and you're returning to parts of it that you haven't looked at in a while. Often I can't remember exactly the kind of data that I'm passing around and strong types really help with that understanding. Plus I've grown to love having a compiler guide you through the code base when doing refactoring as it points out all the places you need to change.&lt;/p&gt;

&lt;p&gt;One way to bring a little more type safety to Elixir projects is to use &lt;a href="http://erlang.org/doc/man/dialyzer.html"&gt;Dialyzer&lt;/a&gt;. Dialyzer performs static analysis on your code and tries to warn you about anything that is almost certainly going to fail. It can be helped by providing type annotations and it also derives its own from inspecting the code. It isn't as good as a solid type system but it is better than nothing.&lt;/p&gt;

&lt;p&gt;So, how do we go about introducing Dialzyer and type annotations through out our codebase? Here are the steps that I've followed for Contact Stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Dialyzer
&lt;/h2&gt;

&lt;p&gt;Maybe a bit of an obvious first step! We can use the &lt;a href="https://github.com/jeremyjh/dialyxir"&gt;dialxyir&lt;/a&gt; project to add a dialyzer task to mix. At the time of writing that involves adding this line to your &lt;code&gt;mix.exs&lt;/code&gt; &lt;code&gt;deps&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:dialyxir, "~&amp;gt; 1.0", only: [:dev], runtime: false},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Run Dialyzer &amp;amp; Fix issues
&lt;/h2&gt;

&lt;p&gt;We can now run dialyzer with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix dialyzer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the command line. This can take a long time as dialyzer analyses and creates &lt;code&gt;PLT&lt;/code&gt; caches for all the Elixir &amp;amp; Erlang standard libraries. Fortunately it is much quicker on that next run though still not as fast a many compilers out there.&lt;/p&gt;

&lt;p&gt;The errors can honestly be quite hard to understand. I would recommend googling as much as possible. I've learned a few of things though that I'll share.&lt;/p&gt;

&lt;p&gt;Firstly, in my projects I've had to config dialyzer to make it away of &lt;code&gt;ex_unit&lt;/code&gt; and &lt;code&gt;mix&lt;/code&gt; otherwise it issues warnings. I suspect I only needed to add &lt;code&gt;mix&lt;/code&gt; because I have a custom mix task. You can configure dialyzer by adding the following to your the &lt;code&gt;project&lt;/code&gt; config in mix.exs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dialyzer: [plt_add_apps: [:ex_unit, :mix], ignore_warnings: "config/dialyzer.ignore"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we add &lt;code&gt;ex_unit&lt;/code&gt; &amp;amp; &lt;code&gt;mix&lt;/code&gt; and also indicate an ignore file.&lt;/p&gt;

&lt;p&gt;Secondly, some errors don't seem to be clearly fixable by code that is under our control. In which case we want to add those errors to the ignore file. If you run dialyzer with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix dialyzer --format dialyzer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can copy the start or all of the error that you want to ignore onto a new line in the ignore file we've just set up and dialyzer will skip it on future runs. &lt;/p&gt;

&lt;p&gt;Thirdly, if you get a warning that says that some function has &lt;code&gt;no local return&lt;/code&gt; then it normally means there is another warning within the function itself that makes dialzyer think that the function will never work. You can skip the 'no local return' warning at look at the next one in the output so see what the issue might be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduce Credo
&lt;/h2&gt;

&lt;p&gt;Credo is a linting tool for Elixir that can warn if you don't provide a type annotation on a function. Part of our goal here is to make sure that we provide type annotations for all the functions in our code base. This helps Dialyzer understand our intent and is self-documenting which helps ourselves and others on the code base.&lt;/p&gt;

&lt;p&gt;So we add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{:credo, "~&amp;gt; 1.2", only: [:dev, :test], runtime: false}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To our &lt;code&gt;mix.exs&lt;/code&gt; &lt;code&gt;deps&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure &amp;amp; Fix Credo Warnings
&lt;/h2&gt;

&lt;p&gt;Credo checks for a lot of different things. It does not check for type annotations by default and we're going to enable that but first, as long as they are manageable, fix any current warnings that Credo has in place. You can do this by changing your code or suppressing some of Credo's warnings. I have the following config for my preferences:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;%{
  configs: [
    %{
      name: "default",
      files: %{
        included: ["lib/"],
        excluded: []
      },
      checks: [
        {Credo.Check.Design.AliasUsage, false},
        {Credo.Check.Readability.AliasOrder, false}
      ]
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Extend Credo Rules to Include Type Annotations
&lt;/h2&gt;

&lt;p&gt;We extend our config to include the &lt;code&gt;Specs&lt;/code&gt; check by adding this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;      checks: [
        {Credo.Check.Design.AliasUsage, false},
        {Credo.Check.Readability.AliasOrder, false}
&lt;span class="gi"&gt;+       {Credo.Check.Readability.Specs, []}
&lt;/span&gt;      ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Silence the Huge Number of Credo Warnings
&lt;/h2&gt;

&lt;p&gt;Now we can run credo again to get a sense of the number of missing type annotations. If you have a small number then go ahead and try to add them now. If, like me, you have something like 200 warnings or more then you might prefer to silence them for now and attend to them gradually.&lt;/p&gt;

&lt;p&gt;To do this we can run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix credo --strict | grep lib | cut -d " " -f 8 | cut -d ":" -f 1 | sort -u | xargs sed -i '1s/^/# credo:disable-for-this-file Credo.Check.Readability.Specs\n/'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is going to add &lt;code&gt;# credo:disable-for-this-file Credo.Check.Readability.Specs&lt;/code&gt; to the top of every file in your codebase that has missing type annotations.&lt;/p&gt;

&lt;p&gt;When we run &lt;code&gt;mix credo --strict&lt;/code&gt; again we should see a clean sheet. Now you can go into the files at your leisure and remove the comment at the top and add type annotations. Credo will warn about any that are missing and warn by default for any new files we add to the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I worry that dialyzer is not very useful in comparison to the type systems &amp;amp; compilers that I have used before but it feels good to be trying to make the code as tight and error free as possible. I am at the beginning of this journey so I can't really report on whether it is worth it long term but we'll see. &lt;/p&gt;

</description>
      <category>elixir</category>
      <category>dialyzer</category>
      <category>types</category>
    </item>
  </channel>
</rss>
