{"componentChunkName":"component---src-templates-post-template-js","path":"/posts/elixir-atoms","result":{"data":{"markdownRemark":{"id":"e02ad01f-0306-5b5f-8314-c79dfde6af2d","html":"<p>Over the past few weeks, I’ve been reading up on the Elixir programming language. It’s focus on concurrency, scalability, fault-tolerance, and the developer experience are all very intriguing to me.</p>\n<p><a href=\"https://elixir-lang.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 192px;\"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAADLklEQVQ4y42U7U+TZxTG+3f4ZV/8osk+aBYzzaJuvkCMGFKmrLhBaS200qJiKQVdXyzQIiBEQDsJoKjgCzQwRREZoFijuPgW2MQXDCMkOiUIOLLWlp+09WE89CHzJHfuPM85uXKd6zr3kSERMzMz4TsYDM59vx55KyTn8lIhWxwsck+MTXHc0sBvnttz+c8GFIrD5xOgRXmEhGU6GqpaCHwI/C+oTIpdIBBp1dvRx3dLdiD/UkOhoZKxV+ORuuBnAAoF/4EGOLDLSczSH9iy9Cf2bLPxvH84IkcgKKpdFDB0BCMe/z5A8kY98SuVbPpCgXpdNve9/VEtLwSVbNnn89H4i4ed32rZ/vUu4pan8P2KNEpMboYGh0WmLdRTttCMUDx7MoQ9vZTUWAOKb9KRr1Sh3pxF0mo9VfY6gjNBSZkkNZyafE/npR7SNuagis0kZUMENDMxD+3WHNQb9tPh6RFGMgp0jqGg3dOBF9SVN6JYlUHSWi2aLfvRxO3FpLKRtdOKIeEAWYk2rlzoFDkeBSjMXWdrL5WOWhRrdMSvUKKO2Ue2yoLFUMBBXSEmpZ1DhiNo40x4r/eJXBcBCtFwrIUKew3p24zIv1Ly43odtn1OXHlluMxlWPVOSnKryEqyYEp28M/UtHTLofD7/NQUnQu7GWISclmxXkNOmpW6qtMcLXRTkF2KNcOFWeWYZWnkcd8fIpayhS/EbT+LQ1fOz+lF7JabSFiTgjpOT77xcBjMmGohJ/UQBzUudsebeXR3QBpQ0PByfTf52gpylc7ZlvLRyY2otupnQQ2YUm2Y1Q5yVQVYtcUUmSp4Pfq3aDNFuTz48CVny1updjZQlneC6sNnMGvsZCQa2ZucizXTSXVpPU31rbQ1X8Pv90drOP/Hv9M+Lp3sorm6navnu2Zn8gaXm65SWeym3FVBiaOMC6cv4mls4c/+QRG7KA2F5/Tqrzc0udtprbtO169eetpv0d1xg1MnzlB77BTN5zz0dt8SLeBFGQpajr+ZoLftHg+8Azy8009X203u3b7P0POXjI6MstiWito285mG4v3kNO/GJhl/+y680qSWyfw5/gjgiFlwxnZ4MAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <picture>\n        <source\n          srcset=\"/static/d9a8b275b31d69f59830dfd4593c8a6f/3e828/elixir.webp 192w\"\n          sizes=\"(max-width: 192px) 100vw, 192px\"\n          type=\"image/webp\"\n        />\n        <source\n          srcset=\"/static/d9a8b275b31d69f59830dfd4593c8a6f/8514f/elixir.png 192w\"\n          sizes=\"(max-width: 192px) 100vw, 192px\"\n          type=\"image/png\"\n        />\n        <img\n          class=\"gatsby-resp-image-image\"\n          src=\"/static/d9a8b275b31d69f59830dfd4593c8a6f/8514f/elixir.png\"\n          alt=\"Elixir logo\"\n          title=\"Elixir logo\"\n          loading=\"lazy\"\n        />\n      </picture>\n    </span></a></p>\n<p>However, I’m coming from the idiosyncratic world of JavaScript (and the notably more sane world of TypeScript), so some fundamental Elixir concepts are new to me.</p>\n<p>One such example is Elixir “atoms”, which often seem to be used in place of strings for things like flags and object property names.</p>\n<h2 id=\"example\"><a href=\"#example\" aria-label=\"example permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Example</h2>\n<p>Consider this Elixir code, which uses two atoms in a single line, to create a file and verify the operation:</p>\n<div class=\"gatsby-highlight\" data-language=\"elixir\"><pre class=\"language-elixir\"><code class=\"language-elixir\">iex<span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span> <span class=\"token punctuation\">{</span><span class=\"token atom symbol\">:ok</span><span class=\"token punctuation\">,</span> file<span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> File<span class=\"token punctuation\">.</span>open<span class=\"token punctuation\">(</span><span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token atom symbol\">:write</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>NodeJS, by contrast, <a href=\"https://nodejs.org/api/fs.html#fs_file_system_flags\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">implements file system flags as strings</a>, so the JavaScript code uses strings:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> file <span class=\"token operator\">=</span> fs<span class=\"token punctuation\">.</span><span class=\"token function\">openSync</span><span class=\"token punctuation\">(</span><span class=\"token string\">'hello'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'w'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>(This example also illustrates the difference in error handling philosophies between Elixir and JavaScript. Elixir methods idiomatically return an <code class=\"language-text\">{:error, :reason}</code> tuple on errors, while JavaScript typically relies on thrown Exception objects and try/catch constructs.)</p>\n<h2 id=\"so-what-actually-is-an-atom\"><a href=\"#so-what-actually-is-an-atom\" aria-label=\"so what actually is an atom permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>So what actually is an atom?</h2>\n<p>According to the <a href=\"https://elixir-lang.org/getting-started/basic-types.html#atoms\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Elixir documentation</a>:</p>\n<blockquote>\n<p>“An atom is a constant whose value is its own name. Some other languages call these symbols.”</p>\n</blockquote>\n<p>Symbols, eh? Symbols in JavaScript aren’t nearly as prominent as atoms in Elixir. Are they really the same thing? If not, how are they different?</p>\n<h2 id=\"javascript-symbols\"><a href=\"#javascript-symbols\" aria-label=\"javascript symbols permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>JavaScript Symbols</h2>\n<p>In JavaScript, symbols are primitives introduced in <a href=\"https://www.ecma-international.org/ecma-262/6.0/#sec-symbol-objects\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ES6</a>.</p>\n<p>A fundamental property of JavaScript symbols is that they’re always unique objects, even when constructed with the same input.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token operator\">></span> <span class=\"token function\">Symbol</span><span class=\"token punctuation\">(</span><span class=\"token string\">'MySymbol'</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token function\">Symbol</span><span class=\"token punctuation\">(</span><span class=\"token string\">'MySymbol'</span><span class=\"token punctuation\">)</span>\n<span class=\"token boolean\">false</span></code></pre></div>\n<p>So why would you want a data type with this characteristic?</p>\n<ol>\n<li>Preventing property name collision on objects. Libraries that share a reference to some object can attach their own symbols to it with no risk of conflict, unlike string keys.</li>\n<li>\n<p>Flag values. In our file-writing example, instead of indicating file modes with strings such as <code class=\"language-text\">&#39;w&#39;</code>, the filesystem module could certainly be implemented using <code class=\"language-text\">Symbol(&#39;w&#39;)</code>.</p>\n<p>I would actually argue that using symbols in this case is preferable. Unlike strings, the symbols must be retrieved from the object in question, in order to match the flag the object is checking against internally. This forces callers to be more intentional in how they invoke the function.</p>\n</li>\n<li>\n<p>Metaprogramming and reflection, which are more advanced use cases. The <code class=\"language-text\">Symbol</code> global has <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Well-known_symbols\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">“well-known” symbols</a> attached to it, which are referred to by the runtime itself while executing constructs like <code class=\"language-text\">for of</code> loops and spread operators.</p>\n<p>By using these well-known symbols in custom data types, developers can write third party data types that have first class support for these language constructs.</p>\n</li>\n</ol>\n<h2 id=\"elixir-atoms\"><a href=\"#elixir-atoms\" aria-label=\"elixir atoms permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Elixir Atoms</h2>\n<p>In Elixir, there’s one big, overarching reason for the widespread use of atoms instead of strings: their implementation allows for very efficient equality comparisons.</p>\n<p>This is because atoms with the same name are stored at the same memory address. This means that, when comparing atoms, the memory address can be compared directly without consulting the string representation and doing a character-by-character check.</p>\n<p>In algorithmic notation, the atom equality can be checked in constant O(<em>1</em>) time. String equality, on the other hand, is linear O(<em>n</em>) where <em>n</em> is the length of the shorter string.</p>\n<p>Because atoms with the same name are stored in the same memory address, unlike JavaScript Symbols, atoms with the same name <em>are</em> considered equal to one another.</p>\n<div class=\"gatsby-highlight\" data-language=\"elixir\"><pre class=\"language-elixir\"><code class=\"language-elixir\">iex<span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token operator\">></span> <span class=\"token atom symbol\">:MySymbol</span> <span class=\"token operator\">==</span> <span class=\"token atom symbol\">:MySymbol</span>\n<span class=\"token boolean\">true</span></code></pre></div>\n<h2 id=\"so-theyre-different\"><a href=\"#so-theyre-different\" aria-label=\"so theyre different permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>So they’re different!</h2>\n<p>Definitely. Very different.</p>\n<p>In Elixir, all atoms with the same name are equal and, under the hood, share a reference. This is completely different from JavaScript, where symbols are only equal if they’ve been explicitly assigned to the same reference by the developer.</p>\n<p>As this post has shown, the use cases for each are largely orthogonal.</p>\n<p>There happens to be some interesting overlap, though: both Elixir atoms and JavaScript symbols can be used to implement flag constants. However, this commonality is coincidental.</p>\n<p>In Elixir, atoms flags make sense for performance reasons, whereas, in JavaScript, symbol flags are beneficial because they impose intentionality in calling code (which is a much more subtle point).</p>\n<p>I imagine the subtlety in the JavaScript use case is why string flags are still idiomatic despite the availability of symbols.</p>\n<h2 id=\"conclusion\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>While the Elixir documentation on atoms says <em>“Some other languages call these symbols”</em>, we’ve learned that JavaScript is not one of those languages.</p>\n<p>Considering the influence of Ruby on Elixir, I imagine the documentation is referring to Ruby-like languages.</p>\n<p><em>Disclaimer: I’m still learning Elixir, so if anything in this post is inaccurate, I’d appreciate corrections at <a href=\"mailto:jonmellman@gmail.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">jonmellman@gmail.com</a>.</em></p>","fields":{"slug":"/posts/elixir-atoms","tagSlugs":["/tag/elixir/","/tag/code/"]},"frontmatter":{"date":"2019-10-07T21:49:58.849Z","description":"What are Elixir \"atoms\", and how are they different from JavaScript Symbols?","tags":["Elixir","Code"],"title":"Elixir Atoms vs JavaScript Symbols"}}},"pageContext":{"slug":"/posts/elixir-atoms"}},"staticQueryHashes":["251939775","401334301","4025097228"]}