<?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: Haile Lagi</title>
    <description>The latest articles on DEV Community by Haile Lagi (@haile).</description>
    <link>https://dev.to/haile</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%2F305953%2F46fb69f4-2c50-49a2-a388-ee7f32066ba5.jpeg</url>
      <title>DEV Community: Haile Lagi</title>
      <link>https://dev.to/haile</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/haile"/>
    <language>en</language>
    <item>
      <title>It's legos all the way down</title>
      <dc:creator>Haile Lagi</dc:creator>
      <pubDate>Fri, 17 Feb 2023 09:46:58 +0000</pubDate>
      <link>https://dev.to/haile/its-legos-all-the-way-down-5e63</link>
      <guid>https://dev.to/haile/its-legos-all-the-way-down-5e63</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Often as folks who create useful software things we tend to think of ourselves as people who write software for the mythical "user". A "user" clicks a button and&lt;br&gt;
something magical happens. This is commonly reffered to as an &lt;a href="https://en.wikipedia.org/wiki/Abstraction_(computer_science)"&gt;abstraction&lt;/a&gt;.&lt;br&gt;
Abstractions are all around us in software and clever programmers create good abstractions for other programmers often to manage complexity.&lt;/p&gt;

&lt;p&gt;A really common example of this is an &lt;a href="https://en.wikipedia.org/wiki/API"&gt;Application Programming Interface&lt;/a&gt; which allows two "applications" to share useful data with each other over some transport while being platform-agnostic as to how this data is used. Like an API, there are other interesting kinds of abstractions -- let's peel back the abstraction between the language creator and language user by &lt;em&gt;inventing syntax!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This involves a subtle shift in the paradigm used to understand computation, at the &lt;em&gt;core&lt;/em&gt; is the idea of viewing &lt;strong&gt;computation as data&lt;/strong&gt;. I would guess for most people,&lt;br&gt;
the typical mental model when reading at first is mostly &lt;em&gt;procedural&lt;/em&gt;, a top-down scan with familiarity of syntax and semantics, then another important shift occurs in&lt;br&gt;
understanding runtime execution with the introduction of concurrency and parallelism, here we'll be peeling back at the layer between &lt;em&gt;compile time&lt;/em&gt; and &lt;em&gt;runtime&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Compile time occurs when program text is being "parsed and transformed" into many forms all the way to bits and runtime&lt;br&gt;
is when the program is actually executing ie "running", in this paradigm of viewing programs as textual input to other programs and to the program itself while running, is known as metaprogramming.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; This distinction between what is "compile" and "runtime" is
 a useful mental model illustrated here for simplicity, odds
 are what's happening in your favorite language is probably 
 more interesting![11]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we begin, a caveat. Although this technique applies broadly to most modern languages -- implementations vary in feature parity, I'll try to primarily include alternate examples with go's &lt;a href="https://go.dev/blog/laws-of-reflection"&gt;reflection&lt;/a&gt; and rust's &lt;a href="https://doc.rust-lang.org/book/ch19-06-macros.html"&gt;macro system&lt;/a&gt; while providing nods to Cpython[1], Ruby MRI[2] and some javascript [3]) but not typescript[4]&lt;/p&gt;

&lt;h3&gt;
  
  
  Computation is data
&lt;/h3&gt;

&lt;p&gt;Consider for example the humble &lt;code&gt;eval()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// javascript&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="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2 + 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# python
print(eval('2 + 2'))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ruby&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2 + 2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The computation &lt;code&gt;2 + 2&lt;/code&gt; is represented as data, in this case a &lt;code&gt;string&lt;/code&gt;. That's kind of neat isn't it? however we can take this much futher.&lt;br&gt;
If you're interested in further details of what's happening here, checkout &lt;a href="https://craftinginterpreters.com/"&gt;crafting interpreters&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since programming languages contain all sorts of elements like &lt;em&gt;expressions&lt;/em&gt; and &lt;em&gt;statements&lt;/em&gt;, we need some&lt;br&gt;
way to hold information about what the program or computation is trying to do, this internal representation is most commonly known as an Abstract Syntax Tree.&lt;/p&gt;

&lt;p&gt;At the risk of oversimplification, think of an AST as a way to meaningfully represent the textual source of a program that sometimes allows you to do something resembling &lt;a href="https://en.wikipedia.org/wiki/String_interpolation"&gt;string interpolation&lt;/a&gt; operations on your program's text source.&lt;/p&gt;
&lt;h3&gt;
  
  
  Prelude, why meta?
&lt;/h3&gt;

&lt;p&gt;To illustrate this concept, lets see how one might add syntax to create a &lt;a href="https://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)"&gt;constructor&lt;/a&gt; for a &lt;a href="https://en.wikipedia.org/wiki/Dynamic_array"&gt;dynamic array&lt;/a&gt; in &lt;code&gt;elixir&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First, some background. Elixir is a (mostly) functional language with (mostly) immutable datastructures, it doesn't encourage the use of&lt;br&gt;
or provide a dynamic array out of the box like most functional languages, as the implementation of one&lt;br&gt;
requires random access read/write via mutable state. Nor does it have "constructors", a typical pattern is creating structured data returned from&lt;br&gt;
a function and &lt;a href="https://elixirschool.com/en/lessons/basics/pipe_operator"&gt;"piping"&lt;/a&gt; it through several other functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Array&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Array&lt;/span&gt;

  &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="ss"&gt;field:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;\\&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;field:&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;iex&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;do_stuff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;do_other_stuff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this example, we're going to piggyback off the rust standard library's &lt;a href="https://doc.rust-lang.org/std/vec/struct.Vec.html"&gt;Vector&lt;/a&gt; by&lt;br&gt;
creating a &lt;a href="https://en.wikipedia.org/wiki/Foreign_function_interface"&gt;foreign function interface&lt;/a&gt; in elixir and alternatively a data structure implemented in the &lt;a href="https://www.erlang.org/doc/man/array.html"&gt;erlang stdlib&lt;/a&gt; in order to re-create something like &lt;code&gt;vec!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As we'll see the "backend" implementation of the data structure is not important, the fact that it's in rust or erlang doesn't matter, what we're focused on is providing an easy to use syntactic abstraction&lt;br&gt;
of a common datastructure.&lt;/p&gt;

&lt;p&gt;Here's a simplified version pulled straight from &lt;a href="https://doc.rust-lang.org/book/ch19-06-macros.html"&gt;the rust book&lt;/a&gt; of &lt;code&gt;vec!&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[macro_export]&lt;/span&gt;
&lt;span class="nd"&gt;macro_rules!&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$x:expr&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&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="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;temp_vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;temp_vec&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
            &lt;span class="n"&gt;temp_vec&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we see a pattern match &lt;code&gt;( $( $x:expr ),* )&lt;/code&gt; like our humble &lt;code&gt;eval('2 + 2')&lt;/code&gt; instead of representing the computation as a string, it's a tree like data-structure&lt;br&gt;
where we can assert at compile time, if some code looks like what we think it looks like, replace it with what's in the match arm,&lt;br&gt;
a process known as &lt;code&gt;macro expansion&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In elixir, we can write something similar, the pattern match is a three-element style tuple[5]:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{node, execution_context or meta_data, arguments}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Go and ruby share some superficial similarities as their metaprogramming api doesn't give you direct access to the AST. In ruby libraries like &lt;code&gt;RSpec&lt;/code&gt;,&lt;code&gt;rails&lt;/code&gt; router and &lt;code&gt;erb&lt;/code&gt; html templates often use metaprogramming techniques via "monkey patching" -- modifying at &lt;em&gt;runtime&lt;/em&gt; various&lt;br&gt;
properties of an object[6] and since in ruby's &lt;em&gt;extremely dynamically typed&lt;/em&gt;[7] interpreted world there is no notion of "compile time expansion" instead you have powerful introspection and malleability at runtime giving rise to patterns like &lt;code&gt;hooks&lt;/code&gt;[8] to alter nearly almost anything about the language via object properties, syntax or not.&lt;/p&gt;

&lt;p&gt;Take this small excerpt[9] from &lt;a href="https://github.com/rspec/rspec-core"&gt;rspec-core&lt;/a&gt; of the &lt;code&gt;describe&lt;/code&gt; public api:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# @private&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expose_example_group_alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;example_group_aliases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;example_group_aliases&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;

  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;__send__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:define_method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&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;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;example_group_block&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Core&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ExampleGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__send__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;example_group_block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;record&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;group&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;expose_example_group_alias_globally&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exposed_globally?&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's alot happening but the important thing to note is &lt;code&gt;RSpec::Core::ExampleGroup&lt;/code&gt; is an object that is being modified at the test-runner's runtime which specifies the linguistic structure of the &lt;em&gt;domain's specific language&lt;/em&gt; of what &lt;code&gt;describe&lt;/code&gt; means.&lt;/p&gt;

&lt;p&gt;In go like ruby we have &lt;code&gt;reflection&lt;/code&gt; that allows runtime introspection, unlike ruby it is statically typed and compiled. Reflection gives a temporary "escape hatch" out of the rigid type system and allows modification based on dynamic &lt;code&gt;interfaces&lt;/code&gt; the most idiomatic example of this I can find are the printing family[10] functions like &lt;code&gt;fmt.Sprintf&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;doPrint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;prevString&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
 &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;argNum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;isString&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;
  &lt;span class="c"&gt;// Add a space between two non-string arguments.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;argNum&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isString&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;prevString&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writeByte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;printArg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'v'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;prevString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;isString&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;h3&gt;
  
  
  Building a (Dynamic) Array "constructor" in Elixir
&lt;/h3&gt;

&lt;p&gt;Now, let's get hands on. Everything here lives in a mix project called &lt;a href="https://github.com/hailelagi/ex_vec"&gt;&lt;code&gt;ExVec&lt;/code&gt;&lt;/a&gt; and defining the macro's public api:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;ExVec&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;ExVec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;defmacro&lt;/span&gt; &lt;span class="n"&gt;__using__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;implementation:&lt;/span&gt; &lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="kn"&gt;quote&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:implementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;unquote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;))&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;defmacro&lt;/span&gt; &lt;span class="n"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;_h&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="kn"&gt;quote&lt;/span&gt; &lt;span class="ss"&gt;bind_quoted:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;args:&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;dispatch_constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@implementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defmacro&lt;/span&gt; &lt;span class="n"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;({:&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Range&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kn"&gt;quote&lt;/span&gt; &lt;span class="ss"&gt;bind_quoted:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;args:&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;dispatch_constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@implementation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dispatch_constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;impl&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="ss"&gt;:rust&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="ss"&gt;:erlang&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"invalid constructor type, did you mean :rust?"&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;The &lt;code&gt;ex_vec&lt;/code&gt; library has two backends &lt;code&gt;ExVec.Array&lt;/code&gt; which is a thin wrapper around &lt;a href="https://www.erlang.org/doc/man/array.html"&gt;&lt;code&gt;:array&lt;/code&gt;&lt;/a&gt; and &lt;code&gt;ExVec.Vector&lt;/code&gt; which is a NIF wrapper that leverages rustler's &lt;code&gt;Encoder&lt;/code&gt; and &lt;code&gt;Decoder&lt;/code&gt; to encode an elixir &lt;code&gt;List&lt;/code&gt; as a &lt;code&gt;Vec&lt;/code&gt; then implementing interfaces for what an array might look like in elixir by defining:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;Access&lt;/code&gt; behaviour&lt;/li&gt;
&lt;li&gt;A protocol implementation of &lt;code&gt;Enumerable&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By implementing these specifications we can safely use things from stdlib like &lt;code&gt;Enum&lt;/code&gt; and even &lt;code&gt;Stream&lt;/code&gt; and just like that in any other elixir project&lt;br&gt;
and letting the client choose the backend while keep the macro's syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DoStuff&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;ExVec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Vector&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;ExVec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;implementation:&lt;/span&gt; &lt;span class="ss"&gt;:rust&lt;/span&gt;


  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# serialised as a rust Vec&amp;lt;i32&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;vec!&lt;/span&gt;&lt;span class="p"&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="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;vec!&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="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# plain old linked-list&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="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;random_access&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# O(1) read&lt;/span&gt;
    &lt;span class="n"&gt;my_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;my_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

     &lt;span class="c1"&gt;# serialised random write access&lt;/span&gt;
    &lt;span class="no"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_and_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_array&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="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DoOtherStuff&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;ExVec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;implementation:&lt;/span&gt; &lt;span class="ss"&gt;:erlang&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# this is an erlang :array!&lt;/span&gt;
    &lt;span class="n"&gt;vec!&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="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&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;unfortunately as of the time of this writing, &lt;code&gt;rustler&lt;/code&gt; &lt;a href="https://github.com/rusterlium/rustler/issues/424"&gt;does not support&lt;/a&gt; generic type intefaces so I&lt;br&gt;
guess this is impossible?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;NifStruct)]&lt;/span&gt;
&lt;span class="nd"&gt;#[module&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ExVec.Vector"&lt;/span&gt;&lt;span class="nd"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;
   &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;isize&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore a serious limitation of this toy example is it only works for &lt;code&gt;i32&lt;/code&gt; integers :) I also glossed over some behaviours and protocols with defaults.&lt;/p&gt;

&lt;p&gt;You can find the full source for this example &lt;a href="https://github.com/hailelagi/ex_vec"&gt;here&lt;/a&gt;, please let me know if you have a comment, found a bug or typo. Thanks for reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] Python3's excellent &lt;code&gt;ast&lt;/code&gt; library: &lt;a href="https://docs.python.org/3/library/ast.html"&gt;https://docs.python.org/3/library/ast.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] RubyVM::AST : &lt;a href="https://ruby-doc.org/core-trunk/RubyVM/AST.html"&gt;https://ruby-doc.org/core-trunk/RubyVM/AST.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] Javascript(since ECMAScript6): &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] Typescript: &lt;a href="https://basarat.gitbook.io/typescript/overview"&gt;https://basarat.gitbook.io/typescript/overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] Go's AST : &lt;a href="https://pkg.go.dev/go/ast"&gt;https://pkg.go.dev/go/ast&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] Elixir's AST: &lt;a href="https://github.com/elixir-lang/elixir/blob/d8f1a5d6b653c14ae44c6eacdbc8e9df7006d284/lib/elixir/pages/syntax-reference.md#the-elixir-ast"&gt;https://github.com/elixir-lang/elixir/blob/d8f1a5d6b653c14ae44c6eacdbc8e9df7006d284/lib/elixir/pages/syntax-reference.md#the-elixir-ast&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[6] The one true (&lt;em&gt;useful&lt;/em&gt;) object to rule them all: &lt;a href="https://ruby-doc.org/3.2.1/Object.html"&gt;https://ruby-doc.org/3.2.1/Object.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[7] Ruby Extensions: &lt;a href="https://docs.ruby-lang.org/en/master/extension_rdoc.html#label-Basic+Knowledge"&gt;https://docs.ruby-lang.org/en/master/extension_rdoc.html#label-Basic+Knowledge&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[8] Awesome example of the &lt;code&gt;hook pattern&lt;/code&gt; into ruby's object lifecyle: &lt;a href="https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/hooks.rb"&gt;https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/hooks.rb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[9] RSpec public DSL module: &lt;a href="https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/dsl.rb"&gt;https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/dsl.rb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[10] doPrint: &lt;a href="https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/fmt/print.go;drc=261fe25c83a94fc3defe064baed3944cd3d16959;l=1204"&gt;https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/fmt/print.go;drc=261fe25c83a94fc3defe064baed3944cd3d16959;l=1204&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[11] Just in Time compilation: &lt;a href="https://en.wikipedia.org/wiki/Just-in-time_compilation"&gt;https://en.wikipedia.org/wiki/Just-in-time_compilation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>rust</category>
      <category>ruby</category>
      <category>go</category>
    </item>
    <item>
      <title>A peek into the beam</title>
      <dc:creator>Haile Lagi</dc:creator>
      <pubDate>Tue, 29 Mar 2022 09:45:58 +0000</pubDate>
      <link>https://dev.to/haile/a-peek-into-the-beam-127j</link>
      <guid>https://dev.to/haile/a-peek-into-the-beam-127j</guid>
      <description>&lt;p&gt;A long time ago, you would give a computer an intensive set of instructions - in assembly or something more sane, and it would compute these instructions one by one, but while it did that - it would “freeze up” you could not really do much else with it. At the time, computer hardware was pretty limited, it had a single CPU core (something that executes instruction sets) which did pretty much everything, one by one - computer scientists were not particularly &lt;br&gt;
satisfied with this, and they &lt;a href="https://en.wikipedia.org/wiki/Mutual_exclusion"&gt;found a solution&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In essence, execution of two or more computations at the same time is possible - given it is guaranteed that both read data from the same source, but not writing which could lead to inconsistency, commonly known as a &lt;em&gt;data race&lt;/em&gt; or &lt;em&gt;race condition&lt;/em&gt;. Today our computers have multiple cores - they can do a lot more stuff than they &lt;a href="https://en.wikipedia.org/wiki/Moore%27s_law"&gt;used to&lt;/a&gt;, but we need some way to guarantee or make it really hard for this to happen.&lt;/p&gt;

&lt;p&gt;The world of concurrency is fascinating, lots of languages design mechanisms around this problem known as &lt;strong&gt;concurrency primitives&lt;/strong&gt;, allowing software creators to fashion applications and software systems that perform much better than their sequential alternative, however we are most interested in a cursory glance into the BEAM (Erlang’s virtual machine). For brief context, a virtual machine is just software - an abstraction over the basic hardware of a computer allowing a layer of execution on top of it. A common example being the Java Virtual Machine (JVM). The elixir/erlang source code is parsed and transformed into a set of intermediary files prefixed with &lt;code&gt;.beam&lt;/code&gt; that the virtual machine can understand known as bytecode, via the &lt;code&gt;C&lt;/code&gt; programming language. From here it is translated into &lt;br&gt;
assembly/machine instruction bits [1].&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;source code&lt;/strong&gt;  ---&amp;gt;  &lt;strong&gt;c interface&lt;/strong&gt; ---&amp;gt;  &lt;strong&gt;bytecode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most of the interesting &lt;a href="https://en.wikipedia.org/wiki/Actor_model"&gt;concurrency primitives&lt;/a&gt; that erlang/elixir provide are built on top of the &lt;a href="https://ferd.ca/it-s-about-the-guarantees.html"&gt;guarantees&lt;/a&gt; this virtual machine provides such as immutable state. The single basic unit being a process [2] [3] - &lt;br&gt;
an isolated sequential unit of computation which is managed by a scheduler an important construct.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: you may think of a process as a kind of "green thread",&lt;br&gt;
if familiar with the concept. Otherwise thinking of them&lt;br&gt;
as an abstract unit of sequential computation is fine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Erlang’s scheduler
&lt;/h2&gt;

&lt;p&gt;The scheduler within the BEAM runtime (not an &lt;a href="https://en.wikipedia.org/wiki/Scheduling_(computing)"&gt;operating system scheduler&lt;/a&gt;),&lt;br&gt;
talks to the operating system via &lt;a href="https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/4_Threads.html"&gt;threads&lt;/a&gt; and manages the &lt;a href="https://hamidreza-s.github.io/erlang/scheduling/real-time/preemptive/migration/2016/02/09/erlang-scheduler-details.html"&gt;how and when&lt;/a&gt; of computations (processes - in the vm). It does something called &lt;em&gt;preemptive scheduling&lt;/em&gt; which requires making a nuanced trade off - all processes are treated as equal(unless a priority is set) and given a tiny block of time/memory to execute, whether this is enough for a process is irrelevant. It sacrifices the efficient allocation of resources to processes that need it most to make some important guarantees which make fault tolerance possible:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;High availability&lt;/li&gt;
&lt;li&gt;Isolated failure states&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This constant &lt;em&gt;context switching&lt;/em&gt; gives guarantees creating a system that is dependable - allowing the creation of processes that inspect others, we can leverage this information to make intelligent deductions about what is happening within the system at runtime and design strategies to deal with and understand crashes and fail states, while also providing concurrent primitives that naturally scale across distributed systems, changing very little about the core system. &lt;/p&gt;

&lt;p&gt;A typical illustration of erlang's introspective superpower is &lt;code&gt;:observer&lt;/code&gt; which ships by default. Pop &lt;code&gt;:observer.start()&lt;/code&gt; into any &lt;code&gt;iex&lt;/code&gt; session and watch the magic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;user@my-pc &lt;span class="nv"&gt;$ &lt;/span&gt;iex
iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; :observer.start&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m0oowFov--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.hailelagi.com/observer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m0oowFov--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.hailelagi.com/observer.png" alt="Observer showing scheduling" width="880" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see the schedulers at work by spinning up a few short-lived processes which begin their lifetime[4] with about &lt;a href="https://en.wikipedia.org/wiki/Word_(computer_architecture)"&gt;326 words of memory&lt;/a&gt; (approximately 0.65 kilobytes) which can &lt;a href="https://www.erlang.org/doc/man/erts_alloc.html"&gt;grow&lt;/a&gt; on a stack or heap.&lt;/p&gt;

&lt;p&gt;Here you have &lt;code&gt;self()&lt;/code&gt; as the &lt;code&gt;iex&lt;/code&gt; session process, creating another process that it communicates with:&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="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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;iex&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&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="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# new identifier process created by spawn&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="c1"&gt;# any arbitrary sequential computation&lt;/span&gt;
    &lt;span class="c1"&gt;# looping, control flow, anything :O&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;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then leverage the high level &lt;code&gt;Process&lt;/code&gt; library for convenience, to create more processes, thousands or even millions if need be:&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;child_two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:monitor&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;child_three&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:monitor&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;child_four&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&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="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="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:monitor&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;child_five&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:monitor&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Processes have an &lt;code&gt;identity&lt;/code&gt; via their &lt;code&gt;pid&lt;/code&gt;, this is how they are aware of one another. The return value of each child &lt;br&gt;
looks a little 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="c1"&gt;# {#PID&amp;lt;0.93.0&amp;gt;, #Reference&amp;lt;0.18808174.1939079169.202418&amp;gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: The actual pid and reference will be different on your machine).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When the scheduler(on one core) sees these concurrent tasks, it allocates some time and memory at runtime to &lt;code&gt;child&lt;/code&gt; and lets it run for a bit, if the process does not finish(an infinite loop for example), the scheduler moves on to &lt;code&gt;child_two&lt;/code&gt; and so on, checking up on each process, computing a bit. Processes are namespaced in a &lt;a href="https://hexdocs.pm/elixir/1.13/Registry.html"&gt;local registry&lt;/a&gt; for a single node. Scheduling across multiple nodes works the same way, only you'd need a different way to &lt;a href="https://github.com/uwiger/gproc"&gt;manage the global name space&lt;/a&gt; of running processes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: There are likely many scheduler threads coordinating &lt;br&gt;
on this activity on a single core, and at least one per&lt;br&gt;
operating system process. Further details are subject to&lt;br&gt;
which version of Erlang/OTP you're running and the implementation has varied significantly over the years and may change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;High availability and isolated failure states are achieved via messages propagated through a web of processes. Leading to interesting high level abstractions such as &lt;a href="https://www.hailelagi.com/posts/dev/break-your-next-server/"&gt;supervisors&lt;/a&gt; and &lt;a href="https://www.hailelagi.com/posts/dev/break-your-next-server/"&gt;agents&lt;/a&gt; for handling local inter process state.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's all about tradeoffs
&lt;/h2&gt;

&lt;p&gt;Elixir provides a beautiful modern language that allows you to leverage the amazing ecosystem and novel concurrency ideas built into erlang, offering you the tools to create and design highly fault-tolerant, self-healing systems, sometimes at the cost of &lt;em&gt;absolute runtime performance&lt;/em&gt;. You can see this with need to replicate data structures and performing computationally intensive tasks that would make sense to be processed sequentially. Do not despair however, you can carefully poke a hole into the runtime through the C interface via &lt;a href="https://www.erlang.org/doc/tutorial/nif.html#:~:text=A%20NIF%20is%20a%20function,UNIX%2C%20DLL%20in%20Windows"&gt;Native Implementation Functions&lt;/a&gt;, whether in C++ or perhaps rust via &lt;a href="https://github.com/rusterlium/rustler"&gt;rustler&lt;/a&gt;. Or outsource this kind of heavy-lifting if required to a service in a different language. Let's explore at a high level the conceptual &lt;br&gt;
underpinnings of relatively more popular languages and how they stack up against the BEAM's approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Actor Model vs Single Thread(multithreading) (Ruby, Javascript and Python)
&lt;/h3&gt;

&lt;p&gt;Ruby, Javascript and Python all have different concurrent models and implementations, however they share some important &lt;br&gt;
similarities at a high enough level they can be grouped together. Ruby(MRI), CPython and Javascript's v8 runtime(node.js) are all single threaded. Concurrency is achieved via a single Process(operating system) which has one large "main" thread(where the runtime is loaded) which creates smaller threads of execution within a single context(system resources - memory etc).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: You can in-fact create analogous threads of execution&lt;br&gt;
beyond what is given but doing so is expensive and tricky.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Node.js in particular was especially optimised with this design early on. The limitations here are somewhat obvious, utilising a multicore architecture is incredibly difficult and burdens the application developer with the nuances of lower level details you'll simply not interface with in erlang/elixir. Ruby and Python historically however needed a mechanism called a Global Interpreter Lock(GIL) to enforce/sync the runtime and make a data race impossible. This is often called a &lt;em&gt;mutual exclusion lock&lt;/em&gt; and the algorithm is plenty fascinating and deserving of its own article.&lt;/p&gt;

&lt;p&gt;The primitives given are fairly similar - ruby gives you a &lt;a href="https://ruby-doc.org/core-3.0.0/Thread.html"&gt;Thread class&lt;/a&gt; and &lt;a href="https://ruby-doc.org/core-3.0.0/Fiber.html"&gt;Fibre&lt;/a&gt; to create worker threads, node gives you access to the main libuv[11] managed &lt;a href="https://nodejs.org/api/process.html#process"&gt;Process&lt;/a&gt; and one for when you're creating &lt;a href="https://nodejs.org/api/worker_threads.html"&gt;worker threads&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To utilise any form of thread parallel execution python provides a &lt;a href="https://docs.python.org/3/library/multiprocessing.html"&gt;library interface&lt;/a&gt;, ruby core has been experimenting with and recently released an actor model inspired mechanism called &lt;a href="https://docs.ruby-lang.org/en/3.0/Ractor.html"&gt;Ractor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In practice, when creating say a web server with these languages an &lt;code&gt;Event Loop&lt;/code&gt;[9][10][11][12] handles the heavy lifting within the main thread, resources are simply not shared and asynchronous failures caught with lots and lots of defensive programming.&lt;/p&gt;

&lt;h3&gt;
  
  
  Actor Model vs Communicating sequential processes (goroutines)
&lt;/h3&gt;

&lt;p&gt;In some ways erlang and go share some features of their concurrent model - both leveraging the symmetric multiprocessing [8] architecture with the key difference eloquently expressed by a deceptively simple philosophy:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not communicate by sharing memory; &lt;br&gt;
instead, share memory by communicating&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Goroutines are analogous to "processes" being a lightweight "unit" of computation, however they have no identity(pid). This isolation ensures the only way data moves is through a "channel", a departure from the concept of a mailbox that keeps track of immutable internal state, a channel serves the purpose of message passing between anonymous routines.&lt;/p&gt;

&lt;p&gt;By opening a channel to some forgotten computation you can peek its state and enforce synchronisation.&lt;/p&gt;

&lt;p&gt;Resources are shared with carefully crafted rules. The analog of a supervisor being a "monitor goroutine". The sole writer of data in any cluster of spawned processes. This too is a form of message passing, just implemented with a kind of artificial immutability for workers. Runtime failures (panics) are rarer in go, and instead errors treated as values passed between goroutines. If panicked routines crash they inform the main go thread and the whole thing carries along swimmingly. &lt;/p&gt;

&lt;p&gt;Reasoning about concurrency systems is somewhat trickier here but allows for performance fine-tuning if you can enforce mutual exclusion between goroutines. This freedom does come seemingly at a cost[6] which it seems all&lt;br&gt;
languages that do not enforce immutable data structures and performance fine-tuning an exception rather than the norm,&lt;br&gt;
but of course it all depends on context and use case.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="https://github.com/ponty96"&gt;Ayomide&lt;/a&gt; and &lt;a href="https://github.com/derhnyel"&gt;Daniel&lt;/a&gt; for reviewing early drafts of this article.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] fxn(medium): &lt;a href="https://medium.com/@fxn/how-does-elixir-compile-execute-code-c1b36c9ec8cf"&gt;https://medium.com/@fxn/how-does-elixir-compile-execute-code-c1b36c9ec8cf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] green threads(wikipedia): &lt;a href="https://en.wikipedia.org/wiki/Green_threads"&gt;https://en.wikipedia.org/wiki/Green_threads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] Joe Armstrong(twitter): &lt;a href="https://twitter.com/joeerl/status/1010485913393254401"&gt;https://twitter.com/joeerl/status/1010485913393254401&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] Erlang documentation: &lt;a href="https://www.erlang.org/doc/reference_manual/processes.html"&gt;https://www.erlang.org/doc/reference_manual/processes.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] Erlang documentation: &lt;a href="https://www.erlang.org/doc/efficiency_guide/processes.html"&gt;https://www.erlang.org/doc/efficiency_guide/processes.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[6] go reference: &lt;a href="https://go.dev/ref/mem"&gt;https://go.dev/ref/mem&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[7] stackoverflow: &lt;a href="https://stackoverflow.com/questions/2708033/technically-why-are-processes-in-erlang-more-efficient-than-os-threads"&gt;https://stackoverflow.com/questions/2708033/technically-why-are-processes-in-erlang-more-efficient-than-os-threads&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[8] symmetric multiprocessing: &lt;a href="https://en.wikipedia.org/wiki/Symmetric_multiprocessing"&gt;https://en.wikipedia.org/wiki/Symmetric_multiprocessing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[9] node event loop: &lt;a href="https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/"&gt;https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[10] asyncio: &lt;a href="https://docs.python.org/3/library/asyncio.html"&gt;https://docs.python.org/3/library/asyncio.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[11] node io: &lt;a href="https://github.com/libuv/libuv"&gt;https://github.com/libuv/libuv&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[12] RoR documentation: &lt;a href="https://guides.rubyonrails.org/threading_and_code_execution.html"&gt;https://guides.rubyonrails.org/threading_and_code_execution.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>concurrency</category>
      <category>scheduler</category>
      <category>go</category>
    </item>
    <item>
      <title>Break your next server.</title>
      <dc:creator>Haile Lagi</dc:creator>
      <pubDate>Sat, 24 Oct 2020 15:03:16 +0000</pubDate>
      <link>https://dev.to/haile/break-your-next-server-3184</link>
      <guid>https://dev.to/haile/break-your-next-server-3184</guid>
      <description>&lt;h1&gt;
  
  
  Your friendly neighborhood aspiring junior dev's guide to understanding the philosophy of fault tolerance in servers. A series of rants and odd thoughts.
&lt;/h1&gt;

&lt;p&gt;I want to propose something, break your next server, on purpose. Nope that title isn't clickbait, but I hope you spare me a few moments to explain. Runtime errors are the last thing you want to happen in your code right? Especially if it's running in "production", but you know... I don't know.&lt;/p&gt;

&lt;p&gt;I'd like to think in general software development, stuff goes wrong more than it goes right. I always wonder what happens in real software teams? how do they respond to minor and major corruptions in their systems? Servers break all the time. For lots of unusual reasons, &lt;em&gt;especially&lt;/em&gt; in production. The world is a messy place, unpredictable and I have yet to find any real world service that hasn't experienced some sort of outage at some point in time. Sometimes? These are entirely unpredictable, novel problems that require novel solutions. There's no magic server that can guarantee 100% uptime(depends on what you define as "uptime", more on that later). Stuff happens, security vulnerabilities, scaling issues, dependencies on external services break, and so on. Things my inexperienced mind cannot begin to fathom.&lt;/p&gt;

&lt;p&gt;Yet? sometimes, these errors aren't so unimaginable. A database query fails? oops! An external api endpoint gets stressed? (*cough graphQL) and the guys on the other side get a weird aws email? 😦, something gets deprecated somewhere and you forgot?&lt;/p&gt;

&lt;p&gt;Okay, that's the &lt;em&gt;problem&lt;/em&gt; what's the solution? Let's explore some common approaches before we know what exactly is going wrong. 😈&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy another one! (Modern problems require modern solutions!)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o6Mbajy4stmeNfCPS/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o6Mbajy4stmeNfCPS/giphy.gif" alt="gif of Bart and Lisa Simpson sitting on a couch"&gt;&lt;/a&gt;&lt;br&gt;
Apparently there's this fancy stuff they call a &lt;code&gt;container&lt;/code&gt; these days. I won't bore you with infrastructure voodoo (I know little about it anyway), or less fancy a simple vcs checkout, let's keep this about &lt;em&gt;systemic approach&lt;/em&gt; rather than implementation. These are different things, yes but they can be used(sometimes together or in isolation) to "fix errors". This approach says "oh crap" something broke, let's go back to &lt;em&gt;when it did work&lt;/em&gt;. This is great except? Something caused a runtime exception you didn't expect and now you have an unavailable service. So you go off on an adventure, generating bug reports, pouring over log files and finding wtf happened! Sherlock mode activated! While this is happening you try to reboot the entire system with an older (bug free you believe) version. Nothing wrong with this, except? It's not solving the error problem. It's solving a dependency problem, an environment problem... but not necessarily an error problem and it's an approach at too high a level, you believe since the error happened in the programmer's domain? It must have been caused by it. Sometimes this is true, but not always. Sadly this server is too fragile anyway, just one lousy runtime error and everything goes boom?! You don't have to put yourself in that position. Not &lt;em&gt;unnecessarily&lt;/em&gt; and &lt;em&gt;without good reason&lt;/em&gt;. You should only need to re-deploy when something &lt;strong&gt;really important&lt;/strong&gt; goes wrong. This should be a rare case.&lt;/p&gt;
&lt;h2&gt;
  
  
  Avoid runtime errors at all costs!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l3YSeNYycfpIvPokM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l3YSeNYycfpIvPokM/giphy.gif" alt="gif of Elliot Alderson on a train"&gt;&lt;/a&gt;&lt;br&gt;
At this point, we're jaded and cynical about I/O. Legend has it? If you wrapped your entire application in a try/except clause it will never fail. You have some input? Don't just sanitize it, you bleach it, add some disinfectant, rub some olive oil on it, cut a chicken's head off and invent scenarios. Likely? unlikely? doesn't matter! &lt;code&gt;try, except, catch, rescue&lt;/code&gt; and their siblings are great... to a point. Yet, you can't predict every possible error under the sun. You need to take precaution, yes but you also need to be nimble, adaptable to the strange world of I/O and unpredictable side effects. The limitation of this approach is in the inability to isolate the error in the system, leading to generic uncaught exceptions and more importantly the corruption of state. More on that later. Depending on how this server's engineer intended recovery, it can go from beautifully crafted code to omg wtf is this because of the many paths the program can follow and how it re-converges to stability matters. This depends on skill and experience to execute and is a function of experience(usually) to the kinds of errors that could occur in prod. What if there was another way? Reflecting on experience is indispensable, you cannot substitute it. However, next best you can try to play catch up with a little foresight and study, re-inventing the wheel only when you need to.&lt;/p&gt;
&lt;h2&gt;
  
  
  To be fore-compiled is to before tested!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/kz6cm1kKle2MYkHtJF/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/kz6cm1kKle2MYkHtJF/giphy.gif" alt="gif of anime girl typing quickly"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's this thing around the programmatic universe, it's called Test Driven Development. Some people swear by it, some think it's a pain, yet pretty much everyone thinks it's a good idea(except crazy people 😏). On another side of the equation you have static typing. What do these things have in common? They check for the correctness of software &lt;em&gt;before&lt;/em&gt; it goes off into the real world(among other things lol). This is awesome, but it doesn't solve our problem still, how software behaves in an environment you do not control. These are lovely additions to controlling the programmer's domain and make sure(to an extent) nothing funny is going on through technology features and development practices.&lt;/p&gt;
&lt;h2&gt;
  
  
  Embracing failure as an inevitable part of systems(and our lives) by introducing the horsemen of the error apocalypse, Agents, GenServers, Supervisors and Applications.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/eIfYQTaK3148kmMCxT/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/eIfYQTaK3148kmMCxT/giphy.gif" alt="cartoon dog sitting in a burning house"&gt;&lt;/a&gt;&lt;br&gt;
There's a lovely rhetoric that I think holds true. Fail often, fail fast. Each of these approaches had a little something, a piece of the puzzle, a system design choice and when combined in the right way? they can be powerful tools. Introducing &lt;a href="https://en.wikipedia.org/wiki/Fault_tolerance"&gt;fault tolerance 101&lt;/a&gt; which has a rich &lt;a href="https://en.wikipedia.org/wiki/SAPO_(computer)"&gt;history.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fault tolerance and by extension concurrency are implemented in Elixir using the &lt;a href="https://en.wikipedia.org/wiki/Actor_model"&gt;Actor model&lt;/a&gt;. Let's start with the fundamental pieces and eventually how they work together to conceptually create an error tolerant server. You can ignore the code snippets if unfamiliar with the language, they run but are ultimately useless and illustrative. Before we go to the fun useful abstractions? Let's talk about the basics! Processes.&lt;/p&gt;
&lt;h4&gt;
  
  
  Processes
&lt;/h4&gt;

&lt;p&gt;This one is weird, in that it shares the same name with a &lt;a href="https://en.wikipedia.org/wiki/Process_(computing)"&gt;system process&lt;/a&gt;. &lt;a href="https://elixir-lang.org/getting-started/processes.html"&gt;Processes in Erlang/Elixir&lt;/a&gt; are lightweight spin offs that do stuff concurrently and communicate through messages. Sounds weird? Yup. I don't know much about how this is implemented internally(I'd love a pointer to deep dive resources). See Elixir is a functional language and yunno what that means kids! immutability, so how does concurrency happen? Why do we care? Well everything else is an abstraction built on top of this. You can think of a process like a &lt;em&gt;really really tiny server&lt;/em&gt;, with the whole &lt;a href="https://en.wikipedia.org/wiki/Request%E2%80%93response"&gt;request//response cycle&lt;/a&gt;. This is what it looks 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;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="s2"&gt;"do something"&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Doesn't this remind you of how a telephone line works?&lt;/em&gt; Instead of a network you communicate with this lone wolf, through an &lt;code&gt;abstract mailbox&lt;/code&gt; that holds messages in queue. Nothing complex here you &lt;code&gt;send&lt;/code&gt; stuff and you &lt;code&gt;recieve&lt;/code&gt; stuff. The mechanism is somewhat similar to &lt;code&gt;dispatching actions&lt;/code&gt; in &lt;a href="https://redux.js.org/"&gt;redux&lt;/a&gt; and this isn't a coincidence but a consequence of immutable state. I'll make references to redux, if you don't know it, that's fine. It's not a prerequisite. The high level concept is the main focus.&lt;/p&gt;

&lt;h4&gt;
  
  
  Agents
&lt;/h4&gt;

&lt;p&gt;Here's where stuff gets interesting, now that we know what processes are, let's discuss something productive. Agents are essentially specialized processes that are used to store app state. If you know what a &lt;a href="https://redux.js.org/basics/store"&gt;redux store&lt;/a&gt; is? this is a lot like that.&lt;br&gt;
&lt;em&gt;Why is this useful?&lt;/em&gt; you have some state that needs to be accessed by different parts of your application and most likely? these are going to be concurrent in different processes, how do you manage state? Agents are your goto solution. That's all it is, a safe space for your immutable state.&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="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="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Agent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&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="s2"&gt;"keep precious data safe"&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has some useful APIs but we don't care about that right now, only the conceptual understanding of what it is and what it does. &lt;/p&gt;

&lt;h4&gt;
  
  
  GenServers
&lt;/h4&gt;

&lt;p&gt;Remember the analogy where I said you can think of processes as &lt;em&gt;really really tiny servers?&lt;/em&gt; well there's a reason for that. A good mental model of this is anything that happens inside a process is the server and anything outside it? is the client. GenServers sound mystical the first time but it's actually short for a &lt;code&gt;generic server&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MetalGearSolid&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;GenServer&lt;/span&gt;
  &lt;span class="c1"&gt;# implement server&lt;/span&gt;
  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big_boss&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&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="n"&gt;big_boss&lt;/span&gt;&lt;span class="p"&gt;}&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;You can think of it as a "process that computes processes". This isn't as complex as it sounds. It just tells stuff what to do, it's like a jerk manager process that bosses around other developer processes...lol you just need to pass callbacks with the functionality you want the abstract &lt;code&gt;generic server&lt;/code&gt; to have and you're done! Here's what it looks 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="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:snake&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:reply&lt;/span&gt;&lt;span class="p"&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;head&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; becomes venom_snake spoiler!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It holds application state(using a similar mechanism with agents), manages and monitors processes. You interact with it using sync &lt;code&gt;calls&lt;/code&gt; and async &lt;code&gt;casts&lt;/code&gt;. There is a little more boilerplate code but we don't care.&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;# Start the server&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="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MetalGearSolid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:naked_snake&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# client&lt;/span&gt;
&lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:snake&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#returns ==&amp;gt; :naked_snake becomes venom_snake spoiler!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://elixir-lang.org/getting-started/mix-otp/genserver.html"&gt;official Elixir guide&lt;/a&gt; uses this phrase and it stuck with me "GenServer provides industrial strength functionality for building servers". That's an interesting choice of words, as someone who interned at a company that processes millions of dollars worth of product daily? Consider my interest piqued.&lt;br&gt;
&lt;em&gt;Why is this useful though?&lt;/em&gt; You see &lt;code&gt;genServers&lt;/code&gt; are you bread and butter, this is what in essence computes all your lovely complex computations, network requests, database queries? you name it.&lt;/p&gt;
&lt;h4&gt;
  
  
  Supervisors(middle management)
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/g0vgklqMS8zT2/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/g0vgklqMS8zT2/giphy.gif" alt="Cheryl Tunt from the show archer"&gt;&lt;/a&gt;&lt;br&gt;
We can sorta intuitively understand processes and message passing. We've explored agents a safety net that make sure our state is never corrupted, and generic servers as abstractions that perform collections of necessary async processes... yet how is any of this fault tolerant?&lt;/p&gt;

&lt;p&gt;What if we make a database query in a &lt;code&gt;genServer&lt;/code&gt; and it fails?&lt;br&gt;
Let's see what we have so far.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Our state isn't corrupted...great! (cause...immutability)&lt;/li&gt;
&lt;li&gt;Functionality is isolated, but so what?&lt;/li&gt;
&lt;li&gt;Our &lt;code&gt;genServer&lt;/code&gt; is gonna start to panic. oh crap what do I do? It &lt;em&gt;knows&lt;/em&gt; what's wrong and what is responsible. The process that was supposed to connect to the database failed...but now what?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What if you just need to try again? Maybe wait a little longer? Well now you need middle management, a faithful servant that will be there for you and observe what happens to your beautiful code and carries on your will when you can't.&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;children&lt;/span&gt; &lt;span class="o"&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;id:&lt;/span&gt; &lt;span class="no"&gt;MetalGearSolid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;start:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;MetalGearSolid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:start_link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="ss"&gt;:naked_snake&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="c1"&gt;# Make sure metalgear doesn't destroy the world&lt;/span&gt;
&lt;span class="c1"&gt;# here's the awesome strategy you apply&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="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Supervisor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;strategy:&lt;/span&gt; &lt;span class="ss"&gt;:one_for_one&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Putting the pieces together as Applications
&lt;/h4&gt;

&lt;p&gt;I've said a lot of stuff, all that was to prepare your mind. We can now talk about the &lt;a href="https://ferd.ca/the-zen-of-erlang.html"&gt;zen of Erlang&lt;/a&gt; (you should really check out that article btw! it's really funny and imo communicates the point of this post). The philosophy of fault tolerance(OTP) is built on structures of processes, isolated pieces of functionality talking to each other, to make bigger "units". Sometimes? This functionality is &lt;code&gt;linked&lt;/code&gt; other times? Our system can live without the database query knowledge of a user's favorite cat, this is how robustness is created. By identify mission critical parts of our system? We can protect them, even in the face of failing little bits and design strategies to cope. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The programmer becomes the ultimate creative ninja.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We display our cool coding skills proudly in the world of I/O. Unafraid of what could go wrong because we know something probably will! Our strategies of recovery are a game, we can trace error points, cast out unnecessary operations, skip some? Restart entire groups of dependent process... the possibilities are endless! If you're wrong? then the supervision tree will continue to run with less and less functionality until the errors propagate far enough into the system(&lt;em&gt;now you have something to worry about and can apply strategy one!!!&lt;/em&gt;) and even &lt;em&gt;here&lt;/em&gt; you have time to figure out what is going horribly wrong, and more often than not? You probably should never have shipped that.&lt;/p&gt;

&lt;p&gt;Applications are such large units of functionality in a larger system. Take a phoenix server, it's an application, the database query interface is child of the parent process, &lt;em&gt;even&lt;/em&gt; the endpoints are children, what happens when part of the functionality stops? Internally? &lt;strong&gt;The server will try to recover how I tell it to, using telemetry to report what happened, all the while still performing other functions&lt;/strong&gt; It's a thing of true beauty! The error(s) caused by any module are &lt;strong&gt;independent&lt;/strong&gt; of any other part of the system.&lt;/p&gt;

&lt;p&gt;In summary, agents store state, supervisors are co-ordinators, while genServers are executors and together they make up an application(which could also exist with them though). There are other interesting abstractions such as &lt;code&gt;Tasks&lt;/code&gt;,&lt;code&gt;Registry&lt;/code&gt; and &lt;code&gt;Dynamic Supervisors&lt;/code&gt; the world of OTP is fascinating.&lt;/p&gt;

&lt;h3&gt;
  
  
  GOTCHAS
&lt;/h3&gt;

&lt;p&gt;Okay, you've read all about fault tolerance and how this can probably help you. The question remains... do you really need it? This is about an approach to solving software problems, you don't need Elixir/Erlang for this. An honorable mention is this &lt;a href="https://github.com/Akamaozu/node-supe"&gt;implementation in javascript&lt;/a&gt; of a supervision tree. In fact, I'd go as far as to agree that &lt;a href="https://degoes.net/articles/fp-is-not-the-answer"&gt;functional programming doesn't necessarily mean good software either!&lt;/a&gt;. However Elixir/Erlang are extremely good tools optimised for not just dynamically handling errors in production but more importantly &lt;a href="https://www.phoenixframework.org/blog/the-road-to-2-million-websocket-connections"&gt;handling lots of persistent concurrent connections up to two million apparently!&lt;/a&gt;. This isn't just fluff either, &lt;a href="https://blog.whatsapp.com/1-million-is-so-2011"&gt;the whatsapp team achieved similar results in production way back in 2012 with Erlang&lt;/a&gt; and &lt;a href="https://blog.discord.com/how-discord-handles-push-request-bursts-of-over-a-million-per-minute-with-elixirs-genstage-8f899f0221b4?gi=d0cc90e81303"&gt;discord seems to love the language&lt;/a&gt;. These features are baked into the core language and ecosystem because it optimizes for them, it's easy to fall into the pit of success and program with these things first and foremost in mind. Many programmers and companies use many different programming languages with differing paradigms and practices, whether this is the right choice isn't simple. Isn't that what's fun about engineering? Software or not. Almost every cool decision is lowkey a &lt;a href="https://en.wikipedia.org/wiki/Constrained_optimization"&gt;constrained optimization problem.&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do you want to learn a new language and ecosystem? and dive into a completely new paradigm (assuming you're coming from a multi-paradigm or object oriented approach) It is an investment to think about.&lt;/li&gt;
&lt;li&gt;Does your system &lt;em&gt;really&lt;/em&gt; need high availability? Which is to say is &lt;a href="https://www.robust-reliability.com/en/robust-design/robust-designb"&gt;robustness an important feature you're optimising for?&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Do you need distributed computing?&lt;/li&gt;
&lt;li&gt;Do you intend on having A LOT of clients that do stuff at the same time?
&lt;em&gt;(A chat app is a good example - see discord and whatsapp case studies)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Do you have an existing codebase?
&lt;em&gt;(Is the ROI of migrating really worth it?)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Can you find good people who use this?
&lt;em&gt;(Not really the most popular language out there and the disadvantages that come with that)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Are you a junior? Or an aspiring junior like myself optimising for a job? Well... imo you're out of luck with Erlang/Elixir. Sad fact is whatever few jobs that are available? Are probably beyond your experience level :( sorry.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many many more questions remain to be answered for your particular use case. However, despite these things, I believe this is an excellent introduction and learning experience, to a fundamentally different approach to solving software problems using functional programming and understanding a curious model for achieving concurrency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Going Forward
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I'm looking to explore interesting technology. Stuff that's awesome because it's awesome. I have my eye out on &lt;a href="https://julialang.org/"&gt;Julia&lt;/a&gt; and it's uses for my research project(if schools ever resume :( ) and &lt;a href="https://golang.org/"&gt;Go&lt;/a&gt; for making tools. Got resource recommendations? not necessarily limited to languages, I'd love to hear them(web and scientific domains mostly!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I'm looking for really nice medium to large open source projects or fun hacks that are friendly. I have a lot of free time I'd like to spend hacking at stuff that &lt;em&gt;will be useful to people&lt;/em&gt; and while trying to do this on my own is fine, it has limitations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thank you for your time. I'm open to feedback whether in the form of criticisms, improvements or simply conversation, here on dev or anywhere you can find me on the internet :)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>elixir</category>
      <category>otp</category>
      <category>concurrency</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The weight of choice is heavy</title>
      <dc:creator>Haile Lagi</dc:creator>
      <pubDate>Mon, 31 Aug 2020 18:46:19 +0000</pubDate>
      <link>https://dev.to/haile/the-weight-of-choice-is-heavy-55o</link>
      <guid>https://dev.to/haile/the-weight-of-choice-is-heavy-55o</guid>
      <description>&lt;h1&gt;
  
  
  A humble aspiring junior dev's guide to probabilistic thought. A series of rants and odd thoughts.
&lt;/h1&gt;

&lt;p&gt;What are the odds? I've spent quite a few hours invested in implementing a seemingly innocent feature of a game I'm currently working on as part of my learning in the world of functional programming with Elixir. I won't bore you with the details, I haven't even finished making the game, the prelude to discovering this problem is an innocent one. It's a  terminal dungeon crawling game, where you venture into dark rooms in search of treasure and an eventual (hopeful) exit. &lt;/p&gt;

&lt;p&gt;If you know anything about me? I loooovvveee games and RPGs especially JRPGs, I love-hate dungeon crawling and puzzles so much so that &lt;a href="https://obsessedyouth.home.blog/2020/05/12/conquering-costlemark-towerand-what-it-taught-me-about-programming-and-life/"&gt;I write about it&lt;/a&gt; [NSFW!] so I've been having fun making this and curious about how all the gears fit, it is especially interesting to note how this relates to the modelling and simulation of &lt;a href="https://en.wikipedia.org/wiki/Mathematical_optimization"&gt;objective functions&lt;/a&gt; something I'm quite interested in!!! Let's dive in and explore!&lt;/p&gt;

&lt;p&gt;The probability of choosing a room is controlled by a call to &lt;code&gt;Enum.random(iterable)&lt;/code&gt; which selects a random element from the iterable, using Erlang's internal pseudo-random generation algorithm. At this point in time, only three rooms existed (a room leading to the exit, A room full of monsters and another room full of monsters.)&lt;br&gt;
Therefore it's safe to &lt;em&gt;assume&lt;/em&gt; the mathematical probability of finding any room is P(1/3). This isn't so great is it? You could just start the game and one-third of the time, without experiencing even a single battle :( Oh I know the author suggests... let's add different probabilities to the rooms, such that rooms with battles appear more likely and rooms with an exit less likely. Okay... so I tried it, after the first hour or so I came up with a satisfactory(to me I thought) solution. This is it. I first added a probability key, with a value of an array of atoms to the struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;DungeonCrawl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Room&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="sd"&gt;"""
  data structure representing a "room"
  a room has "actions" borrowed
  """&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;DungeonCrawl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as:&lt;/span&gt; &lt;span class="no"&gt;Room&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;DungeonCrawl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Room&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Triggers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;as:&lt;/span&gt; &lt;span class="no"&gt;Triggers&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;DungeonCrawl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Room&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Action&lt;/span&gt;

  &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;description:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;actions:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="ss"&gt;trigger:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;probability:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;do&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="no"&gt;Room&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="ss"&gt;:exit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;description:&lt;/span&gt; &lt;span class="s2"&gt;"You can see a small light from a crack in the walls"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;actions:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
        &lt;span class="ss"&gt;trigger:&lt;/span&gt; &lt;span class="no"&gt;Triggers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;probability:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:exit&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="no"&gt;Room&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="ss"&gt;:goblin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;description:&lt;/span&gt; &lt;span class="s2"&gt;"You can see an enemy blocking your path"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;actions:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
        &lt;span class="ss"&gt;trigger:&lt;/span&gt; &lt;span class="no"&gt;Triggers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Enemy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;probability:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:goblin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:goblin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:goblin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:goblin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:goblin&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="no"&gt;Room&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="ss"&gt;:ogre&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;description:&lt;/span&gt; &lt;span class="s2"&gt;"Something moves around in the dark, what do you do?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;actions:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
        &lt;span class="ss"&gt;trigger:&lt;/span&gt; &lt;span class="no"&gt;Triggers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Enemy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;probability:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:ogre&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:ogre&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:ogre&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="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At once you can probably see the naiveness of this solution. What computed the algorithm is 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="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;bias_probability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rooms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;rooms&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;probability&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and finally now that I know the biased random outcome-&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;rooms&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;bias_probability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rooms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technically? This is a mathematically correct solution. It will compute a random value with a biased probability of &lt;code&gt;P(0.1, 0.5, 0.3)&lt;/code&gt;. I felt happy with myself, turned off my laptop and went to sleep! That was that! Or so I thought.&lt;/p&gt;

&lt;p&gt;See there are two fundamental flaws of this approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;I'm hard coding the probabilities, although modifying the probability of a room is possible, it will result in boiler plate code and unnecessary list traversal&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;The algorithm is not performant(in space complexity) atoms are not garbage collected in Elixir, and it would be unwise to arbitrarily create them on a whim! suppose I had a thousand rooms in the future for example&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sure enough, extra feature requirements came, the addition of a "difficulty level" that will bias this probability dynamically. So.. began my search, with a renewed courage to try mathematical problems I tweaked and tweaked, no luck. I asked my friends in engineering from school no luck! and then sure enough, a friend of mine with superior googling skill found a long lost blog post from 2017. This is what really helped me, without it I was lost in meaningless scribbles of probability theory and conditional problems. If you're interested in learning more about implementing a weighted probability algorithm please check out &lt;a href="https://blog.bruce-hill.com/a-faster-weighted-random-choice"&gt;David Hills's blog&lt;/a&gt; it's really detailed and well done! I'll focus on implementing two algorithmic approaches I learned and adapting it to the context of this game. The linear search and one of the alias algorithms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Probabilities can be unfair!
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Linear scan the O(kay) method
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;O(n) runtime&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A lovely idea is to search the linked list for an index value based on probable outcomes, wish I thought of this!! This will work by generating a random number between &lt;code&gt;0 - 1&lt;/code&gt; and multiply that by the total probability distribution(For my use case, I'm assuming the list is sorted), then traverse the probability distribution subtracting each probability from the random probability, if it goes below zero? We've exhausted the probability distribution and found the index we need. Lovely solution. This works because we mathematically assume &lt;code&gt;random.random()&lt;/code&gt; will generate a perfectly random number(spoiler it doesn't, but we don't care). If the probability is really low? It will hit the lowest index less often, and if the probability is high? It will hit that index more often. Run the code below to get a sense of it if you like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;random&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;weighted_random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;"""
    INPUT probabilities - [0.2, 0.3, 0.5]
    OUTPUT index of random_weight - [0, 1, 2]
    """&lt;/span&gt;
    &lt;span class="n"&gt;remaining_distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# probability distribution sample size * random integer
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# [{0, 0.2}, {1, 0.3}, {2, 0.5}]
&lt;/span&gt;        &lt;span class="n"&gt;remaining_distance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="c1"&gt;#print("debug", remaining_distance)
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;remaining_distance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;

&lt;span class="c1"&gt;# Repeat the experiment to observe bias factor
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"exp trial&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;weighted_random&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This seems really cool doesn't it? I can represent the P(n) of my game as floats and dynamically update them, keeping the purity of the function. A quick and dirty Elixir version of this looks 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="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Prob&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;bias_probability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# [i[0] P=0.2, i[1] P=0.5 , i[2] P=0.3] s.s = 3&lt;/span&gt;
    &lt;span class="c1"&gt;# P(n) = distribution sample len bias * random() - P[i] &amp;lt; 0&lt;/span&gt;
    &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# could increase range for greater float precision as you like&lt;/span&gt;
    &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&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;99&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# bias factor&lt;/span&gt;
    &lt;span class="n"&gt;enumerated_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce_while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enumerated_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&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="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:cont&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:halt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&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;inspect&lt;/span&gt; &lt;span class="no"&gt;Prob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bias_probability&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then to find the biased index.&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;rooms&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;probability&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bias_probability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rooms&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but now that I've gone through the trouble of investigating weighted probability, I don't wanna settle for a linear search. Might as well make the game with the fastest possible approach. Let's go back in history, and take a look at one of the &lt;a href="https://en.wikipedia.org/wiki/Alias_method"&gt;alias algorithms&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aliasing(Vose) the O yes! method
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;O(n) alias table prep + O(1) lookup&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This one is a bit tricky to understand at first. If you're interested in a much more technical deep dive into the various approaches for solving this problem, please check out this &lt;a href="https://www.keithschwarz.com/darts-dice-coins/"&gt;article by Keith Schwarz&lt;/a&gt; it's dense, comprehensive and technical. Onto aliasing!&lt;/p&gt;

&lt;p&gt;The idea is honestly very clever! and in my opinion counter-intuitive, which is what makes it's constant-time runtime lookup so impressive. Let's take a step back, before diving in. An alias is like a nickname we give to stuff right? You have a friend called Samuel, and you call him Sam. His name isn't Sam and he hates that nickname, but alas, it stuck... poor Samuel, but if you see his face anywhere you know Sam is Samuel because you're such good friends. The alias method is a lot like this in principle. You have a biased probability weight distribution and it &lt;em&gt;approaches some limit&lt;/em&gt; and that limit can be used to generate a custom distribution. Let's talk about Sam for a bit.&lt;/p&gt;

&lt;p&gt;See Sam's nickname is called an &lt;code&gt;alias table&lt;/code&gt; and your friendship(how you know Sam is Samuel) is the algorithm. Now that we have some hint as to what we're doing, here's the python implementation with my comments from Bruce Hill's blog. Scan through it, maybe run it if you're adventurous. We'll break it down step by step next. (If you're familiar with Java check out &lt;a href="https://www.keithschwarz.com/interesting/code/?dir=alias-method"&gt;Keith Schwarz's implementation instead&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;prepare_aliased_randomizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# limit
&lt;/span&gt;    &lt;span class="n"&gt;avg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="c1"&gt;# alias partition
&lt;/span&gt;
    &lt;span class="n"&gt;aliases&lt;/span&gt; &lt;span class="o"&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="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;
    &lt;span class="c1"&gt;# [(1, None), (1, None), (1, None)] --&amp;gt; alias table
&lt;/span&gt;
    &lt;span class="c1"&gt;# Bucketting (pseudo quick sort like behaviour*)
&lt;/span&gt;    &lt;span class="c1"&gt;# weight/avg &amp;lt; | &amp;gt; avg
&lt;/span&gt;    &lt;span class="c1"&gt;# smalls are partial alias fits
&lt;/span&gt;    &lt;span class="c1"&gt;# bigs fits and remainder thrown to smalls
&lt;/span&gt;
    &lt;span class="n"&gt;smalls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;avg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;avg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bigs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;avg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;avg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# [(0, 0.6), (1, 0.9)] --&amp;gt; small weight avgs
&lt;/span&gt;    &lt;span class="c1"&gt;# [(2, 1.5)] --&amp;gt; big weight avgs
&lt;/span&gt;    &lt;span class="c1"&gt;#cycle through small and big partition generator
&lt;/span&gt;    &lt;span class="n"&gt;small&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;smalls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bigs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# if elems are not exhauted kindly loop
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;small&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# put the partial elem in aliases
&lt;/span&gt;        &lt;span class="n"&gt;aliases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;small&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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;small&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;big&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"alias lookup table transformation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aliases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# big = i of big , weight_b - (1 - weight_s)
&lt;/span&gt;        &lt;span class="c1"&gt;# big = (0, (1.5 - (1 - 0.6))
&lt;/span&gt;        &lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;big&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="n"&gt;big&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="o"&gt;-&lt;/span&gt; &lt;span class="p"&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;small&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;big&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="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"large weight is &amp;lt; 1 skip"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aliases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;small&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;big&lt;/span&gt;
            &lt;span class="n"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bigs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;small&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;smalls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"alias table generated"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aliases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# SELECTION STAGE
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;weighted_random&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# choose a random probability
&lt;/span&gt;        &lt;span class="c1"&gt;# from the alias table
&lt;/span&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;odds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aliases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"what are the odds of"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# return the larger probability if
&lt;/span&gt;        &lt;span class="c1"&gt;# it's odds are higher else
&lt;/span&gt;        &lt;span class="c1"&gt;# return the smaller probability index
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;odds&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;weighted_random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# single trial selection
&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"experiment trial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prepare_aliased_randomizer&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

&lt;span class="c1"&gt;# Repeat the experiment to observe bias factor
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"experiment trial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prepare_aliased_randomizer&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHEWW!!!!!!! there's alot going on. Let's break it down. There are two major steps, once you understand how the table is generated(that's most of the work) the lookup naturally follows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;This paragraph is interesting but ultimately a digression, you can choose to skip over it!&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;How exactly does a computer remember who Sam is? Well computers are a little like the human brain, people have complex organic circuitry of neurons that consolidate sensory observation and from that recognizes patterns and form "thoughts", the only difference is we have to tell the computer what pattern it should follow and it doesn't necessary form a thought, simply a result, and we do not need such instructions?(dna? nope, it's a philosophical question of not only intelligence but implicitly will :) does existence precede essence? I like to think so. Shameless plug, @ me on &lt;a href="https://twitter.com/haile_lagi"&gt;twitter&lt;/a&gt; if you're interested in this topic).&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Table generation
&lt;/h4&gt;

&lt;p&gt;To create the table, the original weight distribution is sliced into pieces(partitions)! Quite literally! Suppose we know how many weights we need, in this case 3, that's the limit. To find &lt;code&gt;P(0.2, 0.3, 0.5)&lt;/code&gt; We create an empty alias, with a data structure, with the exact same length &lt;code&gt;[partition, partition, partition]&lt;/code&gt; and a probability &lt;code&gt;[partition, partition, partition]&lt;/code&gt;. Each partition will contain exactly &lt;code&gt;P(1/3)&lt;/code&gt;. Here's the interesting part, we then scale the probabilities to the factor of our limit and separate it into chunks &lt;code&gt;less than 1&lt;/code&gt; and &lt;code&gt;greater than or equal to 1&lt;/code&gt;. Why?&lt;/p&gt;

&lt;p&gt;Here is the rationale:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If the weight fraction is greater than one or equal to it, it will fill a single alias partition(fit exactly if equal else) with some change! which will be sent to an empty partition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the weight is less than one, then it will be smaller than the allocated partition and it will be expecting a buddy :)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each partition, will hold a new distribution perfectly and why this is mathematically correct.. is kinda funny tbh. I won't discuss the formal proof, but the idea is that at any point in time, the sum of the elements in the distribution is always proportionate to the original weight.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Probability&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;bias_probability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Initialization&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;prepare_alias_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;prepare_alias_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;alias_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&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;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;prob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&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;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# create work lists&lt;/span&gt;
    &lt;span class="n"&gt;scaled_weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scale_probability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;small&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="n"&gt;scaled_weight&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;large&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="n"&gt;scaled_weight&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;w&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="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# recursively create table (TCO optimized)&lt;/span&gt;
    &lt;span class="n"&gt;transform_alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;small&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;large&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alias_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Base case when small and large are empty&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;transform_alias&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prob&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prob&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;transform_alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;small&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;alias_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Remove the first element from large call it g, Set prob[g] = 1&lt;/span&gt;
    &lt;span class="n"&gt;transform_alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;small&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;alias_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&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="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;transform_alias&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;_l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;large&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="n"&gt;alias_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# (clause will trigger due to numerical instability)&lt;/span&gt;
    &lt;span class="c1"&gt;# Remove the first element from Small, call it l&lt;/span&gt;
    &lt;span class="n"&gt;transform_alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;large&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;alias_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&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="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;transform_alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;index_l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight_l&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail_s&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
         &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;index_g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight_g&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail_l&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
         &lt;span class="n"&gt;alias_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;prob&lt;/span&gt;
       &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Remove the first element from small call it l&lt;/span&gt;
    &lt;span class="c1"&gt;# Remove the first element from large call it g&lt;/span&gt;
    &lt;span class="c1"&gt;# Pg := (pg + pl) - 1 (numerical stability :) )&lt;/span&gt;
    &lt;span class="n"&gt;new_weight_g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weight_g&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;weight_l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="c1"&gt;# if Pg &amp;lt; 1 add g to small&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new_weight_g&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;transform_alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;index_g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_weight_g&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail_s&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;tail_l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alias_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index_l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight_g&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index_l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight_l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;# else Pg &amp;gt;= 1 add g to large&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;transform_alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;tail_s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;index_g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_weight_g&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail_l&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alias_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index_l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight_g&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="no"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index_l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight_l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;# HELPER&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;scale_probability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="mi"&gt;0&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;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&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="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&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;Now that we can generate an alias table, this implementation will also include a local cache using &lt;a href="http://erlang.org/doc/man/ets.html"&gt;Erlang Term Storage&lt;/a&gt; to hold the alias table inside another table! lol throughout the lifecycle of the application once it has begun to run. I'm assuming once a difficulty level is selected random rooms need to be populated but the probability of that room occuring needs to be computed once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;bias_probability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Initialization&lt;/span&gt;
    &lt;span class="c1"&gt;# does the probability exist in memory?&lt;/span&gt;
    &lt;span class="n"&gt;current_probability&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;weights:&lt;/span&gt; &lt;span class="n"&gt;cached_probs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:ets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:weight_probability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;cached_probs&lt;/span&gt;
    &lt;span class="k"&gt;rescue&lt;/span&gt;
      &lt;span class="no"&gt;ArgumentError&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&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;current_probability&lt;/span&gt;
    &lt;span class="c1"&gt;#|&amp;gt; weighted_random # to be implemented next&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="ss"&gt;:ets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:weight_probability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:duplicate_bag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:private&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:named_table&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="ss"&gt;:ets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:weight_probability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prepare_alias_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;weights:&lt;/span&gt; &lt;span class="n"&gt;cached_probs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:ets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:weight_probability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:weights&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cached_probs&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Look up
&lt;/h4&gt;

&lt;p&gt;Finally we can generate a random probability and select an index to return from it!&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;# GENERATION&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;weighted_random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aliased_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Generate a fair random distro in a range&lt;/span&gt;
    &lt;span class="c1"&gt;# from n and call it i.&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="c1"&gt;# random choice P(1/3)&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 0, 1 , 2&lt;/span&gt;

    &lt;span class="n"&gt;prob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aliased_table&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="n"&gt;odd&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# partial fit&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;i&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="n"&gt;odd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="c1"&gt;# which piece of what goes where&lt;/span&gt;
      &lt;span class="n"&gt;bias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prob&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bias&lt;/span&gt;

      &lt;span class="n"&gt;i&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
       &lt;span class="n"&gt;i&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;Here's the whole implementation in a &lt;a href="https://gist.github.com/hailelagi/553d0af87209f21516be8fb53bcdf453"&gt;Github gist&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  GOTCHAS
&lt;/h2&gt;

&lt;p&gt;There are quite a few waiting for you if you desire to copy/paste this implementation, for example I ignored float point precision(somewhat) instead I could have chosen to seed the values and &lt;em&gt;my probabilities are always weight fractions of 1&lt;/em&gt;, or the implicit assumption of never returning 0, or 1 weights in the linear search. Please read the more indepth blogs, they're invaluable. For my use case though, it could probably scale to thousands of rooms effortlessly 😄 Thanks for reading!!! I'm always looking for feedback, have a suggestion? found a bug? Know an interesting algorithm? Maybe you just wanna leave kind words, I'm always happy to converse :)&lt;/p&gt;

</description>
      <category>python</category>
      <category>algorithms</category>
      <category>probability</category>
      <category>elixir</category>
    </item>
    <item>
      <title>Schrödinger, cats and boxes.</title>
      <dc:creator>Haile Lagi</dc:creator>
      <pubDate>Sun, 26 Jul 2020 17:20:14 +0000</pubDate>
      <link>https://dev.to/haile/schrodinger-cats-and-boxes-l93</link>
      <guid>https://dev.to/haile/schrodinger-cats-and-boxes-l93</guid>
      <description>&lt;h1&gt;
  
  
  A humble aspiring junior dev's guide to programmatic thought. A series of rants and odd thoughts.
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;“And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters.”&lt;br&gt;
&lt;em&gt;Genesis 1:2&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If functional programming were a cat? It'd be a black cat. Cats are a lot like functional programming, herein referred affectionately to as fp. It's really more scared of you than you are of it. You see? it's always trying to find compile time guarantees and predictable data flow. It's a fragile thing this paradigm, it can't handle the real world of I/O on its own. It needs help from you the programmer and it begs you not to be stupid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2F7vhAnGwSOQvUQ%2F200w.webp%3Fcid%3Decf05e47d992e46e1fc6c67dbbc5153d0601d01dc14928d4%26rid%3D200w.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2F7vhAnGwSOQvUQ%2F200w.webp%3Fcid%3Decf05e47d992e46e1fc6c67dbbc5153d0601d01dc14928d4%26rid%3D200w.webp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unlike their very flexible abstract brother in arms? Objects? They take abstraction and flip it on its head. Gone is the &lt;em&gt;natural&lt;/em&gt;(familiarity bias) view of the programmatic universe, enters this dystopia! Filled with processes that lead to processes. I no longer see a Tree surrounded with air, I see photosynthesis!. The complexity of fp is meant to simplify programming not obscure it. It's scared of mutations! who wants to be a powerless human? among X-men? with the ability to simply create &lt;em&gt;new&lt;/em&gt; data structures at will. They are more like a logicians wet dream. Pretty premises coming in to be analyzed with a scalpel of wit, to its rational valid conclusion. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fj9EfZBLJsLIuA%2Fgiphy.webp%3Fcid%3Decf05e47bhv0d1v0y7w300d67cintcn9pmzbk23e1i15bfz8%26rid%3Dgiphy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fj9EfZBLJsLIuA%2Fgiphy.webp%3Fcid%3Decf05e47bhv0d1v0y7w300d67cintcn9pmzbk23e1i15bfz8%26rid%3Dgiphy.webp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Once upon a time, long ago a man asked himself? What is a thing? Then the woes of all programmers began&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's leave programming for a little while. Follow Alice down this rabbit hole, I promise we will return. For now let's say hi to Oxford philosopher William of Occam, and the &lt;a href="https://plato.stanford.edu/entries/modality-medieval" rel="noopener noreferrer"&gt;modal theory&lt;/a&gt;. Not &lt;a href="https://en.wikipedia.org/wiki/Model_theory" rel="noopener noreferrer"&gt;Model theory&lt;/a&gt; as is traditionally done. You see I am not passionate about mathematics, I tolerate its method for utility. Another noteworthy person of stature was Peter Abelard. There was a problem &lt;a href="https://en.wikipedia.org/wiki/Black_Death" rel="noopener noreferrer"&gt;plaguing&lt;/a&gt; people in the middle Ages(pun intended) it was a problem of stuff. Nope not conspicuous consumption you of the bourgeois class :) What are stuff anyway? &lt;/p&gt;

&lt;p&gt;But first another digression from this digression! Forgive me! But we are looking back into history in the wrong order, and for good reason as you'll come to understand, I hope. Let's pay our respect to the mathematicians before we cast their headache inducing notations &lt;em&gt;ad nauseam&lt;/em&gt; aside. To the original gangster himself, Wilhelm Leibniz. &lt;/p&gt;

&lt;p&gt;Yup that one, the calculus guy that ruined my engineering education(let's forget that other alchemist for now he isn't important). Curse these polyglot achievers, mere mortals like myself struggle in one field but calculus was not mathematical enquiry. Or at least it was not created to be "just" math. It was a pure expression of holy abstraction, to cut down any and all in every field(arguably it has somewhat achieved its intended goal). It is strange the first time you see it. dy/dx. Oh the PTSD this symbol brings back but &lt;em&gt;that is what it is&lt;/em&gt; a &lt;strong&gt;symbol&lt;/strong&gt;. A representation of the rate of change of relative quantities? Oh hush now, this has nothing to do with programming you complain! But it has everything to do with it. The pieces will align, eventually. I hope as I learn, I write and hope I do not err in communication.&lt;/p&gt;

&lt;p&gt;You see? It is the fault of these men. Men like Goedel, Russel, Venn and Boole among others. They cursed us with genius and forgot to dumb it down. Before we return to modal theory let's dive into languages and symbols for a bit without going into too much overwhelming detail? This is what your everyday programmer does. A little &lt;code&gt;if&lt;/code&gt; here, a little &lt;code&gt;false&lt;/code&gt; there. Some iteration there to be sure, a little recursion here poof!!! you have yourself magic! But it wasn't always so. See there was a problem Leibniz attended to. When we speak or write we do so by conveying thoughts that have &lt;strong&gt;cognitive meaning&lt;/strong&gt; or &lt;strong&gt;emotive meaning&lt;/strong&gt;. Emotive statements tend to make a value claim here and there you know them, politics, morality, ethics, those tricky things. Logicians don't like those. They like statements that can be &lt;em&gt;evaluated&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The sky is black.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can notice certain features - It's unambiguous and specific, the premise holds the subject "sky" and adds an adjective(attribute or qualifier) that makes a proposition. It gives you something to think about doesn't it? Suddenly you think of empirical research to support or dispute this. It makes a claim that can be true or false but never both nor neither.&lt;/p&gt;

&lt;p&gt;Easy to reason about no? Now imagine "sky" was data. Could be an array of integers, could be a string of unicode characters. Let's add an attribute to it. Let's call it "black" or "green". Ahhh!!!! now you see it yes? Sky is an object. This is the object oriented approach but remember here? in a functional universe there are no objects like Leibniz let's think of it as dy/dx lol. Think of it like a &lt;em&gt;process&lt;/em&gt;. A transformation of data that may or may not be true. All of a sudden you're asking &lt;code&gt;is_black(The sky)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WTFFFFF!!!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I said. Where is the sky coming from? &lt;code&gt;is_black&lt;/code&gt; don't give AF. It &lt;em&gt;only&lt;/em&gt; knows how to be black. The qualifier does not belong to the object, if you really think about it? It makes sense. Lot's of things can be black, you can have a black car or black shoes. Black can be a property yes! but it can also be a thing in and of itself.&lt;/p&gt;

&lt;p&gt;Remember modal theory? Let me hint at it. Here it has become relevant but its proper introduction is still further ahead. How do we define an object? and how does it come to possess attributes? What is sky? is it the clouds, the air? The sum of its parts? Perhaps. Let's look at "black" it seems to belong to some kind of category? Yes? &lt;em&gt;It is a color after all&lt;/em&gt; but if it's a color &lt;em&gt;Then what is a color?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Such interesting questions oh such interesting questions. Just begging for intellectual attention :sigh: but I'm getting way ahead of myself. Let's pause for a moment, let me sip my entropying coffee.&lt;/p&gt;

&lt;p&gt;Let's return to the familiar world of languages and symbols and introduce something foreign and scary, logical operators!! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[(R ⊃ T) v (S ⊃ U)] • [(W ≡ X) v (Y ≡ Z)]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Logicians and mathematicians use these sorts of languages. Scary isn't it? Looking at complex symbols and notations that are apparently meaningful but only to the initiated. It is reminiscent of a regular expression. This a symbolic expression of a premise. Albeit more complex than &lt;code&gt;The sky is black&lt;/code&gt; but it's still the same fundamentally. Here we introduce something called a &lt;strong&gt;compound statement&lt;/strong&gt;. You can think of it as a bunch of functions communication with each other(notice the parallel with fp? ). Let's break down the cryptic and make it bare.&lt;/p&gt;

&lt;p&gt;The ~ means negation similar to the programming equivalent of &lt;code&gt;not&lt;/code&gt; or &lt;code&gt;!&lt;/code&gt;&lt;br&gt;
The • means conjunction it is basically &lt;code&gt;and&lt;/code&gt; or &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;&lt;br&gt;
The v is called a wedge it's means disjunction aka &lt;code&gt;or&lt;/code&gt; or &lt;code&gt;||&lt;/code&gt;&lt;br&gt;
The ⊃ is a horseshoe lol cute isn't it? it means implication in programming speak it's  &lt;code&gt;if(true) do: ...&lt;/code&gt;&lt;br&gt;
Lastly the ≡ is a triple bar unceremoniously. You must know this from mathematics? yes it's equivalence. Verbosely called "if and only if" In programming lingo &lt;code&gt;===&lt;/code&gt; or any operation that performs deep equality of type and value. The letters are expressions.&lt;/p&gt;

&lt;p&gt;Can you notice something wonderful?&lt;/p&gt;

&lt;p&gt;It maps almost identically &lt;code&gt;1:1&lt;/code&gt; to a programming language that is turing complete. It is just one kind of a formal language expression, like &lt;code&gt;NaCl&lt;/code&gt; or dy/dx these languages aren't like the natural language. They've done away with so much of it with their perfect rules that make them &lt;em&gt;easier&lt;/em&gt; to reason about and as always what happens when I/O comes into play? What happens when we need to create useful ideas with this tiny vocabulary of notations and make ACTUALLY useful software that expresses ideas? That is what we are, the human component. The interface between not man, but ideas and computers.&lt;/p&gt;

&lt;p&gt;What happens when the boundary of a program extends you? It gets messy. Problems. Problems and more problems. Programs create safeguards to protect you &lt;code&gt;try except catch rescue&lt;/code&gt; and what not, this is where functional programming shines. It reduces complexity by offering a stream of ideas. Returning thought not to it's messy philosophical origin of a universal object but the even more odd idea of a deterministic mechanical process. :)&lt;/p&gt;

</description>
      <category>functional</category>
      <category>paradigm</category>
      <category>agnostic</category>
      <category>monads</category>
    </item>
  </channel>
</rss>
