<?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: Tracy Lum</title>
    <description>The latest articles on DEV Community by Tracy Lum (@talum).</description>
    <link>https://dev.to/talum</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%2F46842%2F2c6958e0-cc15-470a-98a4-264e0610f161.jpeg</url>
      <title>DEV Community: Tracy Lum</title>
      <link>https://dev.to/talum</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/talum"/>
    <language>en</language>
    <item>
      <title>How to Convince Yourself to Use Test-Driven Development</title>
      <dc:creator>Tracy Lum</dc:creator>
      <pubDate>Sat, 04 Apr 2020 18:36:34 +0000</pubDate>
      <link>https://dev.to/talum/how-to-convince-yourself-to-use-test-driven-development-3fgg</link>
      <guid>https://dev.to/talum/how-to-convince-yourself-to-use-test-driven-development-3fgg</guid>
      <description>&lt;p&gt;There comes a time in every developer's career when they must ask themselves if they want to write a test before they write the actual code.&lt;/p&gt;

&lt;p&gt;That time came for me probably around two years ago, and now that I (pretty) consistently practice test-driven development, or TDD, I've (almost) never looked back.&lt;/p&gt;

&lt;p&gt;Prior to writing tests, as a new developer, I coded with abandon, furiously typing and stuffing code into places it didn't really belong just to make a feature work. I thought that tests held me back from making real progress. They slowed me down and prevented me from shipping as fast as possible.&lt;/p&gt;

&lt;p&gt;In reality, there existed the minor problem that I didn't really know how to write tests, and learning an entirely new skill under a tight deadline didn't seem feasible. So I didn't write tests for probably the entire first year of my career as a professional developer. But had I invested some time in learning testing, I would have saved myself a lot of hassle and heartache.&lt;/p&gt;

&lt;p&gt;Some people make the case that writing tests is a waste of time, and in some startup environments, where cash is strapped and time is running out to deliver a viable product, that may be true. The best-tested code that doesn't deliver value is indeed useless to the business.&lt;/p&gt;

&lt;p&gt;But for the rest of us, who work at slightly more stable companies with growing businesses and feature sets, tests are actually an invaluable part of the feature development cycle.&lt;/p&gt;

&lt;p&gt;I can preach all day about the benefits of testing—how it documents working code, how it communicates intent to your team, how it saves you from yourself, how it allows you to refactor safely, how it sets juniors and seniors apart—but you probably won't believe me until you experience the magic of testing for yourself.&lt;/p&gt;

&lt;p&gt;If you still need convincing that TDD, or really writing any tests, is essential to your workflow, read on for tips on how to convince yourself to practice TDD.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feel the pain
&lt;/h2&gt;

&lt;p&gt;I'm not joking about this one. To see the benefits of testing, all you need to do is step into a particularly gnarly codebase, change one line of spaghetti code, then watch unexpected bugs appear from out of nowhere. To truly understand why testing is beneficial, you do actually need to mess up for yourself a few times. No amount of anyone preaching to you that "testing is good" will convince you otherwise. And when you're tired of feeling the pain, you'll be able to explore some solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn about testing and refactoring
&lt;/h2&gt;

&lt;p&gt;I (unfortunately) am still no expert on testing, but I still get by with TDD. A few books helped me change my mind on the necessity of testing and specifically how writing tests for how certain classes or components can allow you to refactor safely your existing code. &lt;a href="https://www.sandimetz.com/99bottles"&gt;99 Bottles&lt;/a&gt; by Sandi Metz and Katrina Owen and &lt;a href="https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052"&gt;Working Effectively with Legacy Code&lt;/a&gt; by Michael C. Feathers are two books that I recommend to change your mind. You can also learn about design patterns if you really want to take your coding abilities to the next level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continue working in an ever-changing codebase
&lt;/h2&gt;

&lt;p&gt;Even intellectually understanding why testing is beneficial won't alone change your mind about testing. As you continue to work in an ever-changing codebase, you may come to realize that you're making a lot of changes and praying. Hope does not inspire a lot of confidence in software development.&lt;/p&gt;

&lt;p&gt;And let's face it, writing code is hard enough. Reading other people's code and trying to work with it is even harder. So do yourself a favor and write some tests. This way, you can be more certain that the changes you make are what you intended. Writing tests takes much of the guesswork out of your changes, which saves you time and ultimately makes you more productive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Just add a test file
&lt;/h2&gt;

&lt;p&gt;Take a baby step and just add a test file with a single simple test to get yourself over the hump. For me at least, the greatest barrier to entry is writing the first test (there's &lt;em&gt;so much setup&lt;/em&gt;, &lt;em&gt;so much boilerplate&lt;/em&gt;, I think to myself). Once a test file is established and even a single test is written, it becomes so much easier to build upon it. I usually write something like "it returns true" just to warm up, and then just that act removes the mental block I established, freeing me up to get into the more complex parts of the business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try writing descriptive tests first
&lt;/h2&gt;

&lt;p&gt;If you aren't sure of the interface you want just yet, try writing descriptive tests first. That is, write the code you want, then write the test. Getting into the habit of writing a test is better than writing no test at all. (Truthfully, I have never regretted writing a test, not even once that I later deleted because I learned more about the expected behavior and results.)&lt;/p&gt;

&lt;p&gt;With descriptive tests, you might miss a couple edge cases, but hey, you do need a starting point. Writing tests allows you to write garbage code first and later refactor, guaranteeing that you don't change behavior while you're changing code. It's sort of like writing an essay and just getting a bunch of brainstorming nonsense out before you edit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactor
&lt;/h2&gt;

&lt;p&gt;Once you've written your tests, you can begin refactoring and see what pleasure the ability to change code confidently brings. No more guessing. No more praying. Just sweet peace of mind. Plus, with confidence comes saved dev cycles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start doing TDD
&lt;/h2&gt;

&lt;p&gt;After you're used to writing tests, try writing them first, before you've written the code to make them pass. I like to write out all the cases I know about and then I build upon them as new ones are discovered or use cases change. Then I refactor to my heart's content, never straying too far into red and always committing on green. Soon it will become habit and you'll feel gross &lt;em&gt;not&lt;/em&gt; writing the tests first. At least I do. I get nervous every time I write code without a corresponding test, so I basically test everything I can within reason. I typically stick to testing public-facing methods, but if I'm dealing with time or money, two notorious sources of bugs, I'll even test private methods to make sure I get the logic right. Tests have saved my life so many times that I've actually lost count.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spread the word
&lt;/h2&gt;

&lt;p&gt;After you've seen the magic of TDD, I bet you'll want to spread the word, too. TDD is super fun, especially when combined with ping-pong pairing. It documents your code, helps you organize, and also lets you refactor until you're happy, which may or may not mean you've achieved elegant code, but no matter—getting your code under test gives you the ability to achieve elegance one day, and for now, practically speaking, that is probably good enough.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>testdrivendevelopment</category>
    </item>
    <item>
      <title>Fixing Random, Intermittent, and Flaky RSpec Test Failures</title>
      <dc:creator>Tracy Lum</dc:creator>
      <pubDate>Mon, 05 Nov 2018 14:53:53 +0000</pubDate>
      <link>https://dev.to/talum/fixing-random-intermittent-and-flaky-rspec-test-failures-56c1</link>
      <guid>https://dev.to/talum/fixing-random-intermittent-and-flaky-rspec-test-failures-56c1</guid>
      <description>&lt;p&gt;In my view, there's almost nothing more annoying than a randomly failing, intermittent, flaky test failure. Run the test suite locally and everything passes. Run it on a CI service, and your build fails! A single red! 🔴 Rebuild it again, and somehow, magically, it goes green.&lt;/p&gt;

&lt;p&gt;A flaky or flickering test can create space for lots of noise and uncertainty. False negatives can delay deploys and shipping features. 🚢 An expected red failure may encourage developers to ignore true negatives and merge to master and deploy anyway.&lt;/p&gt;

&lt;p&gt;Such was the general atmosphere on my team recently. Nondeterministic specs kept cropping up every few builds, eventually creeping up to about 50% of our builds on the master branch. And on a growing team, with looming launch dates, no one felt empowered enough to solve the flaky test issue. After all, hunting down a nondeterministic bug could take days, weeks, or more.&lt;/p&gt;

&lt;p&gt;We kept saying we'd address it soon, but with our ops team working on a new deployment strategy that relies on passing builds, we finally prioritized&lt;br&gt;
it. And I was the lucky individual selected to track it down.&lt;/p&gt;

&lt;p&gt;This is the story of how I resolved this particular set of flaky test failures.&lt;/p&gt;
&lt;h2&gt;
  
  
  Unexpected Failures 😕
&lt;/h2&gt;

&lt;p&gt;For the past few months, I've been making a lot of backend, systemic, and wide-reaching changes to my team's codebase to support a migration to GitHub Enterprise. And I mean the entire codebase, from our main Rails monolith, to our open-source gems, to our IDE, and to our chat service. That work warrants its own post, so for now, suffice it to say that our platform is deeply integrated with GitHub, depending on it for everything from avatars and usernames to hosting our lesson content.&lt;/p&gt;

&lt;p&gt;Anyway, in order to decouple our platform from GitHub, my squad and I set out to introduce the concept of a &lt;code&gt;LearnAccount&lt;/code&gt; separate from a &lt;code&gt;GithubAccount&lt;/code&gt;, which keeps track of a Learn-specific identity and a GitHub-specific identity, respectively.&lt;/p&gt;

&lt;p&gt;Being the responsible team members we are, we replaced every method call&lt;br&gt;
meticulously and backed up our changes with specs. For the new &lt;code&gt;LearnAccount&lt;/code&gt; model, which &lt;code&gt;belongs_to&lt;/code&gt; a &lt;code&gt;User&lt;/code&gt; model, we created a factory using &lt;a href="https://github.com/thoughtbot/factory_bot_rails"&gt;Thoughtbot's Factory Bot&lt;/a&gt;. And we use the &lt;a href="https://github.com/stympy/faker"&gt;Faker&lt;/a&gt; gem to create reasonably realistic and random test data to work with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:learn_account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="no"&gt;Identities&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;LearnAccount&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Lorem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;word&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;     &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The new factory for the &lt;code&gt;GithubAccount&lt;/code&gt; was essentially the same.&lt;/p&gt;

&lt;p&gt;We also added a trait to our &lt;code&gt;Users&lt;/code&gt; factory so that we could selectively create &lt;code&gt;learn_account&lt;/code&gt;s for the &lt;code&gt;user&lt;/code&gt;s we create in our tests. We definitely didn't want to persist more records than necessary, which could slow down our test suite.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Internet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;trait&lt;/span&gt; &lt;span class="ss"&gt;:with_learn_account&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_learn_account&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This all seemed fine. We launched the new feature, removed the old code, and then the test suite began to fail occasionally. The most common test failures would look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;Api&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;V1&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UsersController&lt;/span&gt; &lt;span class="no"&gt;Switch&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="no"&gt;POST&lt;/span&gt; &lt;span class="c1"&gt;#switch_active_track given track within students current active batch updates the current track&lt;/span&gt;
&lt;span class="no"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;learn_account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;username&lt;/span&gt;
     &lt;span class="no"&gt;NoMethodError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="n"&gt;undefined&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="sb"&gt;`username' for nil:NilClass
     # ./app/models/user.rb:185:in `&lt;/span&gt;&lt;span class="n"&gt;learn_username&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;Api&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;V1&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;StudyGroupsController&lt;/span&gt; &lt;span class="no"&gt;PUT&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;rsvp_update&lt;/span&gt; &lt;span class="n"&gt;rsvped&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
     &lt;span class="no"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;learn_account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;username&lt;/span&gt;
     &lt;span class="no"&gt;NoMethodError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="n"&gt;undefined&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="sb"&gt;`username' for nil:NilClass
     # ./app/models/user.rb:185:in `&lt;/span&gt;&lt;span class="n"&gt;learn_username&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="no"&gt;CoursesController&lt;/span&gt; &lt;span class="no"&gt;GET&lt;/span&gt; &lt;span class="n"&gt;courses&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="ss"&gt;:course_slug&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="n"&gt;already&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt; &lt;span class="n"&gt;credentials&lt;/span&gt; &lt;span class="n"&gt;redirects&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;sign&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;stores&lt;/span&gt; &lt;span class="n"&gt;slug&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;
     &lt;span class="no"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:course_slug&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;course_slug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="ss"&gt;expected: &lt;/span&gt;&lt;span class="s2"&gt;"batch-123"&lt;/span&gt;
            &lt;span class="ss"&gt;got: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It was often different tests from different domains in our codebase, but the error would always look similar to one of the above test failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproducibility 🤷🏻‍
&lt;/h2&gt;

&lt;p&gt;The first issue I encountered was trying to reproduce the failing specs. I kept re-running the specs locally, and they simply wouldn't fail. I did this over and over again, and began to fear for my sanity. And yet, on CircleCI, builds kept failing. I'd re-run those as well, and sometimes they'd fail, and sometimes they'd pass. I looked a bit into the various Circle configs, wondering if some misconfiguration was causing tests not to clean up after themselves. I also searched our local &lt;code&gt;rspec&lt;/code&gt; configs just in case, but came up empty.&lt;/p&gt;

&lt;p&gt;Then I scoured the other internet literature, looking for other strategies to solve flaky tests. Among the most helpful posts were the instructive ones on how to use RSpec's &lt;code&gt;bisect&lt;/code&gt; flag. When used along with RSpec's &lt;code&gt;--seed&lt;/code&gt; flag, the &lt;code&gt;bisect&lt;/code&gt; option would "run subsets of your suite in order to isolate the minimal set of examples that reproduce the same failures," according to the &lt;a href="https://relishapp.com/rspec/rspec-core/docs/command-line/bisect"&gt;RSpec docs&lt;/a&gt;. This allows you to identify order-dependent test failures. Meanwhile, the &lt;code&gt;seed&lt;/code&gt; option allows you to randomize the specs to run in the same order. You'll need to use both flags to make this work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rspec&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bisect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This wasn't the final solution, however. The first few times I ran this on a single test file, the failing tests would not make themselves known. I knew in my mind that if I could just get one to fail consistently, I'd solve the rest. But finally, I was able to reproduce the failing spec with the command above. And with that minimal reproduction command, I was able to get deterministic test runs and further isolate the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix 🛠️
&lt;/h2&gt;

&lt;p&gt;With reproducibility, I could look closer at the code and identify the issue. Because it wasn't the same test failing all the time, I realized that the problem wasn't with the tests themselves, &lt;em&gt;but with the data setup&lt;/em&gt;. &lt;code&gt;Usernames&lt;/code&gt; for our &lt;code&gt;LearnAccount&lt;/code&gt;s and &lt;code&gt;GithubAccount&lt;/code&gt;s must be unique, but our factories weren't always generating unique values, which resulted in the &lt;code&gt;LearnAccount&lt;/code&gt; and &lt;code&gt;GithubAccount&lt;/code&gt; associated with a &lt;code&gt;User&lt;/code&gt; failing to be persisted in the database because they weren't valid. That explained why the &lt;code&gt;learn_account&lt;/code&gt; and &lt;code&gt;github_account&lt;/code&gt; was sometimes &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In fact, we were using the &lt;code&gt;Faker&lt;/code&gt; gem to generate values that approximated real values, specifically &lt;code&gt;Faker::Lorem::Word&lt;/code&gt;. There are only 249 values in that collection of words, so there is a non-trivial chance of collision. (Yes, there's a supplemental collection of values, but more words still doesn't guarantee uniqueness.) &lt;/p&gt;

&lt;p&gt;So, the fix was to ensure that the generated usernames in the tests would always be unique, and I did that by using &lt;a href="https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md"&gt;Factory Bot's Sequences&lt;/a&gt; to append a unique integer to the end of a generated value.&lt;/p&gt;

&lt;p&gt;Our factories now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="ss"&gt;:learn_account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="no"&gt;Identities&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;LearnAccount&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;sequence&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Lorem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;word&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;     &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I ran the test suite locally and on Circle a few dozen times more, all with passing builds, merged this change in, and celebrated by blocking all future merges to master without a passing test suite. Just kidding, I also alerted our team via Slack and scattered a bunch of fingers-crossed emojis everywhere. 🎉🤞🏼So far, so good. All greens ✅.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Lessons Learned 🗝️
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;It's important to tackle random test failures the moment they're introduced.&lt;/li&gt;
&lt;li&gt;RSpec &lt;code&gt;--seed&lt;/code&gt; and &lt;code&gt;--bisect&lt;/code&gt; can help you isolate the problem.&lt;/li&gt;
&lt;li&gt;Sometimes it's not the test, but the data backing the test. i.e. Don't rely on &lt;code&gt;Faker&lt;/code&gt; to generate unique values.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(Bonus Lesson) I'm getting way too into emojis. 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://engineering.gusto.com/eliminating-flaky-ruby-tests/"&gt;Eliminating Flaky Ruby Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sourcediving.com/a-better-way-to-tame-your-randomly-failing-specs-29040dc0ed24"&gt;A Better Way to Tame Your Randomly Failing Specs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://relishapp.com/rspec/rspec-core/docs/command-line/bisect"&gt;RSpec Bisect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.arkency.com/2016/02/how-rspec-helped-me-with-resolving-random-spec-failures/"&gt;How RSpec helped me with resolving random spec failures&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>rspec</category>
      <category>factorybot</category>
      <category>faker</category>
    </item>
    <item>
      <title>Which Data Structure Should I Use? An Elixir Cheat Sheet</title>
      <dc:creator>Tracy Lum</dc:creator>
      <pubDate>Sun, 02 Sep 2018 01:59:07 +0000</pubDate>
      <link>https://dev.to/talum/which-data-structure-should-i-use-an-elixir-cheat-sheet-3epe</link>
      <guid>https://dev.to/talum/which-data-structure-should-i-use-an-elixir-cheat-sheet-3epe</guid>
      <description>&lt;p&gt;As an Elixir novice, I think one of the hardest things about getting started in Elixir is figuring out what kind of data structures to use. My team has recently started going all in on Elixir, so I've been trying to brush up in earnest. Often, however, I'll be reading over some of my team's code and have a hard time deciphering what I'm even looking at. The syntax looks very similar to Ruby (which I know pretty well), but the patterns, conventions, and data structures are just &lt;em&gt;slightly&lt;/em&gt; different. In my mind, that makes sense since it's a functional rather than object-oriented language: where you would use objects in Ruby, you're probably spawning processes instead in Elixir.&lt;/p&gt;

&lt;p&gt;But anyway, since I'm learning Elixir now, I thought it'd be useful to provide a cheat sheet or overview of the differences in data structures I've noticed as a Rubyist exploring Elixir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Types
&lt;/h2&gt;

&lt;p&gt;If you're coming from Ruby (or most other programming languages), integers, floating-point numbers, ranges, and regular expressions are all probably familiar to you. Fortunately, those all exist in Elixir too. There are a few differences, but I haven't dealt too much with them yet.&lt;/p&gt;

&lt;p&gt;Atoms are like symbols in Ruby. They begin with colons and their names are their values. For example, &lt;code&gt;:hello&lt;/code&gt; is a valid atom in Elixir. They're often used to tag values.&lt;/p&gt;

&lt;p&gt;There are also strings in Elixir. Strings always have double quotation marks, while charlists are in single quotations marks. Strings are binaries, and charlists are actually just lists of code points. I have rarely used charlists so far.&lt;/p&gt;

&lt;p&gt;Here's a quick glance at what those types look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;         &lt;span class="c1"&gt;# integer&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;       &lt;span class="c1"&gt;# floating point&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;     &lt;span class="c1"&gt;# boolean&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;      &lt;span class="c1"&gt;# range&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="sr"&gt;~r/hello/&lt;/span&gt; &lt;span class="c1"&gt;# regular expression&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:hello&lt;/span&gt;    &lt;span class="c1"&gt;# atom&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;   &lt;span class="c1"&gt;# string&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'world'&lt;/span&gt;   &lt;span class="c1"&gt;# charlist&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Elixir has the additional data types, &lt;code&gt;Port&lt;/code&gt; and &lt;code&gt;PID&lt;/code&gt;, which are used in process communication. They are entities that are made available through the Erlang VM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Port
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;Port&lt;/code&gt; is used to communicate (read/write) to resources outside your application. They are great for starting operating system processes and communicating with them. For example, you might want to open a port to run an&lt;br&gt;
OS command, like &lt;code&gt;echo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You could open a port and send it a message, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:spawn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"echo sup"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:binary&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;#Port&amp;lt;0.1305&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you can use the &lt;code&gt;flush()&lt;/code&gt; IEx helper to print the messages from the port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:spawn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"echo sup"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:binary&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;#Port&amp;lt;0.1305&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1305&amp;gt;, {:data, "sup\n"}}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can send a port any name of a binary you want to execute. For example, from the directory of my jekyll blog, I opened up an &lt;code&gt;iex&lt;/code&gt; session, opened a port, and then sent the &lt;code&gt;bundle install&lt;/code&gt; command, which installed all the Ruby gem dependencies. Here's a snippet of the output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:spawn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"bundle install"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:binary&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using concurrent-ruby 1.0.5\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using i18n 0.9.5\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using minitest 5.11.3\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using thread_safe 0.3.6\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using tzinfo 1.2.5\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using activesupport 4.2.10\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using public_suffix 2.0.5\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using addressable 2.5.2\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using bundler 1.16.2\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using coffee-script-source 1.11.1\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;, {:data, "Using execjs 2.7.0\n"}}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt;,&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"Bundle complete! 4 Gemfile dependencies, 85 gems now installed.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Use `bundle info [gemname]` to see where a bundled gem is installed.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="ss"&gt;:ok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  PID
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;PID&lt;/code&gt; is a reference to a process. Whenever you spawn a new process, you'll get a new PID. Expect to talk a lot about PIDs. You'll probably need to hold onto PIDs so you can send different processes messages.&lt;/p&gt;

&lt;p&gt;Here's an example of spawning a process and getting the PID back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;spawn&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hello world"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="n"&gt;world&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#PID&amp;lt;0.123.0&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The process dies after it has done its job. PIDs and Ports warrant their own standalone post, but for now, I think it's sufficient to just be aware that they exist.&lt;/p&gt;

&lt;p&gt;So, now that we've added our new types, this is our basic cheat sheet.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Elixir Data Type Cheat Sheet
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;             &lt;span class="c1"&gt;# integer&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;           &lt;span class="c1"&gt;# floating point&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;         &lt;span class="c1"&gt;# boolean&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;          &lt;span class="c1"&gt;# range&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="sr"&gt;~r/hello/&lt;/span&gt;     &lt;span class="c1"&gt;# regular expression&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:hello&lt;/span&gt;        &lt;span class="c1"&gt;# atom&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;       &lt;span class="c1"&gt;# string&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'world'&lt;/span&gt;       &lt;span class="c1"&gt;# charlist&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#Port&amp;lt;0.1306&amp;gt; # port&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#PID&amp;lt;0.123.0&amp;gt; # pid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real challenge with Elixir in my opinion, though, is figuring out how to organize these basic data types into structures you can use. So let's take a look at the various collection types and why you would use each.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collection Types
&lt;/h2&gt;

&lt;p&gt;Here are the collection types you'll likely encounter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tuples&lt;/li&gt;
&lt;li&gt;Lists&lt;/li&gt;
&lt;li&gt;Keyword Lists&lt;/li&gt;
&lt;li&gt;Maps&lt;/li&gt;
&lt;li&gt;Structs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You've probably heard those words before, at least in passing, but if you're accustomed to Ruby, you're probably wondering why you need all those extra types of collections. Let's investigate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tuples
&lt;/h3&gt;

&lt;p&gt;Tuples are ordered collections of values. They look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;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;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"this is amazing!"&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="c1"&gt;# You can check if it's really a tuple&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;is_tuple&lt;/span&gt; &lt;span class="n"&gt;tuple&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="c1"&gt;# and then you can get an element from a tuple by index&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple&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="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think tuples are a little wild. I mean, they look like they should be hashes, but they sort of behave like Ruby arrays. And then they're called tuples! It'll pay off to get familiar with them though, which is what I keep telling myself when I get confused for the hundredth time.&lt;/p&gt;

&lt;p&gt;Tuples crop up all over the place in Elixir. Return values of functions are often tuples that you can pattern match on, so it makes sense to start seeing the world through tuples. Tuples usually have two to four elements, and at this point, they're my go-to data structure. When you're dealing with data structures that have more than four elements, that's probably a good case for using a map or struct instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lists
&lt;/h3&gt;

&lt;p&gt;Lists are linked data structures. They look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;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;2&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="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Ruby, you'd think that was an array, but in Elixir, it's a list! Because lists are implemented as linked data structures, they're good for recursion, but bad for randomly retrieving an element or even figuring out the length because you'd need to traverse the whole list to figure out the size. To date, I've mostly been using tuples instead of lists. If you had to choose between them, I suppose you'd need to consider the expected size of the collection and what kind of operations you'll be performing on it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyword Lists
&lt;/h3&gt;

&lt;p&gt;To further complicate matters, there are also such things as keyword lists in Elixir. In essence, this is a list of two-value tuples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# keyword list&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="ss"&gt;phrase:&lt;/span&gt; &lt;span class="s2"&gt;"oh hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"tracy"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# is actually two-value tuples&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:phrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"oh hello"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"tracy"&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;This continues to baffle me, even though I am aware of its general existence.The cool thing about keyword lists is that you can have two of the same keys in a keyword list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keyword_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;food:&lt;/span&gt; &lt;span class="s2"&gt;"peanut butter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;food:&lt;/span&gt; &lt;span class="s2"&gt;"ice cream"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;flavor:&lt;/span&gt; &lt;span class="s2"&gt;"chocolate"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# a valid keyword list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keyword lists are good for command-line parameters and options.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maps
&lt;/h3&gt;

&lt;p&gt;Next up are maps. If you wanted a real key-value store, not a list of key-values, this is what you're looking for. They look a bit like hashes in Ruby.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"greeting"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"noun"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;:greeting&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:noun&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;greeting:&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;noun:&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# if the keys are atoms, you can skip the hash rockets.&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;spanish:&lt;/span&gt; &lt;span class="s2"&gt;"hola"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;chinese:&lt;/span&gt; &lt;span class="s2"&gt;"ni hao"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;english:&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:spanish&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"hola"&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chinese&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"ni hao"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maps are good for passing associative data around, and pretty much everything else that is bigger than tuple size.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structs
&lt;/h3&gt;

&lt;p&gt;Structs are like enhanced maps. They permit only certain keys and those keys must be atoms. Structs need to be defined in modules with reasonable default values. They're maps with rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;IceCream&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="o"&gt;....&lt;/span&gt;   &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="ss"&gt;flavor:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;quantity:&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;end&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;chocolate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;flavor:&lt;/span&gt; &lt;span class="s2"&gt;"chocolate"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;chocolate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flavor&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"chocolate"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see that the struct is defined with the same &lt;code&gt;%&lt;/code&gt; percent symbol as a map, but it's followed by the name of the module. That's how I remind myself that they're just stricter maps.&lt;/p&gt;

&lt;p&gt;Older versions of Elixir used to also include the &lt;code&gt;HashDict&lt;/code&gt; to handle maps with more than a couple hundred values, but that module has been deprecated in favor of the good ol'fashioned &lt;code&gt;Map&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That brings us to the end of the common data types and collection types you'll see in Elixir. Although there are a number of differences between the two languages, there are some similarities. Of course, there's plenty more to learn about Elixir, the conventions, and the cool things you can do, but this (I think) is a good start to getting familiar with the language. Hopefully this'll serve as a decent guide to deciphering any Elixir you might encounter soon!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Elixir Collection Cheat Sheet
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"this is amazing!"&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="c1"&gt;# tuple&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;                                                   &lt;span class="c1"&gt;# list&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="ss"&gt;phrase:&lt;/span&gt; &lt;span class="s2"&gt;"oh hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"tracy"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;                                &lt;span class="c1"&gt;# keyword list&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;spanish:&lt;/span&gt; &lt;span class="s2"&gt;"hola"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;chinese:&lt;/span&gt; &lt;span class="s2"&gt;"ni hao"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;english:&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;# map&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;chocolate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;flavor:&lt;/span&gt; &lt;span class="s2"&gt;"chocolate"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;                           &lt;span class="c1"&gt;# struct&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://elixir-lang.org/getting-started/basic-types.html"&gt;Basic Types&lt;/a&gt; on
Elixir Lang&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pragprog.com/book/elixir16/programming-elixir-1-6"&gt;Programming Elixir&lt;/a&gt; by Dave Thomas&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/elixir/"&gt;Hex Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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