<?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: Rob Porter</title>
    <description>The latest articles on DEV Community by Rob Porter (@rgeraldporter).</description>
    <link>https://dev.to/rgeraldporter</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%2Fuser%2Fprofile_image%2F53999%2Ffca72e5b-4cdd-462a-a592-6a7010b49556.jpg</url>
      <title>DEV Community: Rob Porter</title>
      <link>https://dev.to/rgeraldporter</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rgeraldporter"/>
    <language>en</language>
    <item>
      <title>A cautionary note about use of Javascript's Set and Map objects</title>
      <dc:creator>Rob Porter</dc:creator>
      <pubDate>Wed, 12 Jun 2019 14:50:51 +0000</pubDate>
      <link>https://dev.to/rgeraldporter/a-cautionary-note-about-use-of-javascript-s-set-and-map-objects-1kpc</link>
      <guid>https://dev.to/rgeraldporter/a-cautionary-note-about-use-of-javascript-s-set-and-map-objects-1kpc</guid>
      <description>&lt;p&gt;A few weeks ago I was working on a really odd bug. An object was being assembled that contained some user data, and when we went to send that object up to the server as JSON, it was always incomplete -- it was missing data in one of the properties.&lt;/p&gt;

&lt;p&gt;I tried all kinds of things to track down what was causing this: was an object merge acting unexpectedly? Was there an event somewhere that removed this data that I didn't know about?&lt;/p&gt;

&lt;p&gt;It was actually much simpler than this. The problem, was &lt;code&gt;JSON.stringify()&lt;/code&gt; and a &lt;code&gt;Set&lt;/code&gt; contained within the object being stringified.&lt;/p&gt;

&lt;p&gt;For an example, I'll create a user with some "lucky numbers", which I'm just making up as an example where the entries should be unique, so a &lt;code&gt;Set&lt;/code&gt; would (in theory) be better than an &lt;code&gt;Array&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Haleema Greer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7252&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;luckyNumbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&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;Looks good enough. Now, let's convert to JSON so we can send this to a server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// &amp;gt; "{\"name\":\"Haleema Greer\",\"id\":7252,\"luckyNumbers\":{}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Wait, what just ate our &lt;code&gt;luckyNumbers&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Apparently &lt;code&gt;Set&lt;/code&gt; data just isn't in a format that can convert to JSON without some extra work.&lt;/p&gt;

&lt;p&gt;One good solution is presented on &lt;a href="https://stackoverflow.com/a/46491780/325674"&gt;Stack Overflow&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Set_toJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Set_toJSON&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// &amp;gt; "{\"name\":\"Haleema Greer\",\"id\":7252,\"luckyNumbers\":[55,45,62,21]}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Much better!&lt;/p&gt;

&lt;p&gt;Many guides will either state or imply &lt;code&gt;Set&lt;/code&gt; can be used as a drop-in for &lt;code&gt;Array&lt;/code&gt;, but they do not act the same and can have some unexpected consequences if you treat them the same. &lt;/p&gt;

&lt;p&gt;Be aware these two types are different, and what works for one, may not work for the other.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Map&lt;/code&gt; also shares this issue as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;userDataMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Haleema Greer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7252&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;luckyNumbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&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;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userDataMap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// &amp;gt; "{\"name\":\"Haleema Greer\",\"id\":7252,\"luckyNumbers\":{}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Fixing this isn't as straight-forward, because &lt;code&gt;Map&lt;/code&gt;'s structure doesn't directly translate to JSON. It will be a matter of how you prefer to solve the problem.&lt;/p&gt;

&lt;p&gt;For various solutions to converting &lt;code&gt;Map&lt;/code&gt; to JSON, see this &lt;a href="https://stackoverflow.com/questions/29085197/how-do-you-json-stringify-an-es6-map"&gt;Stack Overflow discussion&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Using shell/bash commands in code? Use "long" options</title>
      <dc:creator>Rob Porter</dc:creator>
      <pubDate>Mon, 10 Jun 2019 19:48:27 +0000</pubDate>
      <link>https://dev.to/rgeraldporter/using-shell-bash-commands-in-code-use-long-options-2f4k</link>
      <guid>https://dev.to/rgeraldporter/using-shell-bash-commands-in-code-use-long-options-2f4k</guid>
      <description>&lt;p&gt;Many developers at one point or another need to use a bash or shell script inside code.&lt;/p&gt;

&lt;p&gt;Maybe it's a command being issued in Docker, or an exec function in Node.js, or perhaps a shell command in a Jenkins pipeline.&lt;/p&gt;

&lt;p&gt;One short and simple tip though I've picked up after having to do this a few times is, &lt;strong&gt;when documenting commands in code, always use the long options when available&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Long (&lt;code&gt;--&lt;/code&gt;) and short (&lt;code&gt;-&lt;/code&gt;) options are there for good reason -- one for clarity in documentation, the other for brevity when typing out commands in the terminal.&lt;/p&gt;

&lt;p&gt;For example, here's a sample docker command below. Imagine you found this in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--no-cache&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; myimage:latest &lt;span class="nt"&gt;-f&lt;/span&gt; path/Dockerfile &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's say you were new to docker and encountered this in a Jenkinsfile or bash script.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;--no-cache&lt;/code&gt; seems quite clear about what it does. But what about the rest?&lt;/p&gt;

&lt;p&gt;Wouldn't it have been better if this had been how it was written:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--no-cache&lt;/span&gt; &lt;span class="nt"&gt;--tag&lt;/span&gt; myimage:latest &lt;span class="nt"&gt;--file&lt;/span&gt; path/Dockerfile &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Even better yet, what if it had been broken into a longer statement, using line breaks for each option?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--no-cache&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tag&lt;/span&gt; myimage:latest &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--file&lt;/span&gt; path/Dockerfile &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now the next person who reaches this code is less likely to have the urge to look up what &lt;code&gt;-q&lt;/code&gt;, &lt;code&gt;-f&lt;/code&gt;, and &lt;code&gt;-t&lt;/code&gt; is for. &lt;/p&gt;

&lt;p&gt;Not all terminal applications are consistent with what their short options mean, it can be easy to mix them up. It is often the case that things like &lt;code&gt;-q&lt;/code&gt; will mean &lt;code&gt;--quiet&lt;/code&gt; in one application, and &lt;code&gt;--query&lt;/code&gt; in another.&lt;/p&gt;

&lt;p&gt;Do this, and your code reviewers and inheritors may very well thank you for it.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>shell</category>
    </item>
    <item>
      <title>Creating a ZFS Image of a MySQL Data Directory</title>
      <dc:creator>Rob Porter</dc:creator>
      <pubDate>Fri, 07 Jun 2019 13:18:27 +0000</pubDate>
      <link>https://dev.to/rgeraldporter/creating-a-zfs-image-of-a-mysql-data-directory-dad</link>
      <guid>https://dev.to/rgeraldporter/creating-a-zfs-image-of-a-mysql-data-directory-dad</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Notes&lt;/strong&gt;: I wrote this documentation around 2013 as internal documentation at &lt;a href="https://weeverapps.com/"&gt;Weever Apps&lt;/a&gt; for setting up RAID-Z as a method of making very quick backups of MySQL. Since we no longer use this setup and the documentation will never be used again, I felt it might be a good idea to post it out there for those who might find some use in it. Using RAID-Z for MySQL was amazing, and never failed us, and allowed hourly snapshot-based backups with no downtime. We've since moved to AWS RDS instances though.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This will be part of multiple posts that combined will allow one to build a RAID-Z setup for MySQL. Or, at least it used to be able to! While this is geared towards Azure, I'm sure it would work anywhere.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As I add more parts over the next few days I'll add links here.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Article series
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/installing-zfs-on-centos-2fkl"&gt;Installing ZFS on CentOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/creating-a-raid-z-drive-with-zfs-on-centos-3484"&gt;Creating a RAID-Z Drive for MySQL with ZFS on CentOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/setting-up-raid-z-for-use-in-a-mysql-master-master-replicator-pattern-4eme"&gt;Setting up RAID-Z for use in a MySQL Master-Master Replicator Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creating a ZFS Image of a MySQL Data Directory&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Instructions
&lt;/h1&gt;

&lt;p&gt;Creating a ZFS image for backup is pretty easy.&lt;/p&gt;

&lt;p&gt;First, a ZFS snapshot must exist. If one does not already, create one. &lt;/p&gt;

&lt;p&gt;If this is for MySQL and the tables in MySQL are using MyISAM, make sure to either turn off the server briefly, or, lock the tables momentarily. In my experience these locks just delay writes until unlocked, and snapshotting is &lt;em&gt;surprisingly&lt;/em&gt; quick in ZFS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;FLUSH TABLES WITH READ LOCK&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This example will assume you're grabbing the MySQL data directory, which would be stored in a tank called &lt;code&gt;sqlstorage&lt;/code&gt;, with filesystem &lt;code&gt;data&lt;/code&gt;. Adjust if your setup is differently named.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;zfs snapshot sqlstorage/data@now
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we can unlock the tables or start the MySQL server up again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;UNLOCK TABLES&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All we need is one command to send this snapshot to a file. Depending on the size of the file system, this could take a while.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;zfs send sqlstorage/data@now &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/tmp/sqlstorage-backup.zfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Is something badly out of date? Did this work for you? Please post a comment to help others who might use this for guidance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>zfs</category>
      <category>mysql</category>
    </item>
    <item>
      <title>Building Expressive Monads in Javascript: Introduction</title>
      <dc:creator>Rob Porter</dc:creator>
      <pubDate>Fri, 07 Jun 2019 00:47:03 +0000</pubDate>
      <link>https://dev.to/rgeraldporter/building-expressive-monads-in-javascript-introduction-23b</link>
      <guid>https://dev.to/rgeraldporter/building-expressive-monads-in-javascript-introduction-23b</guid>
      <description>&lt;p&gt;The monad is a powerful design pattern that, when used correctly, can completely change how you think about handling values in Javascript (JS). This introductory tutorial is for any level of JS familiarity, even (and perhaps, especially) beginners.&lt;/p&gt;

&lt;p&gt;For those already familiar with monads, this introduction only covers the essentials for using monads effectively, and will only touch upon the origins and more technical language when necessary to give context. No attempts will be made to explain category theory or deep concepts of functional programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does "monad" mean?
&lt;/h2&gt;

&lt;p&gt;For the purposes of this introduction, I'd like to refer to the &lt;a href="https://www.merriam-webster.com/dictionary/monad"&gt;dictionary definition&lt;/a&gt;, which pre-dates its use in mathematics and programming: &lt;em&gt;a single unit&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This definition is akin to &lt;em&gt;dyad&lt;/em&gt; and &lt;em&gt;triad&lt;/em&gt; - meaning two, or three units respectively.&lt;/p&gt;

&lt;p&gt;The term "monad" is used differently in mathematics, and in category theory. For programming, the monad was made popular by Haskell, and has been transposed into various languages, including JS. It is used as a way of containing values and controlling mutations.&lt;/p&gt;

&lt;p&gt;I think though that the definition of &lt;em&gt;"a single unit"&lt;/em&gt; is good to keep in mind. It helps me, at least.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problems do monads solve?
&lt;/h2&gt;

&lt;p&gt;Any time you've had to deal with trying to keep track of value mutation, any compatible type of monad would have helped wrangle how the values are changing.&lt;/p&gt;

&lt;p&gt;If you've struggled with &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; causing havoc in functions that can't handle them, a &lt;code&gt;Maybe&lt;/code&gt; monad would solve that problem.&lt;/p&gt;

&lt;p&gt;For myself, it helps break down value-altering processes into small steps, allowing me to think about one piece at a time, not worrying about values mutating in unexpected ways. One can focus better on individual functions more easily. The results are so much more predictable, and the steps in the process more testable.&lt;/p&gt;

&lt;p&gt;Monads can even handle processes that are asyncronous, but for the purposes of this introduction, we're only going to focus on syncronous cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  How is it used in Javascript?
&lt;/h2&gt;

&lt;p&gt;A monad is best thought of as a container of a value: much like how the container-like types &lt;code&gt;Array&lt;/code&gt; and &lt;code&gt;Object&lt;/code&gt; can hold a collection of values, a monad does the same.&lt;/p&gt;

&lt;p&gt;Each monad you build is like building a new kind of container-like type. As &lt;code&gt;Array&lt;/code&gt; has methods like &lt;code&gt;forEach&lt;/code&gt;, and as &lt;code&gt;Object&lt;/code&gt; has methods like &lt;code&gt;keys&lt;/code&gt;, a monad will have standard methods, and methods you can add on a case-by-case basis.&lt;/p&gt;

&lt;p&gt;If you've used &lt;code&gt;Array&lt;/code&gt; and &lt;code&gt;Object&lt;/code&gt;, you've already got some experience that will be useful with monads.&lt;/p&gt;

&lt;h2&gt;
  
  
  The most basic monad: &lt;code&gt;Identity&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;We'll start our first example with the most basic possible monad, an &lt;code&gt;Identity&lt;/code&gt; monad.&lt;/p&gt;

&lt;h3&gt;
  
  
  First though, a quick note on monad naming and style conventions...
&lt;/h3&gt;

&lt;p&gt;Before we begin to build an &lt;code&gt;Identity&lt;/code&gt; monad, I'd like to make clear the naming and styles you'll see in this introduction. When first learning monads, I was quickly hung up on the names and styles. It was enough to slow me down quite a bit.&lt;/p&gt;

&lt;p&gt;You'll see monads named with capital letters, often with rather abstract names.&lt;/p&gt;

&lt;p&gt;Do not get too concerned with the naming; if an abstract name is confusing you, remember that it is said that &lt;em&gt;"naming things is one of the hardest things in computer science"&lt;/em&gt;. Often these names point to a particular established design pattern that may have multiple possible awkward-sounding names.&lt;/p&gt;

&lt;p&gt;The monad names will be capitalized -- this is an established convention, my assumption is this is to demonstrate they are a special type, much like a &lt;code&gt;class&lt;/code&gt; name.&lt;/p&gt;

&lt;p&gt;The same will go with monad method names, the most common ones have many established names. When one is introduced, I'll mention other names you may find being used for the same method. I will aim to focus on whichever method name I feel is most expressive for someone new to monads, though opinions will likely differ.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second, a quick note on the term "identity"...
&lt;/h3&gt;

&lt;p&gt;One more brief side-note: the monad name &lt;code&gt;Identity&lt;/code&gt; is based on a term "&lt;code&gt;identity&lt;/code&gt;" used for a function which simply returns the value given to it. The &lt;code&gt;Identity&lt;/code&gt; monad will effectively do the same. This may seem like a near-useless function (it doesn't do anything!) but it is great for giving the most basic example, and there are some actual use cases in functional programming. &lt;/p&gt;

&lt;p&gt;For instance, if you are required pass a function as an argument to potentially alter a value, but wanted to ensure that function didn't actually alter the value in certain circumstances, an identity is a great way to do that.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Identity&lt;/code&gt;: the code
&lt;/h3&gt;



&lt;div class="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;Identity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// example use:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Yes, that is all. Write something like the above, and you have written a monad. These are the three required methods.&lt;/p&gt;

&lt;p&gt;Many tutorials will hand you a library and just show how to use monads, but I feel a hands-on approach is going to actually make it easier to understand the concept.&lt;/p&gt;

&lt;p&gt;That all stated, this &lt;code&gt;Identity&lt;/code&gt; monad, at 5 lines, has a lot going on. Let's break that down.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;const Identity = x =&amp;gt; ({ ... });&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The simplest part: we'll be using &lt;code&gt;const&lt;/code&gt; as we don't want our defintion to ever change. You might know or have heard that &lt;code&gt;const&lt;/code&gt; isn't perfect at locking down mutations: if you use &lt;code&gt;const&lt;/code&gt; to define an &lt;code&gt;Array&lt;/code&gt; or &lt;code&gt;Object&lt;/code&gt;, and those can subsequenly mutate.&lt;/p&gt;

&lt;p&gt;Thankfully, we're assigning a &lt;em&gt;function expression&lt;/em&gt; to our &lt;code&gt;const&lt;/code&gt;, which I like to refer to as a &lt;em&gt;Constant Function Expression&lt;/em&gt; (CFE). I prefer these over the standard &lt;code&gt;function&lt;/code&gt; defintion as they prevent anyone ever meddling with the function prototypes.&lt;/p&gt;

&lt;p&gt;If you look up monad libraries in JS often you will find them based upon &lt;code&gt;function&lt;/code&gt; or &lt;code&gt;class&lt;/code&gt;, which makes them susceptible to meddling.&lt;/p&gt;

&lt;p&gt;Our value we're going to pass into the &lt;code&gt;Identity&lt;/code&gt; monad is &lt;code&gt;x&lt;/code&gt;, and the beauty of a CFE is that the arguments passed into it cannot ever be altered or changed: it is absolutely immutable without having to use any special APIs.&lt;/p&gt;

&lt;p&gt;This is why I love this pattern for monads: in just a few lines with no advanced syntaxes it creates an absolutely immutible value!&lt;/p&gt;

&lt;p&gt;Once we pass &lt;code&gt;1&lt;/code&gt; as a value in, nothing can ever change that &lt;code&gt;1&lt;/code&gt; was the value passed in. If we had used a class and stored the value in an accessor, without some special API usage we'd be able to something like &lt;code&gt;myIdentity.__value = 2&lt;/code&gt; and just change the value.&lt;/p&gt;

&lt;p&gt;And while I have not tested this hypothesis, I would think this is the JS monad pattern with the least-possible memory footprint.&lt;/p&gt;

&lt;p&gt;Let's start looking at the core methods.&lt;/p&gt;

&lt;h4&gt;
  
  
  Method: &lt;code&gt;emit&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Alternative names:&lt;/strong&gt; &lt;code&gt;join&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;valueOf&lt;/code&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Code
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  Example use
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&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;one&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is the simplest method, that just returns the value contained within. Most commonly known as &lt;code&gt;join&lt;/code&gt;, however I find that quite unexpressive when it comes to learning in Javascript. I like &lt;code&gt;emit&lt;/code&gt; for explaining what it does as a verb: emit the value contained within.&lt;/p&gt;

&lt;p&gt;A quick note of warning though, &lt;code&gt;emit&lt;/code&gt; isn't something you should necessarily depend on in anything but debugging. In fact, you won't see me use it at all in the primary examples.&lt;/p&gt;

&lt;h4&gt;
  
  
  Method: &lt;code&gt;chain&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Alternative names:&lt;/strong&gt; &lt;code&gt;flatMap&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Code
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  Example use
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&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;one&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The next simplest method is &lt;code&gt;chain&lt;/code&gt;, which is intended to &lt;em&gt;chain&lt;/em&gt; various monads together, but can operate as demonstrated above.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;f =&amp;gt; f(x)&lt;/code&gt; indicates a function &lt;code&gt;f&lt;/code&gt; is taken, and value &lt;code&gt;x&lt;/code&gt; is passed to said function. In this example, &lt;code&gt;a =&amp;gt; a + 1&lt;/code&gt; takes the value, returns it plus one.&lt;/p&gt;

&lt;p&gt;A more typical usage may be:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;one&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;SomeMonad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;SomeMonad&lt;/code&gt; is a monad. In this &lt;code&gt;chain&lt;/code&gt;, we transform &lt;code&gt;Identity(1)&lt;/code&gt; into &lt;code&gt;SomeMonad(2)&lt;/code&gt;. When you are using &lt;code&gt;chain&lt;/code&gt;, typically you're indicating that the function you are passing in either will itself return a monad (preventing recursive monad-inside-monad-inside-monad...) or that you intend for the result to be non-monadic.&lt;/p&gt;

&lt;p&gt;Don't worry too much about &lt;em&gt;why&lt;/em&gt; right now, as this I find is less commonly useful as compared to the next method, &lt;code&gt;map&lt;/code&gt;. But it is important to understand first before we look at &lt;code&gt;map&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Method: &lt;code&gt;map&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Alternative name:&lt;/strong&gt; &lt;code&gt;fmap&lt;/code&gt; ("functional map")&lt;/p&gt;

&lt;h5&gt;
  
  
  Code
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h5&gt;
  
  
  Example use
&lt;/h5&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&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;one&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; [not pretty: outputs monad defintion... at least until we implement .inspect() below]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;map&lt;/code&gt; is the most important method. This is what makes monads so useful: we can take an established monad &lt;code&gt;Identity(1)&lt;/code&gt; and through a function, generate &lt;code&gt;Identity(2)&lt;/code&gt; without any mutation of our example constant &lt;code&gt;one&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Put simply, it is the &lt;code&gt;chain&lt;/code&gt; function with a built-in rewrapping of the resulting value into a new &lt;code&gt;Identity&lt;/code&gt;, which itself can be subject to &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;chain&lt;/code&gt;, and &lt;code&gt;emit&lt;/code&gt; on and on for as many functions you'd like to apply to it.&lt;/p&gt;

&lt;p&gt;This is the method I most use in a monad.&lt;/p&gt;

&lt;p&gt;I sometimes like to think of it like a bank account ledger. All values must be accounted for: where they started (&lt;code&gt;.of&lt;/code&gt;), and how they changed over time (&lt;code&gt;map&lt;/code&gt; &amp;amp; &lt;code&gt;chain&lt;/code&gt; methods). The initial value of a monad is like a new bank account being opened with an initial deposit, each &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;chain&lt;/code&gt; is a transaction atop it. Nothing will ever change the value of the initial deposit, but we have methods to figure out how much remains in the account today.&lt;/p&gt;

&lt;h4&gt;
  
  
  One more method: &lt;code&gt;inspect&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;You may have noticed doing a console output of the value after a map isn't going to look pretty. While not strictly required to make a monad work correctly, &lt;code&gt;inspect&lt;/code&gt; can help inform us via the console what exactly is in the monad, and what type of monad it is.&lt;/p&gt;



&lt;div class="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;Identity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&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="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="na"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Identity(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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;two&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; Identity(2)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This method is important in debugging as a simple &lt;code&gt;emit&lt;/code&gt; would not give you the type &lt;code&gt;Identity&lt;/code&gt;; just the contained value &lt;code&gt;2&lt;/code&gt;. This is very important when working with multiple monad types.&lt;/p&gt;

&lt;h4&gt;
  
  
  Lastly, adding a constructor
&lt;/h4&gt;

&lt;p&gt;In all the examples above I have been calling directly &lt;code&gt;Identity&lt;/code&gt;. Typically, however, there is a constructor method. In JS, the convention is to add an &lt;code&gt;of&lt;/code&gt; constructor. This looks like:&lt;/p&gt;



&lt;div class="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;one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This helps in a couple ways. One, &lt;code&gt;of()&lt;/code&gt; is a very strong hint we're dealing with a monad, as there's probably nowhere else you'll see it.&lt;/p&gt;

&lt;p&gt;Secondly, it'll allow you to do type-checking behaviour, should your monad have restrictions on what is passed into it.&lt;/p&gt;

&lt;p&gt;Typically I handle this using import/export, as such:&lt;/p&gt;



&lt;div class="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;Identity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;IdentityOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="na"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Identity(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// you might do type-checking here&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IdentityOf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exportIdentity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IdentityOf&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// or module.exports&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;exportIdentity&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// or require()&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Identity&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Identity.js`;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Enough examples from me, though. Time for you to give it a try.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Try it out: &lt;a href="https://repl.it/@rgeraldporter/Identity-Monad-Example"&gt;Identity Monad Example REPL&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's make another monad: &lt;code&gt;List&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;List&lt;/code&gt; is the typical name of an &lt;code&gt;Array&lt;/code&gt;-like monad.&lt;/p&gt;

&lt;p&gt;We'll start with our &lt;code&gt;Identity&lt;/code&gt;, but rename it.&lt;/p&gt;



&lt;div class="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;List&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="na"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`List(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;For the purposes of this example, we'll assume &lt;code&gt;of&lt;/code&gt; constructor has been added to this. When actually making one, we'd also type-check in the &lt;code&gt;of&lt;/code&gt; constructor to ensure the passed value is an &lt;code&gt;Array&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Adding more methods
&lt;/h4&gt;

&lt;p&gt;As you can see with the addition of &lt;code&gt;inspect&lt;/code&gt;, adding new methods is very easy. And if you write your own monad, why not add methods if you have a particular function you use with &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;chain&lt;/code&gt; a lot?&lt;/p&gt;

&lt;p&gt;In my experience, there are two kinds of methods you might add:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;map&lt;/code&gt;-like: methods that return back the same type of Monad&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chain&lt;/code&gt;-like: methods that either return a different kind of monad, or a non-monadic value; it may or may not "exit" the monad pattern, which I like to refer to as "unwrapping" the monad value&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Method: &lt;code&gt;concat&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Concatenation is a fairly simple concept from &lt;code&gt;Array&lt;/code&gt;: take one array, and add it onto the end of another. This seems like a method that would be very useful to have available.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;

&lt;span class="c1"&gt;// e.g.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;myNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nx"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; List(1,3,4,7,10,12);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The function is simple: make a new &lt;code&gt;List&lt;/code&gt; from using &lt;code&gt;Array.concat&lt;/code&gt; on the contained value and the incoming value.&lt;/p&gt;

&lt;p&gt;Note that this is &lt;code&gt;map&lt;/code&gt;-like; it returns a new &lt;code&gt;List&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Method: &lt;code&gt;head&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Let's say we wanted to just know what the first item in the &lt;code&gt;List&lt;/code&gt; is. It's not an &lt;code&gt;Array&lt;/code&gt; so using an index accessor like &lt;code&gt;[0]&lt;/code&gt; isn't going to work.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

&lt;span class="c1"&gt;// e.g.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;myNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This method is &lt;code&gt;chain&lt;/code&gt;-like, as it returns a non-monadic value -- in this case, unwrapping part of the value. This one exits the monad pattern, so be aware when using these kinds of methods that continuing to chain &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;emit&lt;/code&gt;, &lt;code&gt;inspect&lt;/code&gt;, etc will not work.&lt;/p&gt;



&lt;div class="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;myNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;myNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; ERROR! We unwrapped from the monad at `.head()`!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  More methods
&lt;/h4&gt;

&lt;p&gt;If you know &lt;code&gt;Array&lt;/code&gt; well, you know it has an awful lot of methods. You can build a &lt;code&gt;List&lt;/code&gt; with all kinds of things. &lt;/p&gt;

&lt;p&gt;So here's a good excercise -- take this basic &lt;code&gt;List&lt;/code&gt; monad and write some methods of your own!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Try it out: &lt;a href="https://repl.it/@rgeraldporter/List-Monad-Example"&gt;List Monad Example REPL&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;Maybe&lt;/code&gt;: the most powerful monad
&lt;/h2&gt;

&lt;p&gt;It's possible you've heard of &lt;code&gt;Maybe&lt;/code&gt; (also known as &lt;code&gt;Option&lt;/code&gt;): the oddly named, but incredibly useful and powerful monad pattern.&lt;/p&gt;

&lt;p&gt;The name "maybe" refers to the idea of "maybe there is a value... but maybe there is not".&lt;/p&gt;

&lt;p&gt;In JS, having values that are &lt;code&gt;undefined&lt;/code&gt; and &lt;code&gt;null&lt;/code&gt; can cause havoc in the wrong place. What if, in every case where we currently have to place an awkward &lt;code&gt;if (x === undefined || x === null)&lt;/code&gt; statement, we just could handle those cases right inside the value's container and never expose those unsightly and troublesome null values?&lt;/p&gt;

&lt;h3&gt;
  
  
  The code
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Here comes a lot of code. Don't worry, we'll go through it all.&lt;/em&gt;&lt;/p&gt;



&lt;div class="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;Just&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&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="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;MaybeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="na"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;isJust&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isNothing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Just(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&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="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Nothing&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Nothing&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Nothing&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;isJust&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isNothing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Nothing`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MaybeOf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isNothing&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Nothing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Just&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exportMaybe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MaybeOf&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;exportMaybe&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Use case
&lt;/h3&gt;

&lt;p&gt;To give an example where this would be useful, let's have system that reads a temperature in Fahrenheit and gives it out in Celsius.&lt;/p&gt;



&lt;div class="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;fahrenheitToCelsius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&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;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5556&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reading1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reading2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;temp1C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reading1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fahrenheitToCelsius&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;temp1C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; Just(-9.4444)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;temp2C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reading2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fahrenheitToCelsius&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;temp2C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; Nothing()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Right away we have a problem: for function &lt;code&gt;fahrenheitToCelsius&lt;/code&gt; to work, we need &lt;code&gt;a&lt;/code&gt; to be a number. Since &lt;code&gt;reading2&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt; (maybe a dead thermometer?), Javascript will cast &lt;code&gt;null&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt;, giving a constant false reading of &lt;code&gt;-17.7792&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, since we have encapsulated in a &lt;code&gt;Maybe&lt;/code&gt; monad we only have two possibilities: a real number (&lt;code&gt;Just&lt;/code&gt;, as in "just a value"), and no value at all (&lt;code&gt;Nothing&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Explanation
&lt;/h3&gt;

&lt;p&gt;How did this happen?&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;Maybe.of&lt;/code&gt; constructor did it:&lt;/p&gt;



&lt;div class="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;MaybeOf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isNothing&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Nothing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Just&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If the value being encapsulated in the monad was not &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, or already a &lt;code&gt;Nothing&lt;/code&gt;, then it is kept in &lt;code&gt;Just&lt;/code&gt;. While the name &lt;code&gt;Just&lt;/code&gt; may look new to you, its concept is almost identical with &lt;code&gt;Identity&lt;/code&gt;! So you pretty much know already how &lt;code&gt;Just&lt;/code&gt; works.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Nothing&lt;/code&gt; is a rather different monad than most: it doesn't take a value, and every method you use will result in &lt;code&gt;Nothing()&lt;/code&gt;. After a &lt;code&gt;Maybe&lt;/code&gt; has cast a value to &lt;code&gt;Nothing&lt;/code&gt; there's no going back -- all attempts to &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;chain&lt;/code&gt; just result in &lt;code&gt;Nothing&lt;/code&gt;, so you need not worry about functions having unexpected behaviours since they &lt;em&gt;never actually run&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Even &lt;code&gt;emit&lt;/code&gt; here returns &lt;code&gt;Nothing()&lt;/code&gt;, not &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. This is because I lied slightly earlier, our &lt;code&gt;emit&lt;/code&gt; method sometimes can't actually emit a value, especially if it has &lt;code&gt;Nothing()&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;But we need to handle what we do with &lt;code&gt;Nothing&lt;/code&gt;, eventually...&lt;/p&gt;

&lt;h3&gt;
  
  
  Method: &lt;code&gt;fork&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Here enters the prized method of the &lt;code&gt;Maybe&lt;/code&gt; monad given above: &lt;code&gt;fork&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;One quick side note: not all &lt;code&gt;Maybe&lt;/code&gt; monad implementations will have a &lt;code&gt;fork&lt;/code&gt;, but handle &lt;code&gt;Nothing&lt;/code&gt; in other ways. For this tutorial however, we'll be using it, because we can!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fork&lt;/code&gt; is a method in two places here: in &lt;code&gt;Just&lt;/code&gt; and &lt;code&gt;Nothing&lt;/code&gt;&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Just&lt;/span&gt;
&lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

&lt;span class="c1"&gt;// Nothing&lt;/span&gt;
&lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Right away you might see something odd. &lt;code&gt;_&lt;/code&gt; is a style choice often used in functional programming to indicate where we know there will be a value passed, but we plan not to use it. It is like the opposite of a placeholder.&lt;/p&gt;

&lt;p&gt;Now let's use it for temperature display:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// assume a `display` function to display the temperature reading, and act like console.log&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fahrenheitToCelsius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&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;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5556&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reading1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reading2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reading1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fahrenheitToCelsius&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERR!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°C`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// will read `-9.4452°C`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reading2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fahrenheitToCelsius&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERR!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// will read `ERR!`&lt;/span&gt;
        &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°C`&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;Note in this use case we're not even assigning the results of the &lt;code&gt;Maybe&lt;/code&gt; into a &lt;code&gt;const&lt;/code&gt; value, as in this example we just need to display it.&lt;/p&gt;

&lt;p&gt;But if we did need that string value to do something else...&lt;/p&gt;



&lt;div class="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;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&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;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fahrenheitToCelsius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&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;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5556&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reading1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;temp3C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Maybe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reading1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fahrenheitToCelsius&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERR!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°C`&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="nx"&gt;temp3C&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; "-9.4452°C"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This should be enough to get you started on using &lt;code&gt;Maybe&lt;/code&gt;. It's a very different way of thinking about values than one is usually taught in JS, and will likely take some time to fully grasp.&lt;/p&gt;

&lt;p&gt;What helps a lot with understanding the use of monads is practice! On your next small project, try adding in a &lt;code&gt;Maybe&lt;/code&gt; module (suggestion below), or write your own. Given enough time, you might not be able to imagine writing code in JS without it!&lt;/p&gt;

&lt;p&gt;For now, you can give &lt;code&gt;Maybe&lt;/code&gt; a spin in the following REPL.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Try it out: &lt;a href="https://repl.it/@rgeraldporter/Maybe-Monad-Example"&gt;Maybe Monad Example REPL&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A note about &lt;code&gt;emit&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;You may have noticed there's not really any examples of using &lt;code&gt;emit&lt;/code&gt; (aka &lt;code&gt;join&lt;/code&gt;) here. This is because "unwrapping" a monad is something you should actually completely avoid if possible, except when removing multiple layers of container monads.&lt;/p&gt;

&lt;p&gt;It's great for debugging, but when you &lt;code&gt;emit&lt;/code&gt; you'll need to realize you're leaving the safe world of monads, and into side-effects and mutability again.&lt;/p&gt;

&lt;p&gt;There are many monad libraries that don't even have this method, as it isn't technically necessary -- after all, &lt;code&gt;chain&lt;/code&gt; can achieve the same effect if it's fed a simple identity function.&lt;/p&gt;

&lt;p&gt;The best thing you can do, if possible, rather than using a monad to compute a value to return, is build the monad and pass it all the functions it needs to do what it needs to do.&lt;/p&gt;

&lt;p&gt;Don't worry if you can't figure out how to do that for every situation right now though. Just starting to use monads at all can be an exciting learning experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick review
&lt;/h2&gt;

&lt;p&gt;What has helped me the most over the years is to think of monads as a &lt;em&gt;container&lt;/em&gt;. That may help you, or to fall back to the dictionary defintion of &lt;em&gt;single unit&lt;/em&gt; may also be of help.&lt;/p&gt;

&lt;p&gt;Much like a bank ledger, monads keep their values immutible but allow methods to apply functions atop them to generate new monads, and thus new values.&lt;/p&gt;

&lt;p&gt;But do be aware, doing a web search to find solutions on monad problems you might encounter may be a bit challenging. A lot of documentation out there is deeply saturated with technical language you might not be familiar with. A lot of it even I'm not familiar with. Hopefully that will change as this powerful pattern is adopted more widely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monad modules you can use right now
&lt;/h2&gt;

&lt;p&gt;My own module, which is not very different from what has been demonstrated in this introduction is available as &lt;a href="https://www.npmjs.com/package/simple-maybe"&gt;simple-maybe on npm&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What next?
&lt;/h2&gt;

&lt;p&gt;Once you have grasped completely the concepts outlined in this introduction, other monads will mostly be just slight variations on the types of monad shown here.&lt;/p&gt;

&lt;p&gt;In the near future I'll be posting about some other monad modules I've been building, and how they are used, and constructed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope this article's approach has been accessible, even to those new to Javascript, and the code sufficiently expressive to not be a barrier to learning. Please feel free to leave suggestions for improvements or to share some other methods that have helped you better understand the use of monads.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>monads</category>
      <category>javascript</category>
      <category>functional</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Setting up RAID-Z for use in a MySQL Master-Master Replicator Pattern</title>
      <dc:creator>Rob Porter</dc:creator>
      <pubDate>Thu, 06 Jun 2019 13:05:28 +0000</pubDate>
      <link>https://dev.to/rgeraldporter/setting-up-raid-z-for-use-in-a-mysql-master-master-replicator-pattern-4eme</link>
      <guid>https://dev.to/rgeraldporter/setting-up-raid-z-for-use-in-a-mysql-master-master-replicator-pattern-4eme</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Notes&lt;/strong&gt;: I wrote this documentation around 2013 as internal documentation at &lt;a href="https://weeverapps.com/"&gt;Weever Apps&lt;/a&gt; for setting up RAID-Z as a method of making very quick backups of MySQL. Since we no longer use this setup and the documentation will never be used again, I felt it might be a good idea to post it out there for those who might find some use in it. Using RAID-Z for MySQL was amazing, and never failed us, and allowed hourly snapshot-based backups with no downtime. We've since moved to AWS RDS instances though.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This will be part of multiple posts that combined will allow one to build a RAID-Z setup for MySQL. Or, at least it used to be able to! While this is geared towards Azure, I'm sure it would work anywhere.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As I add more parts over the next few days I'll add links here.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Article series
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/installing-zfs-on-centos-2fkl"&gt;Installing ZFS on CentOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/creating-a-raid-z-drive-with-zfs-on-centos-3484"&gt;Creating a RAID-Z Drive for MySQL with ZFS on CentOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Setting up RAID-Z for use in a MySQL Master-Master Replicator Pattern&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/creating-a-zfs-image-of-a-mysql-data-directory-dad"&gt;Creating a ZFS Image of a MySQL Data Directory&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Additional note
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This documentation is a few years old and it uses the problematic "master/slave" terminology. Better terms have come up recently (my favourite is "master/minion"), but as this is legacy documentation I'm not sure if one can just drop in different terms without causing technical issues in the setup. Please leave a comment if you can confirm dropping the better terms in will work correctly!&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Instructions
&lt;/h1&gt;

&lt;p&gt;For MySQL to work on RAID-Z, we must be mounted on &lt;code&gt;/var/lib/mysql&lt;/code&gt;. Also, this mount point needs to be owned by mysql user so we need to do the following:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chown &lt;/span&gt;mysql.mysql /var/lib/mysql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then we'll want to create filesystem containers with this, which act like a directory but can be independently tracked by ZFS.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;zfs create sqlstorage/data
zfs create sqlstorage/log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Two more &lt;code&gt;chown&lt;/code&gt;s to do now..&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chown &lt;/span&gt;mysql.mysql /var/lib/mysql/data
&lt;span class="nb"&gt;chown &lt;/span&gt;mysql.mysql /var/lib/mysql/log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You must then edit &lt;code&gt;/etc/my.cnf&lt;/code&gt; to the following (change server-id depending on whether this is server 1 or 2 though, and auto_increment_offset):&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[mysqld]
max_connections=1000
datadir=/var/lib/mysql/data
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
max_allowed_packet=1024M
log_bin = /var/lib/mysql/log/mysql-bin.log
server-id = 1
# this will prevent master-master auto_increment collisions, set offset to server-id
auto_increment_increment = 10
auto_increment_offset = 1
[mysqld_safe]
log-error=/var/lib/mysql/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Set the server-id to the correct ID.&lt;/p&gt;

&lt;p&gt;You will then start up mysql for the first time, using&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;service mysqld start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next we'll make sure this boots up every time the machine reboots:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;/sbin/chkconfig mysqld &lt;span class="nt"&gt;--list&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; /sbin/chkconfig mysqld on
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then follow the instructions provided upon this first boot-up to assign a root password, typically:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;/usr/bin/mysqladmin &lt;span class="nt"&gt;-u&lt;/span&gt; root password &lt;span class="s1"&gt;'new-password'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then we'll be logging into mysql's terminal.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql &lt;span class="nt"&gt;-u&lt;/span&gt; root &lt;span class="nt"&gt;-p&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Enter the password.&lt;/p&gt;

&lt;p&gt;Then we'll create our replicator user, using this mysql command:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create user 'replicator'@'%' identified by 'password'; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Generate and replace 'password' with a password.&lt;/p&gt;

&lt;p&gt;Now give it permission to replicate:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grant replication slave on *.* to 'replicator'@'%';
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now run this and make note of what information it displays:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;show master status; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You will need the 'position' and 'file name' provided, and use this on Server #2.&lt;/p&gt;

&lt;p&gt;At this point, log into server #2, and repeat everything in this document up until this point.&lt;/p&gt;

&lt;h2&gt;
  
  
  On Server 2 only...
&lt;/h2&gt;

&lt;p&gt;Time to set up the replicator.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slave stop; 
CHANGE MASTER TO MASTER_HOST = '1.1.1.1', MASTER_USER = 'replicator', MASTER_PASSWORD = 'password', MASTER_LOG_FILE = 'mysql-bin.000003', MASTER_LOG_POS = 106; 
slave start; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;1.1.1.1&lt;/code&gt; is the internal IP address of server #1. Replace it with the correct Azure Internal IP. Also use the password and user created for server #1 'replicator', be sure not to mix it up with the replicator password for server #2. The master log file name and log position you should have noted before, replace it here with those values. Position is likely to be 106 though the filename can vary.&lt;/p&gt;

&lt;p&gt;Now once again we'll do:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;show master status;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And now on to server 1...&lt;/p&gt;

&lt;h2&gt;
  
  
  On Server 1 only...
&lt;/h2&gt;

&lt;p&gt;Go back into mysql as root user. Enter this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slave stop; 
CHANGE MASTER TO MASTER_HOST = '2.2.2.2', MASTER_USER = 'replicator', MASTER_PASSWORD = 'password', MASTER_LOG_FILE = 'mysql-bin.000004', MASTER_LOG_POS = 107; 
slave start; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now just create the database you put in &lt;code&gt;database_name_here&lt;/code&gt; in the &lt;code&gt;my.cnf&lt;/code&gt; and replication should be working.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Is something badly out of date? Did this work for you? Please post a comment to help others who might use this for guidance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>raidz</category>
    </item>
    <item>
      <title>How to do Security Updates only with Yum in CentOS</title>
      <dc:creator>Rob Porter</dc:creator>
      <pubDate>Wed, 05 Jun 2019 13:57:20 +0000</pubDate>
      <link>https://dev.to/rgeraldporter/how-to-do-security-updates-only-with-yum-in-centos-1db1</link>
      <guid>https://dev.to/rgeraldporter/how-to-do-security-updates-only-with-yum-in-centos-1db1</guid>
      <description>&lt;p&gt;This is a fairly basic "just the security updates, please!" guide for CentOS 6+.&lt;/p&gt;

&lt;p&gt;This assumes you're &lt;code&gt;root&lt;/code&gt; or have used &lt;code&gt;sudo su&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, you may need to ensure you have the yum security plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;rpm &lt;span class="nt"&gt;-qa&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; yum-plugin-security
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you don't, you can update it with the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;yum-plugin-security
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now let's check if there are updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;yum &lt;span class="nt"&gt;--security&lt;/span&gt; check-update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If there are available updates, there will be results after this command.&lt;/p&gt;

&lt;p&gt;To update, run the updater with the option &lt;code&gt;--security&lt;/code&gt; to specify security updates only.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;yum update &lt;span class="nt"&gt;--security&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Is something badly out of date? Did this work for you? Please post a comment to help others who might use this for guidance. I originally wrote these instructions around 2013.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>centos</category>
      <category>yum</category>
      <category>security</category>
    </item>
    <item>
      <title>Creating a RAID-Z Drive for MySQL with ZFS on CentOS</title>
      <dc:creator>Rob Porter</dc:creator>
      <pubDate>Wed, 05 Jun 2019 13:38:49 +0000</pubDate>
      <link>https://dev.to/rgeraldporter/creating-a-raid-z-drive-with-zfs-on-centos-3484</link>
      <guid>https://dev.to/rgeraldporter/creating-a-raid-z-drive-with-zfs-on-centos-3484</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Notes&lt;/strong&gt;: I wrote this documentation around 2013 as internal documentation at &lt;a href="https://weeverapps.com/"&gt;Weever Apps&lt;/a&gt; for setting up RAID-Z as a method of making very quick backups of MySQL. Since we no longer use this setup and the documentation will never be used again, I felt it might be a good idea to post it out there for those who might find some use in it. Using RAID-Z for MySQL was amazing, and never failed us, and allowed hourly snapshot-based backups with no downtime. We've since moved to AWS RDS instances though.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This will be part of multiple posts that combined will allow one to build a RAID-Z setup for MySQL. Or, at least it used to be able to! While this is geared towards Azure, I'm sure it would work anywhere.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As I add more parts over the next few days I'll add links here.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Article series
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/installing-zfs-on-centos-2fkl"&gt;Installing ZFS on CentOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creating a RAID-Z Drive for MySQL with ZFS on CentOS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/setting-up-raid-z-for-use-in-a-mysql-master-master-replicator-pattern-4eme"&gt;Setting up RAID-Z for use in a MySQL Master-Master Replicator Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/creating-a-zfs-image-of-a-mysql-data-directory-dad"&gt;Creating a ZFS Image of a MySQL Data Directory&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Instructions
&lt;/h1&gt;

&lt;p&gt;First, let's make sure we have ZFS installed.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su
lsmod | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; zfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, in Azure, shut down the server then attach all the disks you'd like to use for RAID-Z; minimum should be a 2-core machine using the max 4 disks. All disks should be the same size, though this may not be a requirement for RAID-Z.&lt;/p&gt;

&lt;p&gt;For this example, I'll be making 4 disks with 300 GB each. Give them names so it is clear that they are RAID-Z disks, by making sure raid-z is somewhere in the name.&lt;/p&gt;

&lt;p&gt;Each disk should take about a minute to set up.&lt;/p&gt;

&lt;p&gt;Start the machine up when the final disk is added.&lt;/p&gt;

&lt;p&gt;Once booted back up, check the status of the disks (be sure to &lt;code&gt;sudo su&lt;/code&gt;):&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;fdisk &lt;span class="nt"&gt;-l&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;GB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The following command will create a zpool called &lt;code&gt;sqlstorage&lt;/code&gt; and mount it to &lt;code&gt;/etc/mysql&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;zpool create &lt;span class="nt"&gt;-m&lt;/span&gt; /var/lib/mysql sqlstorage raidz &lt;span class="nt"&gt;-f&lt;/span&gt; sdc sdd sde sdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that the minimum for &lt;code&gt;raidz&lt;/code&gt; is two disks. For double-parity &lt;code&gt;raidz&lt;/code&gt; known as &lt;code&gt;raidz2&lt;/code&gt;, you need a minimum of 3 disks. For triple, 4 disks are required. Use the highest level RAID-Z possible with the setup.&lt;/p&gt;

&lt;p&gt;To check the zpool status:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;zpool status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To make sure it's mounted:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;mount | &lt;span class="nb"&gt;grep &lt;/span&gt;zfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And to confirm the storage size:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;sqlstorage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We also want to make sure the drive will mount on bootup:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"zfs mount sqlstorage"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/rc.local
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Reboot, and you can then repeat the above checks to ensure it is working on boot.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Is something badly out of date? Did this work for you? Please post a comment to help others who might use this for guidance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>zfs</category>
      <category>raidz</category>
      <category>centos</category>
      <category>mysql</category>
    </item>
    <item>
      <title>Installing ZFS on CentOS</title>
      <dc:creator>Rob Porter</dc:creator>
      <pubDate>Tue, 04 Jun 2019 13:44:34 +0000</pubDate>
      <link>https://dev.to/rgeraldporter/installing-zfs-on-centos-2fkl</link>
      <guid>https://dev.to/rgeraldporter/installing-zfs-on-centos-2fkl</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Notes&lt;/strong&gt;: I wrote this documentation around 2013 as internal documentation at &lt;a href="https://weeverapps.com/"&gt;Weever Apps&lt;/a&gt; for setting up RAID-Z as a method of making very quick backups of MySQL. Since we no longer use this setup and the documentation will never be used again, I felt it might be a good idea to post it out there for those who might find some use in it. Using RAID-Z for MySQL was amazing, and never failed us, and allowed hourly snapshot-based backups with no downtime. We've since moved to AWS RDS instances though.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This will be part of multiple posts that combined will allow one to build a RAID-Z setup for MySQL. Or, at least it used to be able to! While this is geared towards Azure, I'm sure it would work anywhere.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Article series
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Installing ZFS on CentOS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/creating-a-raid-z-drive-with-zfs-on-centos-3484"&gt;Creating a RAID-Z Drive for MySQL with ZFS on CentOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/setting-up-raid-z-for-use-in-a-mysql-master-master-replicator-pattern-4eme"&gt;Setting up RAID-Z for use in a MySQL Master-Master Replicator Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/rgeraldporter/creating-a-zfs-image-of-a-mysql-data-directory-dad"&gt;Creating a ZFS Image of a MySQL Data Directory&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;As I add more parts over the next few days I'll add links here.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating the VM
&lt;/h1&gt;

&lt;p&gt;First, create a VM in Azure using the CentOS image. It needs to be a minimum of 2 cores to be set up with RAID-Z.&lt;/p&gt;

&lt;p&gt;Make sure it is inside the Cloud Service of the application server VMs you wish to connect it to.&lt;/p&gt;

&lt;p&gt;User name for the initial user should be &lt;code&gt;azureadmin&lt;/code&gt;, but you should be sure to change the password and document it somewhere safe.&lt;/p&gt;

&lt;p&gt;If you wish to make use of Load Balancing, be sure to create an Availability Set when asked, or select one that it will be used with if we're adding another load balanced instance.&lt;/p&gt;

&lt;h1&gt;
  
  
  After logging in via SSH...
&lt;/h1&gt;

&lt;p&gt;First we need to be sudo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next we're going to need to get ZFS installed, which will require some set up. First, we need to disable SELinux for this to work, at least until ZFS software gets updated to support it (or visa versa). First command disables it for now, second disables it for good.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;0 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/selinux/enforce
vim /etc/selinux/config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And change &lt;code&gt;SELINUX=&lt;/code&gt; to &lt;code&gt;permissive&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next we need some new kernel libraries in yum so we need to edit the config file to remove kernel exceptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;vim /etc/yum.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Find the line with &lt;code&gt;exclude=kernel*&lt;/code&gt; and comment it out with a hash (&lt;code&gt;#&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Then we're going to install some stuff.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;yum groupinstall &lt;span class="s2"&gt;"Development Tools"&lt;/span&gt;
yum &lt;span class="nb"&gt;install &lt;/span&gt;kernel-devel zlib-devel libuuid-devel libblkid-devel libselinux-devel parted lsscsi nano mdadm bc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next go to &lt;a href="//zfsonlinux.org"&gt;zfsonlinux.org&lt;/a&gt; and click on CentOS link, which should have commands like these two:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum localinstall &lt;span class="nt"&gt;--nogpgcheck&lt;/span&gt; http://archive.zfsonlinux.org/epel/zfs-release-1-3.el6.noarch.rpm
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;zfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will take a few minutes.&lt;/p&gt;

&lt;p&gt;Now we'll load the module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;modprobe zfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To make sure it's there and working, we'll check using this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;lsmod | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; zfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's set it up so it'll load on boot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;vim /etc/sysconfig/modules/zfs.modules
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Paste into this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; /dev/zfs &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt; /sbin/modprobe zfs &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Save the file (:wq) and then we'll do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /etc/sysconfig/modules/zfs.modules
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's now test that it works, and reboot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then make sure we get output from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;lsmod | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; zfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If so, ZFS is installed!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Is something badly out of date? Did this work for you? Please post a comment to help others who might use this for guidance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>zfs</category>
      <category>centos</category>
      <category>azure</category>
    </item>
    <item>
      <title>Extracting Test Results from CucumberJs in Jenkins Pipeline Syntax</title>
      <dc:creator>Rob Porter</dc:creator>
      <pubDate>Tue, 04 Jun 2019 00:01:57 +0000</pubDate>
      <link>https://dev.to/rgeraldporter/extracting-test-results-from-cucumberjs-in-jenkins-pipeline-syntax-49h</link>
      <guid>https://dev.to/rgeraldporter/extracting-test-results-from-cucumberjs-in-jenkins-pipeline-syntax-49h</guid>
      <description>&lt;p&gt;Jenkins can be a powerful system for Continuous Integration (CI) services, allowing automation of complex tasks, such as running an end-to-end (E2E) test suite within a Dockerized environment.&lt;/p&gt;

&lt;p&gt;You don't automatically get useful data out of Jenkins jobs, however. Perhaps you want to take results from an E2E run and feed them into Slack, notify a monitor on a service like Datadog when there are test failures. You might also want to use the results to inform the successs/failure report of the Jenkins job itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assumptions
&lt;/h2&gt;

&lt;p&gt;This guide assumes you're using &lt;code&gt;cucumber-js&lt;/code&gt; (v5.1.0 as of this writing), and &lt;code&gt;cucumber-html-reporter&lt;/code&gt; (v5.0.0) in a Jenkins Pipeline job. If you are using another reporter, as long as you have a resulting file with data to extract, you may be able to use this guide with some adjustments.&lt;/p&gt;

&lt;p&gt;This was designed around an E2E solution that runs tests entirely in Docker, and concludes by using &lt;code&gt;docker cp&lt;/code&gt; to copy the resulting HTML report to the Jenkins job workspace.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;Jenkinsfile&lt;/code&gt; will be using the Jenkins &lt;a href="https://jenkins.io/doc/book/pipeline/syntax/#scripted-pipeline"&gt;Scripted Pipeline Syntax&lt;/a&gt;, which is built with Groovy. You won't need to know much about Groovy as it's similar enough to JS for what we're doing. Groovy is a (&lt;a href="https://stackoverflow.com/questions/4272068/is-groovy-syntax-an-exact-superset-of-java-syntax/4274542"&gt;sort of&lt;/a&gt;) superset of Java, and we're going to take advantage of that in this method.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method
&lt;/h2&gt;

&lt;p&gt;As our method for extraction, we're going to parse the HTML file that results, find the two lines that contain the pass and failure results, then use some light regex matching to hone in on those exact integers.&lt;/p&gt;

&lt;p&gt;This may seem a bit awkward, but parsing the raw &lt;code&gt;cucumber-report.json&lt;/code&gt; file would be far, far more work as we'd have to recalculate the results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;At the top of our &lt;code&gt;Jenkinsfile&lt;/code&gt; let's declare some variables we'll be using in this script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;groovy&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;e2ePassed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;e2eFailed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;e2eTotal&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;e2ePercent&lt;/span&gt;

&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Somewhere down the line, when our main task of running tests is complete, we'll be generating an artifact from the Cucumber JS HTML report.&lt;/p&gt;

&lt;p&gt;I've used comments below to document what each line is responsible for.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="cm"&gt;/*
     run test, copy the report file out of docker or where ever it is...
    */&lt;/span&gt;

    &lt;span class="n"&gt;archiveArtifacts&lt;/span&gt; &lt;span class="nl"&gt;artifacts:&lt;/span&gt; &lt;span class="s2"&gt;"cucumber_report.html"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;fingerprint:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="c1"&gt;// our Groovy script will be contained in this scope&lt;/span&gt;
    &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Extracting passed &amp;amp; failed values'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// get the present working directory (PWD)&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;PWD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pwd&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;// based on this, construct the path to the workspace&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;workspacePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PWD&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;substring&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PWD&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastIndexOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PWD&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;

        &lt;span class="c1"&gt;// read our HTML report into a String&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;readFile&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"${env.PWD}/workspace/${workspacePath}/cucumber_report.html"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// split each line break into its own String&lt;/span&gt;
        &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"\n"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// use regex to find the "passed" line and "failed" line&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;foundPassedLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;find&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="s"&gt;/\&amp;lt;span class="label label-success" title=scenarios\&amp;gt;/&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;foundFailedLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;find&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="s"&gt;/\&amp;lt;span class="label label-danger" title=scenarios\&amp;gt;/&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// match for the numeric values&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;passedMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foundPassedLine&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="s"&gt;/[0-9]+/&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;failedMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foundFailedLine&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="s"&gt;/[0-9]+/&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// cast to Integer so we can work with the number values&lt;/span&gt;
        &lt;span class="n"&gt;e2ePassed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;passedMatch&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Integer&lt;/span&gt;
        &lt;span class="n"&gt;e2eFailed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;failedMatch&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Integer&lt;/span&gt;
        &lt;span class="n"&gt;e2eTotal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e2eFailed&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e2ePassed&lt;/span&gt;
        &lt;span class="n"&gt;e2ePercent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e2ePassed&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;e2eTotal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e2eFailed&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// do something extra if there are failures&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// print out our results to the console&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Passed: ${e2ePassed}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Failed: ${e2eFailed}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;println&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Percent passes: ${e2ePercent}%"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// we can also access these values in an `sh` declaration (or other functions) outside of `script` now&lt;/span&gt;
    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"echo \"Passed: ${e2ePassed}\""&lt;/span&gt;
    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"echo \"Failed: ${e2eFailed}\""&lt;/span&gt;
    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"echo \"Percent passes: ${e2ePercent}%\""&lt;/span&gt;

    &lt;span class="c1"&gt;// you may opt to use the vars in plugins like `slackSend`, etc&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The security settings for up-to-date Jenkins setups will trigger an error upon using &lt;code&gt;readFile&lt;/code&gt; the first time. When this happens, go to &lt;code&gt;Manage Jenkins&lt;/code&gt; and &lt;code&gt;In-process Script Approval&lt;/code&gt;. You'll see a prompt to allow the readFile for use in the specific Jenkinsfile in all future job runs. You must be an admin to approve this.&lt;/p&gt;

&lt;p&gt;Once you have this data extracted from the reporter, you could use it notify external systems when there are failures, or to keep a running track of test pass/failure metrics.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://robporter.ca/jenkins-cucumber/"&gt;https://robporter.ca/jenkins-cucumber/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>jenkins</category>
      <category>cucumberjs</category>
      <category>e2e</category>
    </item>
  </channel>
</rss>
