<?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: Aaron Christiansen</title>
    <description>The latest articles on DEV Community by Aaron Christiansen (@aaronc81).</description>
    <link>https://dev.to/aaronc81</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%2F189564%2Fa48ef256-aa00-4357-b5bc-dc9a36252e13.jpg</url>
      <title>DEV Community: Aaron Christiansen</title>
      <link>https://dev.to/aaronc81</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aaronc81"/>
    <language>en</language>
    <item>
      <title>Delta Pico - what I've learned by building a graphing calculator</title>
      <dc:creator>Aaron Christiansen</dc:creator>
      <pubDate>Sun, 23 Oct 2022 08:53:04 +0000</pubDate>
      <link>https://dev.to/aaronc81/delta-pico-what-ive-learned-by-building-a-graphing-calculator-2o44</link>
      <guid>https://dev.to/aaronc81/delta-pico-what-ive-learned-by-building-a-graphing-calculator-2o44</guid>
      <description>&lt;p&gt;This is the &lt;a href="https://github.com/AaronC81/delta-pico"&gt;Delta Pico&lt;/a&gt;! It's a graphing calculator with a 2.8" colour display, running on a Raspberry Pi Pico, with software written in Rust.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IIH3sTLk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gjc929l7opk0hn03pkx6.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IIH3sTLk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gjc929l7opk0hn03pkx6.jpeg" alt='The Delta Pico. Built on a blue PCB inside a black 3D-printed case, there is a 2.8" TFT display showing a main menu, below which lies a keypad of tactile buttons.' width="880" height="1173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can evaluate expressions with a history stored in flash memory, and plot multiple graphs on an adjustable pair of axes. (You can also play a simple clone of 2048!)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oYMn_7uf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6n8680173lhzwmo7eg2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oYMn_7uf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6n8680173lhzwmo7eg2.jpg" alt="Screenshots of the Delta Pico's calculator and graphing applications." width="880" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After working on it since July 2021, I've reached a point where I'm very satisfied with this project. It has far from all the features you'd find in a commercially-available graphing calculator, but it's complete enough for me to be happy!&lt;/p&gt;

&lt;p&gt;The Delta Pico is probably the most ambitious side-project I've ever undertaken, and also the longest I've ever stuck with a personal project.&lt;/p&gt;

&lt;p&gt;This post will be a short retrospective of the project - how it evolved over time, and what I've learned along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development and Iteration
&lt;/h2&gt;

&lt;p&gt;I really like calculators! Earlier models in history showcase the introduction of computing into our daily lives, and they remain interesting today to watch how they avoid being completely swallowed up by smartphones. I've even &lt;a href="https://www.youtube.com/watch?v=fb53nr6U-Rg"&gt;given a talk about them&lt;/a&gt; for my alma-mater's computer science society.&lt;/p&gt;

&lt;p&gt;This project was a follow-on from my &lt;a href="https://github.com/AaronC81/delta-m0"&gt;Delta M0&lt;/a&gt; - a compact and much more simple calculator, based on one of STM's Cortex-M0 microcontrollers. I wanted to build the Delta Pico as a calculator more similar to the &lt;a href="https://education.ti.com/en/products/calculators/graphing-calculators/ti-nspire-cx-cas"&gt;TI-Nspire&lt;/a&gt;, &lt;a href="http://www.hp-prime.de/en/category/5-hp-prime"&gt;HP Prime&lt;/a&gt;, or the brilliant open-source &lt;a href="https://www.numworks.com/"&gt;NumWorks&lt;/a&gt; calculator.&lt;/p&gt;

&lt;p&gt;It all started on a breadboard! While working on the Delta M0, I built a generic button matrix PCB, which you can see connected to the breadboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3cxu8I1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ql751fxmf8yqprjn2do.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3cxu8I1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ql751fxmf8yqprjn2do.png" alt='A Pimoroni Pico Explorer, with a board containing many tactile buttons, and the 2.8" display, connected to its breadboard. The display is showing a mathematical expression in crude font.' width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Shortly after getting the first prototype working, I designed a PCB in KiCad and ordered it from JLCPCB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TFSHQALj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7233ydb623flhaydh31r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TFSHQALj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7233ydb623flhaydh31r.png" alt="The revision-1 Delta Pico, showing an expression on screen." width="656" height="875"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There have been three hardware revisions in total so far, though the changes have been quite minor. &lt;/p&gt;

&lt;p&gt;Instead, most of the changes have been in software. The Delta Pico's current software stack and architecture is on its &lt;em&gt;third&lt;/em&gt; iteration! It began as a PlatformIO Arduino project, since there were existing Arduino libraries for driving this ILI9341-based display, so that helped me to get up-and-running quickly. It then morphed into a Pico SDK-based project, and finally ended up as a pure embedded Rust codebase.&lt;/p&gt;

&lt;p&gt;Rust code was introduced gradually before the project became completely Rust - it started out just being for user-level applications, then I rewrote the drivers for each device in Rust too.&lt;/p&gt;

&lt;p&gt;The hardware abstraction layer (HAL) and the user software are two separate projects, which means you can run the Delta Pico's software on other hardware by just implementing a HAL for it. This allowed me to create a &lt;a href="https://github.com/AaronC81/delta-pico-sim"&gt;simulator&lt;/a&gt; to run on my computer which used the exact same software, which came in handy for debugging several times!&lt;/p&gt;

&lt;h2&gt;
  
  
  What have I learned?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mathematical editors are tricky
&lt;/h3&gt;

&lt;p&gt;The core of a calculator is the ability to input the expression you'd like to evaluate.&lt;/p&gt;

&lt;p&gt;To match the functionality that I enjoyed on other calculators I own, I wanted the Delta Pico to have "natural" input. That means your expression isn't "flat" like &lt;code&gt;sqrt(2/3)&lt;/code&gt;, it actually looks like how you'd write it on paper:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;23\sqrt{\frac{2}{3}} &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord sqrt"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class="svg-align"&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="hide-tail"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;This turned out to be a much greater challenge than I expected. While there are libraries for this, they're largely tied to the web, and aren't suitable for embedded use.&lt;/p&gt;

&lt;p&gt;After a lot of experimentation, I built &lt;a href="https://github.com/AaronC81/rbop"&gt;rbop&lt;/a&gt;, a framework for implementing mathematical editors on any platform. It's completely separate to the Delta Pico's codebase - it'll provide the input and evaluation logic, and you just need to implement however it will draw the expressions on your platform.&lt;/p&gt;

&lt;p&gt;For example, you can even write a crude editor which works in your terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8r9KD_DL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u3xt2ubfmg8zensdyl5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8r9KD_DL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u3xt2ubfmg8zensdyl5o.png" alt="A mathematical expression being edited in a terminal." width="324" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means that rbop is completely reusable if I decide to work on another calculator project.&lt;/p&gt;

&lt;p&gt;rbop works using two different node trees: &lt;em&gt;unstructured&lt;/em&gt;, which is looser and suited to user inputs, and &lt;em&gt;structured&lt;/em&gt;, which follows a tight structure ready for evaluation. Unstructured node trees can be &lt;em&gt;upgraded&lt;/em&gt; to structured ones using a parsing step. Both node trees can be rendered by recursively transforming them into a sequence of glyphs, which are then handed off to platform-provided code to draw them to the screen.&lt;/p&gt;

&lt;p&gt;I might write more about how rbop works in the future - I found it fascinating to implement, and wasn't able to find other projects aiming for the same goals, so hopefully this could be useful going forward.&lt;/p&gt;

&lt;h3&gt;
  
  
  Embedded Rust isn't quite mature
&lt;/h3&gt;

&lt;p&gt;Writing Rust for an embedded platform is a rocky experience, especially if you aren't too familiar with the language itself when starting out, which was the case for me.&lt;/p&gt;

&lt;p&gt;For the uninitiated, a key Rust feature is the &lt;em&gt;borrow checker&lt;/em&gt;, which essentially enforces that data can only be owned in one place at a time. You can create references to data, but the borrow checker must know how long they'll exist, which isn't always easy to specify.&lt;/p&gt;

&lt;p&gt;The borrow checker enables Rust to insert memory allocations and deallocations at compile-time, rather than needing a garbage collector which would be impractical on an embedded system.&lt;/p&gt;

&lt;p&gt;Rust's standard model for embedded development treats the peripherals of a microcontroller as data with an owner. This means that it's very tricky to share peripherals between multiple drivers in a way that the borrow checker is happy with. &lt;/p&gt;

&lt;p&gt;The Delta Pico's keypad, flash storage, and display drivers all need to be able to access the clock peripheral to use delays. How do you model this?&lt;/p&gt;

&lt;p&gt;The difficulty of working around the borrow checker has led to me writing what might be the &lt;a href="https://github.com/AaronC81/delta-pico/blob/19dff6e640bb5af155e80217cc4cf07ca5f600c9/rust-hal/src/main.rs#L36-L49"&gt;worst Rust function I will ever write&lt;/a&gt;, to completely subvert Rust's referencing restrictions. I'm sorry, &lt;a href="https://rustacean.net/"&gt;Ferris&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The library ecosystem is also currently far from what you have available when writing C or C++. As a Pico SDK project, the Delta Pico implemented USB mass storage using &lt;a href="https://github.com/hathach/tinyusb"&gt;TinyUSB&lt;/a&gt;, so it would show us a storage device when connected to a computer. Unfortunately, I wasn't able to find a suitable Rust replacement for this when migrating the codebase.&lt;/p&gt;

&lt;p&gt;At least, thanks to the community, the breadth of embedded libraries available is &lt;a href="https://crates.io/categories/embedded?sort=new"&gt;constantly getting bigger&lt;/a&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  Trying new stacks is fun
&lt;/h3&gt;

&lt;p&gt;I had wanted to properly sink my teeth into Rust for a while, and this project was the perfect opportunity to do so. Rewriting parts of a familiar project in a different language was a useful learning experience.&lt;/p&gt;

&lt;p&gt;That said, it also encouraged some unhealthy habits. The Delta Pico codebase is littered with patterns which would be considered poor Rust idioms, so that things just work the way they used to.&lt;/p&gt;

&lt;p&gt;Now that I know more, I could likely go back and update everything to be more Rust-like, but that's not exactly my idea of fun! I have refactored the software for this project enough times already.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Raspberry Pi Pico is a wonderful platform
&lt;/h3&gt;

&lt;p&gt;Time and time again, I was impressed by the Raspberry Pi Pico microcontroller that I chose as the core of this project.&lt;/p&gt;

&lt;p&gt;The form factor is great, it has a tonne of RAM (important for a 240x320 colour frame buffer), and the documentation is leagues ahead of other microcontrollers I've used.&lt;/p&gt;

&lt;p&gt;Having already risen to being a ubiquitous choice among makers, the &lt;a href="https://github.com/rp-rs/rp-hal"&gt;Rust bindings&lt;/a&gt; for the platform are very complete too.&lt;/p&gt;

&lt;p&gt;The Pico will absolutely be my default choice of microcontroller for new projects!&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;I got into electronics about seven years ago now, starting off with little sensor projects using an Arduino Uno kit, and I've been dabbling in the occasional project ever since. I also picked up PCB design during the first COVID-19 lockdown, and built a &lt;a href="https://github.com/AaronC81/bfg"&gt;simple function generator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have to admit that I'm really proud of the Delta Pico - this is exactly the kind of project that I wanted to be able to create when I bought my first electronics kit those years ago. The fact I've finally done it is an incredibly rewarding feeling.&lt;/p&gt;

&lt;p&gt;Going forward, I'm excited to continue extending the Delta Pico, and start working on new projects too!&lt;/p&gt;

&lt;p&gt;If you'd like to take a look at the Delta Pico's hardware or software, check out the &lt;a href="https://github.com/AaronC81/delta-pico"&gt;GitHub repository&lt;/a&gt;, where you'll find the Rust codebase and KiCad project.&lt;/p&gt;

</description>
      <category>electronics</category>
      <category>rust</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Elixir's bitstrings - the data type I didn't know I wanted</title>
      <dc:creator>Aaron Christiansen</dc:creator>
      <pubDate>Fri, 17 Dec 2021 18:24:50 +0000</pubDate>
      <link>https://dev.to/aaronc81/elixirs-bitstrings-the-data-type-i-didnt-know-i-wanted-2842</link>
      <guid>https://dev.to/aaronc81/elixirs-bitstrings-the-data-type-i-didnt-know-i-wanted-2842</guid>
      <description>&lt;p&gt;After hearing a lot about it within the Ruby community, I'm working through this year's &lt;a href="https://adventofcode.com/"&gt;Advent of Code&lt;/a&gt; in Elixir. &lt;/p&gt;

&lt;p&gt;Overall, I'm enjoying Elixir so far! I've found that Ruby knowledge has helped me to get to grips with Elixir rather quickly - their syntax is very similar, and I'm able to make educated guesses on the names of Elixir functions coming from Ruby too. By far the most challenging part of learning Elixir has been solving the Advent of Code problems in a functional, immutable style.&lt;/p&gt;

&lt;p&gt;But in this post, I want to focus on one specific part of Elixir: bitstrings. These were invaluable for solving &lt;a href="https://adventofcode.com/2021/day/16"&gt;Day 16 of Advent of Code&lt;/a&gt;, which involved parsing packets made up of tightly-packed bit-level structures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thinking About Strings
&lt;/h2&gt;

&lt;p&gt;Let's step back from bitstrings and think about regular old &lt;em&gt;strings&lt;/em&gt; of text. Here's one:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;In memory, a string will actually be a sequence of bytes (with a length attached somehow, not shown here):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;" h    e    l    l    o    "
  0x68 0x65 0x6c 0x6c 0x6f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many interpreted languages, such as Python, have separate &lt;code&gt;str&lt;/code&gt; and &lt;code&gt;bytes&lt;/code&gt; types for differentiating between text and an arbitrary list of bytes.&lt;/p&gt;

&lt;p&gt;But, Elixir makes no such distinction! Strings are simply an instance of a type called a &lt;strong&gt;binary&lt;/strong&gt;, which is a list of bytes with a length attached. You can create a binary using &lt;code&gt;&amp;lt;&amp;lt; &amp;gt;&amp;gt;&lt;/code&gt; syntax - notice that Elixir's prints both of these inputs in the same way (using &lt;code&gt;IO.inspect&lt;/code&gt;, Elixir's equivalent of Ruby's &lt;code&gt;p&lt;/code&gt; or Python's &lt;code&gt;repr&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="s2"&gt;"hello"&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "hello"&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mh"&gt;0x68&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x6c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x6f&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's because they are the same underlying data type, and the double-quotes are really just a shortcut for creating a binary from some characters.&lt;/p&gt;

&lt;p&gt;Elixir is printing it back to us as a string for our convenience, because it can see that the binary is made up of printable Unicode characters. If we create a binary of unprintable characters instead, it'll display it as a binary rather than a string:&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="o"&gt;&amp;lt;&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="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="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; &amp;lt;&amp;lt; 1, 2, 3 &amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, so we've got a type which can store some bytes. But how's this special at all, when you can simply create an array or vector of bytes in most languages?&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Bitstrings
&lt;/h2&gt;

&lt;p&gt;In Elixir, binaries are not really their own data type. A binary is actually a special case of the real data type, called a &lt;strong&gt;bitstring&lt;/strong&gt;. A bitstring is a binary if the number of bits is divisible by 8.&lt;/p&gt;

&lt;p&gt;This is the special part! Most languages I've worked with don't provide facilities for seamlessly working with data whose size isn't a whole number of bytes, but in Elixir we can use bitstrings to work with &lt;em&gt;any number of bits&lt;/em&gt;, not necessarily divisible by 8 into bytes.&lt;/p&gt;

&lt;p&gt;Bitstrings are constructed using the same &lt;code&gt;&amp;lt;&amp;lt; &amp;gt;&amp;gt;&lt;/code&gt; syntax, but we can tag each component with its size in bits. For example:&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="o"&gt;&amp;lt;&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="n"&gt;size&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;6&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;size&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;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; &amp;lt;&amp;lt; 19::size(6) &amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;size&lt;/code&gt; can be omitted as a shorthand, allowing us to just enter &lt;code&gt;&amp;lt;&amp;lt; 1 :: 2, 6 :: 4 &amp;gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Elixir does concatenate these two components together into a single 6-bit field, but that doesn't matter, since the bit-level representation in memory remains the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Original:   1       3
               .-.   .-----.
               0 1   0 0 1 1
               '-----------'
Concatenated:       19
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Working With Bitstrings
&lt;/h2&gt;

&lt;p&gt;We can use bitstrings to easily construct data structures at the bit level, from individual components. But their real power comes from when we want to do the opposite, and &lt;em&gt;deconstruct&lt;/em&gt; data into its bits.&lt;/p&gt;

&lt;p&gt;This is the best part: bitstrings support Elixir's pattern matching! Let's try pulling apart that example from earlier using pattern matching:&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="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like that, we can extract arbitrarily-sized integers from bitstrings!&lt;/p&gt;

&lt;p&gt;The equivalent using most programming language's bitwise operators would be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;b110000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;b11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my opinion, Elixir's pattern matching approach shows intention much better and is less error-prone. (Elixir does have bitwise operators those, so you can fall back to them if you like!)&lt;/p&gt;

&lt;p&gt;Pattern matching allows us to do even more advanced things. Instead of &lt;code&gt;:: size(x)&lt;/code&gt; or &lt;code&gt;:: x&lt;/code&gt;, we can use the &lt;code&gt;:: bitstring&lt;/code&gt; specifier to match a chunk of any size. For example, given some input data of any unknown size, we could split apart the first two bits and the remaining bits:&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="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;bitstring&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;243&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 3&lt;/span&gt;
&lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; &amp;lt;&amp;lt; 204, 48::size(6) &amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(This particular application was where they were most useful in Advent of Code!)&lt;/p&gt;

&lt;p&gt;For a final example, let's combine this with Elixir's pattern matching on method definitions, to define a method which counts the number of 1 bits in a bitstring:&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;# If the next bit is 1, count it and recurse&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;count_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;bitstring&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;count_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# If the next bit is 0, don't count it and recurse&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;count_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;bitstring&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;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="n"&gt;count_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Base case: if bits have run out, stop&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;count_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;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="mi"&gt;0&lt;/span&gt;

&lt;span class="c1"&gt;# Let's try it out...&lt;/span&gt;
&lt;span class="n"&gt;count_bits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; 5&lt;/span&gt;
&lt;span class="c1"&gt;# That's right! 55 is 0b00110111&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope you've found this to be an interesting look at bitstrings, and that you can see their value for certain problems! Although libraries with similar functionality are available for other languages, I doubt any of them will manage to achieve the same level of language integration with pattern matching that Elixir accomplishes.&lt;/p&gt;

&lt;p&gt;Even if you aren't too familiar with Elixir, you may find it interesting to have a skim through my &lt;a href="https://github.com/AaronC81/advent-of-code-2021/blob/main/lib/day16.exs"&gt;Advent of Code Day 16 solution&lt;/a&gt; to find how I've used bitstrings to deconstruct the puzzle input.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>adventofcode</category>
    </item>
    <item>
      <title>Removing functionality the Ruby way - a look into SortedSet on Ruby 3</title>
      <dc:creator>Aaron Christiansen</dc:creator>
      <pubDate>Wed, 30 Dec 2020 21:17:26 +0000</pubDate>
      <link>https://dev.to/aaronc81/removing-functionality-the-ruby-way-a-look-into-sortedset-on-ruby-3-clf</link>
      <guid>https://dev.to/aaronc81/removing-functionality-the-ruby-way-a-look-into-sortedset-on-ruby-3-clf</guid>
      <description>&lt;p&gt;Ruby 3 has just released - hooray! But naturally, some of my code hit problems with Ruby 3's breaking changes.&lt;/p&gt;

&lt;p&gt;Almost all of these were related to &lt;a href="https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/"&gt;Ruby 3's changes to how keyword arguments are handled&lt;/a&gt;, but I also had &lt;a href="https://github.com/AaronC81/sord/pull/123"&gt;an intriguing issue&lt;/a&gt; reported on my Sord type generation project.&lt;/p&gt;

&lt;p&gt;Ruby used to include a &lt;code&gt;SortedSet&lt;/code&gt; class, but it's been removed from Ruby 3 for "dependency and performance reasons". Suppose we try to use it...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main)&amp;gt; SortedSet
RuntimeError (The `SortedSet` class has been extracted from the `set` library.You must use the `sorted_set` gem or other alternatives.)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Woah, what's that error message!? That's not usually what we see when we try to use a constant which doesn't exist. You'd expect to get something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NameError (uninitialized constant SortedSet)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;SortedSet&lt;/code&gt; gives us a much more useful error message.&lt;/p&gt;

&lt;p&gt;How does Ruby do this? Let's take a look!&lt;/p&gt;




&lt;p&gt;My first guess was that Ruby 3 replaced the &lt;code&gt;SortedSet&lt;/code&gt; class with a &lt;code&gt;SortedSet&lt;/code&gt; &lt;em&gt;method&lt;/em&gt; which throws an exception. It's not unusual for the Ruby &lt;code&gt;Kernel&lt;/code&gt; to have &lt;a href="https://ruby-doc.org/core-2.7.2/Kernel.html#method-i-Array"&gt;methods which look like classes&lt;/a&gt;, so I thought this was a pretty good guess. But nope, there isn't any &lt;code&gt;SortedSet&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main)&amp;gt; method(:SortedSet)
NameError (undefined method `SortedSet' for class `#&amp;lt;Class:#&amp;lt;Object:0x000056382e0a84c8&amp;gt;&amp;gt;')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;To dig a bit deeper, I took a look at the &lt;a href="https://github.com/ruby/ruby"&gt;Ruby interpreter source code&lt;/a&gt;. The &lt;a href="https://github.com/ruby/ruby/blob/master/lib/set.rb"&gt;&lt;code&gt;lib/set.rb&lt;/code&gt;&lt;/a&gt; file revealed the answer:&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="nb"&gt;autoload&lt;/span&gt; &lt;span class="ss"&gt;:SortedSet&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;__dir__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/set/sorted_set"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;SortedSet&lt;/code&gt; is now defined with &lt;code&gt;autoload&lt;/code&gt;. Referencing &lt;code&gt;SortedSet&lt;/code&gt; will require the given file to try and resolve that constant, acting as a kind of lazy-loading within a Ruby program.&lt;/p&gt;

&lt;p&gt;Sure enough, the useful exception we were seeing is thrown by the &lt;a href="https://github.com/ruby/ruby/blob/master/lib/set/sorted_set.rb"&gt;&lt;code&gt;sorted_set&lt;/code&gt;&lt;/a&gt; file which &lt;code&gt;autoload&lt;/code&gt; points to:&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="k"&gt;begin&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'sorted_set'&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;LoadError&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"The `SortedSet` class has been extracted from the `set` library."&lt;/span&gt; &lt;span class="p"&gt;\&lt;/span&gt;
        &lt;span class="s2"&gt;"You must use the `sorted_set` gem or other alternatives."&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;This is a really clever way of providing useful error messages when functionality is broken out or removed, which I personally haven't seen before! &lt;/p&gt;

&lt;p&gt;There is one quirk with it though, and it's the cause of the bug which made me look into this in the first place.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SortedSet&lt;/code&gt; is still a constant, so &lt;code&gt;Object.constants&lt;/code&gt; contains it. But accessing this constant isn't always safe if you don't have the &lt;code&gt;sorted_set&lt;/code&gt; gem. This means that iterating over all available constants can throw an exception!&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="no"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&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;c&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="no"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;const_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&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;# =&amp;gt; KeyError&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; Thread::Queue&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; IndexError&lt;/span&gt;
&lt;span class="c1"&gt;# ...etc, until boom!&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; RuntimeError (The `SortedSet` class has been extracted from the `set` library.You must use the `sorted_set` gem or other alternatives.)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can see this being a problem in some heavily-metaprogrammed environments, just like it was for Sord.&lt;/p&gt;




&lt;p&gt;For what's basically just a custom error message, I found this approach to the removal of &lt;code&gt;SortedSet&lt;/code&gt; interesting to think about.&lt;/p&gt;

&lt;p&gt;Is breaking a common assumption like "reading a constant which exists won't throw an exception" worthwhile when it might help out the developer?&lt;/p&gt;

&lt;p&gt;Or, on the other hand, is consistency key to maximise the effectiveness of Ruby's metaprogramming? Do edge cases like this introduce complexity which makes the internals of Ruby more difficult to understand?&lt;/p&gt;

&lt;p&gt;Personally I think this minor touch is a great design decision in Ruby 3, even if it did introduce a bug that had to be solved. If you have any other thoughts, I'd be interested to hear them!&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>"yes_i_did" - A tiny gem to rerun your last IRB command with the "did you mean" suggestion if you make a typo</title>
      <dc:creator>Aaron Christiansen</dc:creator>
      <pubDate>Sun, 05 Apr 2020 10:39:11 +0000</pubDate>
      <link>https://dev.to/aaronc81/yesidid-a-tiny-gem-to-rerun-your-last-irb-command-with-the-did-you-mean-suggestion-if-you-make-a-typo-2o65</link>
      <guid>https://dev.to/aaronc81/yesidid-a-tiny-gem-to-rerun-your-last-irb-command-with-the-did-you-mean-suggestion-if-you-make-a-typo-2o65</guid>
      <description>&lt;p&gt;I've written a tiny gem called &lt;a href="https://github.com/AaronC81/yes_i_did"&gt;yes_i_did&lt;/a&gt; which adds a new method to your IRB session, &lt;code&gt;yes&lt;/code&gt;. If you didn't quite get the name of something right in a command, simply invoke &lt;code&gt;yes&lt;/code&gt; to rerun it with the typo fixed using the "did you mean" suggestion!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0cH7b3oS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kbwctzhpsttc7wmsby6t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0cH7b3oS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kbwctzhpsttc7wmsby6t.png" alt='Example of the utility in use. Running "yes" replaces a typoed usage of "append" with the correct spelling and reruns the command.'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setup is simple: just install the gem and require it in your &lt;code&gt;~/.irbrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This has already proven a handy time-saver for me, and I hope it can be for you too! &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Flashing your PineTime using an ST-Link and OpenOCD</title>
      <dc:creator>Aaron Christiansen</dc:creator>
      <pubDate>Tue, 07 Jan 2020 21:34:34 +0000</pubDate>
      <link>https://dev.to/aaronc81/flashing-your-pinetime-using-an-st-link-and-openocd-54dd</link>
      <guid>https://dev.to/aaronc81/flashing-your-pinetime-using-an-st-link-and-openocd-54dd</guid>
      <description>&lt;p&gt;The &lt;a href="https://www.pine64.org/pinetime/"&gt;PineTime development kits&lt;/a&gt; are now shipping out, and to do anything interesting with yours, you'll probably be looking to flash a firmware on to it.&lt;/p&gt;

&lt;p&gt;With open-source tool OpenOCD and a cheap ST-Link programmer, it's really easy to flash firmware once you know what to do!&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;There are a few things you need to do before you can follow this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You'll need to solder wires onto your PineTime's SWD pins so that you can connect it to a programmer (or a Pi to unlock it - see below). See the &lt;a href="https://wiki.pine64.org/index.php/PineTime"&gt;wiki page&lt;/a&gt; for a diagram of which pin is which. (Some people have had success with just resting the pins in the holes on the board and not soldering them there, but I haven't tried this.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You &lt;strong&gt;must&lt;/strong&gt; remove the flash protection your PineTime before you can flash it. It's possible to do this using a J-Link, but they are very expensive. Fortunately, you can also do it with a Raspberry Pi; follow the &lt;em&gt;Remove nRF52 Flash Protection with Raspberry Pi&lt;/em&gt; section of &lt;a href="https://medium.com/@ly.lee/coding-nrf52-with-rust-and-apache-mynewt-on-visual-studio-code-9521bcba6004"&gt;Lup Yuen Lee's fantastic guide&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need an ST-Link programmer; I use &lt;a href="https://www.amazon.co.uk/gp/product/B07QBLNDPM"&gt;this cheap clone from Amazon UK&lt;/a&gt;. If you haven't yet used an ST-Link on your Linux installation, you'll need udev rules: I followed &lt;a href="https://fishpepper.de/2016/09/16/installing-using-st-link-v2-to-flash-stm32-on-linux/"&gt;this guide&lt;/a&gt; to add mine.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Building OpenOCD
&lt;/h1&gt;

&lt;p&gt;The build of OpenOCD you can get from your package manager might not work for our purposes, as it probably hasn't been built with CMSIS-DAP support. We'll build it from source using a GitHub mirror instead.&lt;/p&gt;

&lt;p&gt;On Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/ntfreak/openocd
cd openocd
./bootstrap
./configure --enable-cmsis-dap
make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give you an OpenOCD executable inside the repo at &lt;code&gt;src/openocd&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuring OpenOCD
&lt;/h1&gt;

&lt;p&gt;You'll need a configuration file to tell OpenOCD to connect to your ST-Link, and tell it what kind of chip we'll be debugging. Save this in &lt;code&gt;nrf52.cfg&lt;/code&gt;, at the root of your OpenOCD repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source [find interface/stlink.cfg]
transport select hla_swd
source [find target/nrf52.cfg]
init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Starting OpenOCD
&lt;/h1&gt;

&lt;p&gt;Now we can start an OpenOCD server with our configuration! Run this in the repo root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./src/openocd -s tcl -f nrf52.cfg -d3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-s tcl&lt;/code&gt; tells OpenOCD to look for files it needs in the &lt;code&gt;tcl&lt;/code&gt; directory, such as the &lt;code&gt;interface/stlink.cfg&lt;/code&gt; we specified in our config. &lt;code&gt;-f nrf52.cfg&lt;/code&gt; runs our configuration file on OpenOCD, and &lt;code&gt;-d3&lt;/code&gt; prints the maximum amount of debugging information so it's easier to diagnose any issues.&lt;/p&gt;

&lt;h1&gt;
  
  
  Connecting to OpenOCD
&lt;/h1&gt;

&lt;p&gt;After starting OpenOCD, we now have a telnet server on port 4444 which we can connect to in order to issue commands to our ST-Link. Connect with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;telnet localhost 4444
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll get some preamble and a prompt which should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trying ::1...
Connection failed: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two commands to check to ensure your chip is detected. &lt;code&gt;targets&lt;/code&gt; should show one device, and &lt;code&gt;flash banks&lt;/code&gt; should show two results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; targets
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* nrf52.cpu          hla_target little nrf52.cpu          running

&amp;gt; flash banks
#0 : nrf52.flash (nrf5) at 0x00000000, size 0x00000000, buswidth 1, chipwidth 1
#1 : nrf52.uicr (nrf5) at 0x10001000, size 0x00000000, buswidth 1, chipwidth 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks good!&lt;/p&gt;

&lt;h1&gt;
  
  
  Flashing
&lt;/h1&gt;

&lt;p&gt;Flashing a firmware is now pretty easy. First, we want to ensure that our PineTime is stopped:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; reset halt
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000462 msp: 0x20000800

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may want to clear the PineTime's firmware before flashing a new one. This &lt;em&gt;should&lt;/em&gt; happen as part of the programming process, but if you want to do it explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; nrf51 mass_erase
nRF52832-QFAA(build code: E0) 512kB Flash, 64kB RAM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the actual flash! Give the path you'd like to program. Note that this path is relative from where you ran OpenOCD, not where you ran telnet, so you'll probably want to give an absolute path here. Make sure you also include the &lt;code&gt;verify reset&lt;/code&gt; at the end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; program /home/aaron/projects/pinetime/app.bin verify reset
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffc
** Programming Started **
Adding extra erase range, 0x00005d2c .. 0x00005fff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're all done! If your PineTime didn't restart for some reason, you can always reset it and kick it off with a command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; reset run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Need a pre-built firmware?
&lt;/h1&gt;

&lt;p&gt;Want to make sure you can flash your PineTime, but haven't got round to building a firmware yet? I've built a simple firmware on &lt;a href="https://github.com/aykevl/go-smartwatch"&gt;go-smartwatch&lt;/a&gt; which should show "Hello!" on your PineTime's display.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stuff.aaronc.cc/uploads/hello.bin"&gt;&lt;strong&gt;Download the pre-built firmware here!&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Taking pattern matching further in Ruby 2.7</title>
      <dc:creator>Aaron Christiansen</dc:creator>
      <pubDate>Sun, 22 Dec 2019 23:11:23 +0000</pubDate>
      <link>https://dev.to/aaronc81/taking-pattern-matching-further-in-ruby-2-7-4k38</link>
      <guid>https://dev.to/aaronc81/taking-pattern-matching-further-in-ruby-2-7-4k38</guid>
      <description>&lt;p&gt;With Ruby 2.7 just around the corner, and release candidate 2 &lt;a href="https://www.ruby-lang.org/en/news/2019/12/21/2-7-0-rc2-released/"&gt;available now&lt;/a&gt;, I was eager to try the new pattern matching feature that has been introduced. As with anything in Ruby, I wanted to see how I could push this feature to its limits.&lt;/p&gt;

&lt;p&gt;Note that this is not an introduction to Ruby 2.7's pattern matching; make sure you're already familiar with its purpose and how to use it. The &lt;a href="https://www.ruby-lang.org/en/news/2019/12/21/2-7-0-rc2-released/"&gt;release notes&lt;/a&gt; summarise this very well!&lt;/p&gt;

&lt;h1&gt;
  
  
  How does pattern matching work?
&lt;/h1&gt;

&lt;p&gt;There are two main methods involved with the behaviour behind pattern matching, &lt;code&gt;#deconstruct&lt;/code&gt; and &lt;code&gt;#deconstruct_keys&lt;/code&gt;, which are used for array-style matches and hash-style matches respectively.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#deconstruct&lt;/code&gt; returns an array representing the object which can be matched against. For the &lt;code&gt;Array&lt;/code&gt; class, this is simply aliased to &lt;code&gt;#itself&lt;/code&gt;, as no conversion needs to be done here. Instances of &lt;code&gt;Struct&lt;/code&gt; define &lt;code&gt;#deconstruct&lt;/code&gt; as an array of the field values.&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="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="nf"&gt;deconstruct&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; [1, 2, 3]&lt;/span&gt;

&lt;span class="no"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Struct&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="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:favourite_food&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;Person&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="s1"&gt;'Aaron'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Pizza'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;deconstruct&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; ['Aaron', 'Pizza']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;#deconstruct_keys&lt;/code&gt; is similar, except it returns a hash rather than an array. Additionally, &lt;code&gt;#deconstruct_keys&lt;/code&gt; takes an array of Symbol keys as an argument, indicating which keys of the hash must be returned. It is permitted to a hash with more keys than specified (&lt;code&gt;Hash#deconstruct_keys&lt;/code&gt; is aliased to &lt;code&gt;#itself&lt;/code&gt; so returns all keys) but the additional keys won't be used for the pattern match.&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="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;a: &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;b: &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;deconstruct_keys&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="ss"&gt;:a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:b&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; { a: 3, b: 4 }&lt;/span&gt;

&lt;span class="no"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Struct&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="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:favourite_food&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Person&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="s1"&gt;'Aaron'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Pizza'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deconstruct_keys&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; { name: 'Aaron' }&lt;/span&gt;
&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deconstruct_keys&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:favourite_food&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; { name: 'Aaron', favourite_food: 'Pizza' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  As the &lt;code&gt;case&lt;/code&gt; may be...
&lt;/h1&gt;

&lt;p&gt;I was surprised to learn that you don't actually need to use the &lt;code&gt;in&lt;/code&gt; operator for pattern matching within a &lt;code&gt;case&lt;/code&gt; statement; you can use it anywhere! This can be used to unpack structs quite elegantly:&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="no"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Struct&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="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:favourite_food&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Person&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="s1"&gt;'Aaron'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Pizza'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;me&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;my_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;favourite_food: &lt;/span&gt;&lt;span class="n"&gt;my_favourite_food&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;my_name&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 'Aaron'&lt;/span&gt;
&lt;span class="n"&gt;my_favourite_food&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 'Pizza'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even use it as a slightly esoteric form of assertion, as a pattern which doesn't match will raise a &lt;code&gt;NoMatchingPatternError&lt;/code&gt;. I'm not sure I'd recommend this, but it certainly works!&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="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="c1"&gt;# Fine!&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;# Raises NoMatchingPatternError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In its most basic form, you can even use pattern matching as a simple assignment. I wonder if DSLs could make use of this?&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="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  A methodical approach
&lt;/h1&gt;

&lt;p&gt;This was inspired by &lt;a href="https://medium.com/@baweaver/ruby-2-7-pattern-matching-first-impressions-cdb93c6246e6"&gt;Brandon Weaver's excellent post&lt;/a&gt; about pattern matching. Being able to match against objects which define &lt;code&gt;#deconstruct&lt;/code&gt; or &lt;code&gt;#deconstruct_keys&lt;/code&gt; is great, but what about any other objects where properties are behind methods?&lt;/p&gt;

&lt;p&gt;It's really easy to create a wrapper around any object which will dynamically invoke methods on it when &lt;code&gt;#deconstruct_keys&lt;/code&gt; is called, allowing any object's zero-argument methods to be used in pattern matching!&lt;/p&gt;

&lt;p&gt;Let's create an example of how this will help us first. I'll define a simple data class:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Rectangle&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;
    &lt;span class="vi"&gt;@height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:height&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;code&gt;Rectangle#width&lt;/code&gt; and &lt;code&gt;Rectangle#height&lt;/code&gt; are methods which will retrieve the properties of any instances of &lt;code&gt;Rectangle&lt;/code&gt;. Unfortunately, pattern matching doesn't know how to match against instances of this class, as it doesn't contain a &lt;code&gt;#deconstruct_keys&lt;/code&gt; definition:&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="n"&gt;rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rectangle&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="mi"&gt;2&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="n"&gt;rect&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;width: &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Raises NoMatchingPatternError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's define a class which can wrap any object in to allow method calls to be made from a pattern match. I'll call it &lt;code&gt;SendMatch&lt;/code&gt;:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendMatch&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;deconstruct_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_h&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@target&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="n"&gt;key&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How this works is actually really simple. When constructed, it takes a single object and stores a reference to it as an instance variable &lt;code&gt;@target&lt;/code&gt;. Then, when &lt;code&gt;#deconstruct_keys&lt;/code&gt; is called, it invokes each the methods with the names of each requested key on &lt;code&gt;@target&lt;/code&gt; and creates a hash from the results.&lt;/p&gt;

&lt;p&gt;This effectively lets pattern matching work on any object!&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="n"&gt;rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rectangle&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="mi"&gt;2&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="no"&gt;SendMatch&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="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;width: &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 2&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could make this even more concise by monkey-patching &lt;code&gt;Object&lt;/code&gt;, so classes without a definition of &lt;code&gt;#deconstruct_keys&lt;/code&gt; will automatically call methods instead:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;deconstruct_keys&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="no"&gt;SendMatch&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="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;deconstruct_keys&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;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;rect&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;width: &lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 2&lt;/span&gt;
&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I hope this has given you a good insight into how pattern matching can be used in creative ways in Ruby 2.7! Remember that pattern matching is still an experimental feature, so any of these behaviours could change at any time.&lt;/p&gt;

&lt;p&gt;I'd love to hear about how you're using pattern matching to streamline your Ruby code!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>functional</category>
    </item>
    <item>
      <title>Getting the most out of Ruby strings</title>
      <dc:creator>Aaron Christiansen</dc:creator>
      <pubDate>Tue, 29 Oct 2019 23:14:22 +0000</pubDate>
      <link>https://dev.to/aaronc81/getting-the-most-out-of-ruby-strings-82p</link>
      <guid>https://dev.to/aaronc81/getting-the-most-out-of-ruby-strings-82p</guid>
      <description>&lt;p&gt;Ruby has a fantastic set of methods on its built-in &lt;code&gt;String&lt;/code&gt; class, and it's really useful to know how to use them. This will go over some which you might not have heard of!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; All these methods are from Ruby 2.6.5, and they're all from the standard library; no Active Support required!&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;code&gt;String#+@&lt;/code&gt; and &lt;code&gt;String#-@&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Strings in Ruby support both the unary plus (&lt;code&gt;+&lt;/code&gt;) and minus (&lt;code&gt;-&lt;/code&gt;) operators.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;+&lt;/code&gt; operator will return a "thaw" a frozen string, returning a mutable copy of it. If the string was already mutable, it has no effect.&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase!&lt;/span&gt; &lt;span class="c1"&gt;# Throws: FrozenError (can't modify frozen String)&lt;/span&gt;

&lt;span class="c1"&gt;# Now, let's thaw the string first...&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase!&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-&lt;/code&gt; operator does the opposite, returning a frozen copy of the string. Note that, if a frozen instance of that particular string already exists in Ruby's object pool, it'll return that instance instead.&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase!&lt;/span&gt; &lt;span class="c1"&gt;# This is fine - our string isn't frozen yet&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upcase!&lt;/span&gt; &lt;span class="c1"&gt;# Throws: FrozenError (can't modify frozen String)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even combine these two operators for a terse (but horrible) string duplication operator. (Please use &lt;code&gt;#dup&lt;/code&gt; over this, though!)&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;+-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gsub!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Hallo"&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The many uses of &lt;code&gt;String#[]&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;The square-braces indexing syntax on strings has a gigantic range of use cases in Ruby. Here are the more typical ones you've probably seen before, which involve passing in numbers or ranges.&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="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;    &lt;span class="c1"&gt;# Get the character at index 0             =&amp;gt; "H"&lt;/span&gt;
&lt;span class="n"&gt;a&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="c1"&gt;# Get 3 characters, starting from index 2  =&amp;gt; "llo"&lt;/span&gt;
&lt;span class="n"&gt;a&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;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# Get the characters between index 1 and 3 =&amp;gt; "ell"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did you know that you can also pass in a regex to get the part of the string which matches it? If there are multiple matches, this will always return the first match.&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="s2"&gt;"foo bar baz"&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/b../&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "bar"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even use capture groups in your regex, and pass an index to specify which capture group to return:&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="s2"&gt;"foo bar baz"&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/b(..)/&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="c1"&gt;# =&amp;gt; "ar"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, you can pass a string as an index and it will act like &lt;code&gt;include?&lt;/code&gt;, except returning the original search string if it was found and &lt;code&gt;nil&lt;/code&gt; if it was not found.&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="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"foo bar baz"&lt;/span&gt;

&lt;span class="c1"&gt;# String#include? returns a boolean&lt;/span&gt;
&lt;span class="n"&gt;s&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="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;span class="n"&gt;s&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="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; false&lt;/span&gt;

&lt;span class="c1"&gt;# String#[] with a string argument returns a string or nil&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="c1"&gt;# =&amp;gt; "bar"&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even better, all of these work with indexed assignment too, so you can replace specific parts of your string effortlessly!&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="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"foo bar baz"&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/b../&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "foo hello baz"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;code&gt;String#tr&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;tr&lt;/code&gt; method on strings translates one set of characters into another.&lt;/p&gt;

&lt;p&gt;When called on a string and given two arguments, it maps characters from the first argument found in the string to the corresponding characters in the second argument.&lt;/p&gt;

&lt;p&gt;This method is best explained with an example. Suppose we want to replace all occurrences of &lt;code&gt;.&lt;/code&gt; with &lt;code&gt;!&lt;/code&gt;, and vice versa. We could use the following &lt;code&gt;tr&lt;/code&gt; call.&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="s2"&gt;"Foo. Bar!"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"!."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;".!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Foo! Bar."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can also be used to map ranges of characters onto one character, or onto another range. A caret (&lt;code&gt;^&lt;/code&gt;) can be used as a "not" operator, too.&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="s2"&gt;"abcdef"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a-d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# =&amp;gt; "xxxxef"&lt;/span&gt;
&lt;span class="s2"&gt;"abcdef"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a-d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"w-z"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "wxyzef"&lt;/span&gt;
&lt;span class="s2"&gt;"abcdef"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"^a-d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# =&amp;gt; "abcdxx"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;String#tr&lt;/code&gt; method is a powerful method which can make fiddly string replacements much easier if used effectively! Like many string methods, it also comes with a mutating form, &lt;code&gt;String#tr!&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;String#squeeze&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;squeeze&lt;/code&gt; method removes adjacent duplicate characters in a string. By default, it will remove any characters, but it also takes an argument to select the range of characters to remove. This argument is in the same format is &lt;code&gt;#tr&lt;/code&gt;'s arguments - &lt;code&gt;-&lt;/code&gt; for ranges and &lt;code&gt;^&lt;/code&gt; for inversion.&lt;/p&gt;

&lt;p&gt;This is most useful as a flexible whitespace-removal tool, which is much easier to read than a regex.&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="s2"&gt;"aaabbaacccc"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;squeeze&lt;/span&gt;        &lt;span class="c1"&gt;# =&amp;gt; "abac"&lt;/span&gt;
&lt;span class="s2"&gt;"aaabbaacccc"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;squeeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a-b"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "abacccc"&lt;/span&gt;

&lt;span class="c1"&gt;# One of the best uses...&lt;/span&gt;
&lt;span class="s2"&gt;"Look   at all  this   whitespace!"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;squeeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "Look at all this whitespace!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I hope this has taught you something new! If you have any tips for dealing with Ruby strings effectively, leave them in a comment below.&lt;/p&gt;

</description>
      <category>ruby</category>
    </item>
    <item>
      <title>Causes - a programming language feature concept</title>
      <dc:creator>Aaron Christiansen</dc:creator>
      <pubDate>Thu, 15 Aug 2019 17:53:58 +0000</pubDate>
      <link>https://dev.to/aaronc81/causes-a-programming-language-feature-concept-2ag0</link>
      <guid>https://dev.to/aaronc81/causes-a-programming-language-feature-concept-2ag0</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;A typical programming language's standard library is often filled with methods which clearly complement each other.&lt;/p&gt;

&lt;p&gt;A clear and common relationship is between an operation method, and a predicate method which becomes true if that operation has taken place. For example, immediately after calling the &lt;code&gt;clear&lt;/code&gt; method on a Ruby &lt;code&gt;Array&lt;/code&gt; instance, the &lt;code&gt;empty?&lt;/code&gt; predicate becomes true. There are plenty of other ways to mutate an array such that it satisfies the &lt;code&gt;empty?&lt;/code&gt; predicate, but &lt;code&gt;clear&lt;/code&gt; is guaranteed to satisfy it every time with just one method call. To summarise: calling &lt;code&gt;clear&lt;/code&gt; causes &lt;code&gt;empty?&lt;/code&gt; to be true.&lt;/p&gt;

&lt;p&gt;We've now established that there's a relationship between these methods. What if we could declare relationships like this to the language, and what advantages would this bring to both the programmer and the language itself?&lt;/p&gt;

&lt;h1&gt;
  
  
  Proposing a language which includes causes
&lt;/h1&gt;

&lt;p&gt;Let's take a look at a theoretical language which allows relationships like this to be declared. We'll call these relationships &lt;em&gt;causes&lt;/em&gt;,  as calling one method &lt;em&gt;causes&lt;/em&gt; another predicate to become true.&lt;/p&gt;

&lt;p&gt;I'll be writing Ruby-style pseudocode, as implementing complex functionality like this using Ruby's metaprogramming functionality seems feasible.&lt;/p&gt;

&lt;p&gt;Here's how the &lt;code&gt;empty?&lt;/code&gt; and &lt;code&gt;clear&lt;/code&gt; methods could be declared in the &lt;code&gt;Array&lt;/code&gt; class, with a cause given for &lt;code&gt;clear&lt;/code&gt;:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;
  &lt;span class="c1"&gt;# ...other definitions...&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;empty?&lt;/span&gt;
    &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zero?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;causes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;empty?&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- Here's our defined cause&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clear&lt;/span&gt;
    &lt;span class="n"&gt;each&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;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&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;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code would associate the &lt;code&gt;empty?&lt;/code&gt; and &lt;code&gt;clear&lt;/code&gt; methods, specifying that an invocation of &lt;code&gt;clear&lt;/code&gt; causes the predicate &lt;code&gt;empty?&lt;/code&gt; to become true.&lt;/p&gt;

&lt;p&gt;This could also be extended to more complex causes relying on the arguments passed to the method. For example, if an item has just been appended to an array (using &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; in Ruby), then it must be the last item in that array.&lt;/p&gt;

&lt;p&gt;A definition of this cause could look like:&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="n"&gt;cause&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# ...array append logic...&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, the predicate is more than a simple method call - the &lt;code&gt;last&lt;/code&gt; method is invoked and has its result compared with the item to append.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is gained from doing this?
&lt;/h1&gt;

&lt;p&gt;Thinking of a method's causes seems like yet another hurdle when writing code, so why bother?&lt;/p&gt;

&lt;h2&gt;
  
  
  Effortless idempotency
&lt;/h2&gt;

&lt;p&gt;Because it is specified exactly what will happen when they're called, simple methods with causes can be called idempotently. That is, if their effect has already happened, it shouldn't happen again.&lt;/p&gt;

&lt;p&gt;Suppose you have an array of bytes called &lt;code&gt;bytes&lt;/code&gt; supplied by a user, and you're about to process it in a way which requires a null terminator to be at the end. The user may or may not have included this null terminator. In traditional Ruby code, this could be done like so:&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="n"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Introducing an idempotent call syntax into our language, where we add a &lt;code&gt;?&lt;/code&gt; prefix to the method's name, we could do this:&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="n"&gt;bytes&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is possible because, by specifying what a method causes formally, we know exactly what &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; will do and therefore can determine if it is required to call it. This particular code snippet would evaluate the predicate specified in the cause for &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt;; recall that this predicate is &lt;code&gt;|item| last == item&lt;/code&gt;. If this predicate is false, i.e. the last item is not 0, then &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; would be executed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bringing declarative programming to a procedural language
&lt;/h2&gt;

&lt;p&gt;If it is known what condition a method satisfies, then there is also the power to flip this information around. Given a condition we want to satisfy, we can find a method which causes it.&lt;/p&gt;

&lt;p&gt;Suppose we have a variety of sorting algorithms defined on the language's array type, each with a cause specified such that the array satisfies a &lt;code&gt;sorted?&lt;/code&gt; predicate after invoking them. To sort an array instance, we can write code that asks the language to satisfy the &lt;code&gt;sorted?&lt;/code&gt; predicate, using a &lt;code&gt;satisfy&lt;/code&gt; keyword:&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="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;satisfy&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sorted?&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; [2, 3, 4, 7]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The language is aware of which methods will satisfy the &lt;code&gt;sorted?&lt;/code&gt; predicate and can select one accordingly, perhaps using an intelligent interpreter which tries each candidate method over time and establishes which method is faster for particular instances.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra assertions for free
&lt;/h2&gt;

&lt;p&gt;Each cause could optionally act as a postcondition assertion, where it runs after the associated method has been invoked. This is similar to the contract features built into Eiffel or D. For instance, in the &lt;code&gt;clear&lt;/code&gt; and &lt;code&gt;empty?&lt;/code&gt; example, the language will verify that the list really is empty when &lt;code&gt;clear&lt;/code&gt; returns, and throw an assertion error if not. This could help catch bugs earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Easier-to-read code
&lt;/h2&gt;

&lt;p&gt;Each cause can act as documentation, showing a programmer reading the code what implications a method will have. In addition, because causes can act as assertions, it is guaranteed that these implications are true.&lt;/p&gt;

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

&lt;p&gt;I think that implementing causes in a language could be a clean, unintrusive way to make code more expressive and easier to read. What do you think?&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>First impressions of Sorbet, a Ruby type checker</title>
      <dc:creator>Aaron Christiansen</dc:creator>
      <pubDate>Wed, 03 Jul 2019 18:11:42 +0000</pubDate>
      <link>https://dev.to/aaronc81/first-impressions-of-sorbet-a-ruby-type-checker-3ef7</link>
      <guid>https://dev.to/aaronc81/first-impressions-of-sorbet-a-ruby-type-checker-3ef7</guid>
      <description>&lt;p&gt;&lt;a href="https://sorbet.org" rel="noopener noreferrer"&gt;Sorbet&lt;/a&gt; is a type checker for Ruby, built by Stripe. Its release has been long-anticipated, having been discussed at a handful of Ruby conferences, and being available to test out in an &lt;a href="https://sorbet.run" rel="noopener noreferrer"&gt;online playground called sorbet.run&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now it's been released as an open-source project, and I've been eagerly playing around with it. I'll start off by saying that, overall, my experience with Sorbet has been quite positive.&lt;/p&gt;

&lt;p&gt;I've always been a fan of static typing, and the lack of it in Ruby has sometimes put me off writing large projects with it. Sorbet could be enough to tempt me back - but only after it's been given a bit of time to mature. In this post I'll be discussing my thoughts on Sorbet in-depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I like
&lt;/h2&gt;

&lt;h3&gt;
  
  
  It's still Ruby!
&lt;/h3&gt;

&lt;p&gt;This is one of the nicest things about Sorbet, made possible by Ruby's flexible and versatile syntax. Ruby code which uses Sorbet is still just Ruby. Type signatures are added through method calls above each definition:&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="n"&gt;sig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;a: &lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;b: &lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_ints&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;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All you need to run this is the &lt;code&gt;sorbet-runtime&lt;/code&gt; gem, which defines &lt;code&gt;sig&lt;/code&gt; and any other calls which are sometimes used to declare types. &lt;/p&gt;

&lt;p&gt;This is in stark contrast to TypeScript's approach, which is an entirely new language compiling down to JavaScript. Creating a new language adds an entirely new build step and complicates things somewhat. (In many ways, what TypeScript is to JavaScript is very similar to what Sorbet is to Ruby, so I'll be drawing quite a few comparisons between them here.)&lt;/p&gt;

&lt;h3&gt;
  
  
  It's gradual
&lt;/h3&gt;

&lt;p&gt;Once you add Sorbet to your project, you don't need to go through and add type signatures to every single method immediately. (However, shameless plug, &lt;a href="https://github.com/AaronC81/sord" rel="noopener noreferrer"&gt;my project will do that&lt;/a&gt; if you have YARD docs!)&lt;/p&gt;

&lt;p&gt;Instead, you can gradually add types to your existing codebase, and Sorbet will only check methods with type signatures.&lt;/p&gt;

&lt;h3&gt;
  
  
  It brings an awesome language server with it
&lt;/h3&gt;

&lt;p&gt;Sorbet needs to have a deep understanding of the structure of your codebase to do its job, and as a great bonus feature it is exposes this information over the &lt;a href="https://microsoft.github.io/language-server-protocol/specification" rel="noopener noreferrer"&gt;Language Server Protocol&lt;/a&gt;. This means that your editor can see this information and offer rich autocomplete, jump-to-definition, and more.&lt;/p&gt;

&lt;p&gt;With the Sorbet extension for Visual Studio Code, I got some of the best autocompletion I've ever seen in an editor for Ruby. Other solutions I've tried for Ruby in VS Code didn't even come close; I'd say Sorbet is about on par, if not better, than RubyMine's completion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk7mntuipq9s7jznryfl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk7mntuipq9s7jznryfl.png" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  It makes code safer
&lt;/h3&gt;

&lt;p&gt;Obviously, being a static type system, Sorbet brings all the advantages of static typing to your Ruby code. Accurate type signatures with the aid of a type checker can spot many common errors within the code you're writing. &lt;/p&gt;

&lt;h2&gt;
  
  
  What I don't like as much
&lt;/h2&gt;

&lt;h3&gt;
  
  
  It doesn't support structural interfaces
&lt;/h3&gt;

&lt;p&gt;I feel like this is currently one of Sorbet's largest weak points. One of the aspects where TypeScript really knocked it out of the park is in supporting all of the stuff that people frequently do in JavaScript.&lt;/p&gt;

&lt;p&gt;Like Ruby, JavaScript is quite a malleable language, but TypeScript is able to encompass virtually all of JavaScript's behaviours. It does this by using &lt;a href="http://wiki.c2.com/?NominativeAndStructuralTyping" rel="noopener noreferrer"&gt;structural typing&lt;/a&gt; with interfaces. The programmer can create an interface type defining properties and methods, and then all objects which contain these properties and methods match the interface type automatically.&lt;/p&gt;

&lt;p&gt;For example, take this TypeScript code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanSpeak&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&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="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;speakable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CanSpeak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Aaron&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;speakable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello!&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;p&gt;Although we have not explicitly said that &lt;code&gt;Person&lt;/code&gt; implements the method required for the &lt;code&gt;CanSpeak&lt;/code&gt; interface, the TypeScript compiler can determine this for itself, and the type check succeeds.&lt;/p&gt;

&lt;p&gt;On the other hand, Sorbet uses a nominative type system, more similar to what you may find in C# or Java. Interface implementation must be explicit, as you can see in this snippet of Ruby with Sorbet:&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="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;CanSpeak&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Helpers&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Sig&lt;/span&gt;

  &lt;span class="n"&gt;interface!&lt;/span&gt;

  &lt;span class="n"&gt;sig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;abstract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;msg: &lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;untyped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&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;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Sig&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;CanSpeak&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;-- explicit interface inclusion&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&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="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;sig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;msg: &lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;void&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;msg&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;speakable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Person&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="s2"&gt;"Aaron"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;CanSpeak&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the &lt;code&gt;include CanSpeak&lt;/code&gt; line, this snippet does not pass type checking.&lt;/p&gt;

&lt;p&gt;The issue with this system is that it means portions of code may have to be refactored entirely to include a particular interface. The even larger problem is that, if the code isn't your own, you can't edit that to include the interface! This could lead to tricky scenarios when adopting Sorbet in a larger codebase which depends on gems.&lt;/p&gt;

&lt;h3&gt;
  
  
  It doesn't support options hashes very well
&lt;/h3&gt;

&lt;p&gt;As you may well know, it's extremely common practice for a method to accept an options hash: a hash parameter containing any extraneous options for that method. For instance, in an API library, you might see a method definition like:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
  &lt;span class="c1"&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;You could specify values like your API key in the &lt;code&gt;opts&lt;/code&gt; hash. This helps to keep method signatures concise for methods with huge numbers of optional arguments.&lt;/p&gt;

&lt;p&gt;Disappointingly, Sorbet doesn't support hashes like this very well. You have a few options of what to use in your type signature, none of which are perfect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Hash&lt;/code&gt;, which just accepts any keys or values. This is almost like having no type checking at all.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;T::Hash[Symbol, T.untyped]&lt;/code&gt;, which restricts keys to symbols but still allows any value and doesn't enforce that certain keys are specified.&lt;/li&gt;
&lt;li&gt;Use a &lt;a href="https://sorbet.org/docs/shapes" rel="noopener noreferrer"&gt;shape&lt;/a&gt;, which allows both key and value types to be specified. However, you can't have optional keys, which is one of the most common use cases of these options hashes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's not ready yet, which is holding me back from using Sorbet everywhere
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Most gems don't have types yet
&lt;/h3&gt;

&lt;p&gt;Sorbet has only just been released, and as such it hasn't been adopted in most projects yet. This kind of adoption takes time, and I have no doubt that the Ruby community will come together to add type signatures to most popular gems in no time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plugins aren't ready
&lt;/h3&gt;

&lt;p&gt;Ruby's wealth of metaprogramming-powered domain specific languages are one of the things that makes Ruby so special. Naturally, it's not really possible to add type safety to these using a traditional type system, so Sorbet will have a plugin system to allow types to be generated on-the-fly.&lt;/p&gt;

&lt;p&gt;This plugin system is currently not finalised and has some serious drawbacks. With that said, once the plugin system is fully implemented and matured, it will be really interesting to see how extensively static typing can be employed across existing Ruby tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;Sorbet is a fantastic start in adding static typing to Ruby; the team at Stripe have done a brilliant job! It's currently great for many small projects, but for larger ones I believe it needs time to fully mature and build up a community following. I'm looking forward to seeing how Sorbet develops in the near future.&lt;/p&gt;

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