<?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: Benjamin Congdon</title>
    <description>The latest articles on DEV Community by Benjamin Congdon (@benrcongdon).</description>
    <link>https://dev.to/benrcongdon</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%2F48948%2F29b8ee6b-4daf-4468-9f6e-d4c63f46ac3c.jpg</url>
      <title>DEV Community: Benjamin Congdon</title>
      <link>https://dev.to/benrcongdon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/benrcongdon"/>
    <language>en</language>
    <item>
      <title>A Gentle Nudge</title>
      <dc:creator>Benjamin Congdon</dc:creator>
      <pubDate>Sun, 03 Nov 2019 07:12:00 +0000</pubDate>
      <link>https://dev.to/benrcongdon/a-gentle-nudge-g65</link>
      <guid>https://dev.to/benrcongdon/a-gentle-nudge-g65</guid>
      <description>&lt;p&gt;Earlier this year, I was persuaded to start paper journaling. Paper journaling is unlikely to replace digital task management for me, but there definitely are some benefits to an analog, offline journal.&lt;/p&gt;

&lt;p&gt;The paper journal that I keep nominally follows the &lt;a href="https://bulletjournal.com/"&gt;Bullet Journal&lt;/a&gt; method, but only loosely. I’ve tried a couple different techniques over the year. Some, like retrospectively writing down what I did in a given day, felt tedious and redundant given that I already capture that type of information in other ways.&lt;/p&gt;

&lt;p&gt;One technique that I’ve found to be useful is “habit trackers”. The idea is simple: each month, make a list of 4-5 things that you either want to do or abstain from doing each day. Then, take a page in your notebook and made headers for each of these activities, and a row for each day. At the end of each day, mark which activities you completed. For me, I used this to track habits that didn’t &lt;em&gt;need&lt;/em&gt; to get done everyday, but would improve my sense of productivity and personal satisfaction if I &lt;em&gt;did&lt;/em&gt; do them.&lt;/p&gt;

&lt;p&gt;I’ve written before that some tasks really don’t belong in a task tracker like Todoist. For habits that are already on “autopilot” (for me, running daily), having a daily repeating task just clutters my dashboard. For habits that are less of a slam dunk (for me, meditating daily), I find that I’m actually &lt;em&gt;less&lt;/em&gt; likely to do them if they appear as anitem on my todo list. (“Procrastiworking,” anyone?)&lt;/p&gt;

&lt;p&gt;Since habits are tracked as completed or uncompleted at the end of the day, there’s less of a sense of guilt for not doing something, but you still get a little dopamine hit for crossing off an accomplished habit. You aren’t shamed into deferring a todo item to tomorrow; you simply didn’t do that habit today. This practice also bakes in a bit of end-of-day reflection, which can be helpful for other reasons.&lt;/p&gt;

&lt;p&gt;This was on my mind as I was reading Michael Lopp’s &lt;a href="https://www.goodreads.com/book/show/8473471-being-geek"&gt;&lt;em&gt;Being Geek&lt;/em&gt;&lt;/a&gt;. When I read his essay on what he calls &lt;a href="https://randsinrepose.com/archives/the-trickle-list/"&gt;“The Trickle List”&lt;/a&gt;, I noticed it closely resembled my discovered system of habit tracking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My first excursion into the word trickle was a productivity article called Trickle Theory. The argument was simple. You can do more than you think with small, consistent investments of your time.&lt;/p&gt;

&lt;p&gt;To understand the Trickle List, you need to first look at the headers at the top of the list. These are the heart of the list and how you define them is how you define what you want to do.&lt;/p&gt;

&lt;p&gt;The items on your Trickle List don’t need to be huge, in fact, as we’ll learn in a moment, the bigger they are, the less likely you’ll do them. What they need to be is aligned with where you’re headed. However small, they need to be a daily reminder that you’re headed somewhere.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lopp’s “trickle list” emphasizes a couple points which makes this type of habit tracking successful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The habit should be useful to you personally, not a vague aspiration.&lt;/li&gt;
&lt;li&gt;The habit should be small.&lt;/li&gt;
&lt;li&gt;The habit should be measurable as a “yes”/“no”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At its best, the “trickle list” gives your frantic “daily self” a gentle nudge from your more rational “long-term thinking” self.&lt;/p&gt;

&lt;p&gt;Personally, I find reevaluating my habits monthly to be a good cadence. If I’ve accomplished something everyday for the entire month, I probably don’t need to include that on next month’s list. Similarly, if I have a habit that I only managed to do a handful of times during the month, I probably need to evaluate why I wasn’t successful. Is the habit too big? Am I just not motivated enough? What environmental factors prevented me from doing what I’d planned?&lt;/p&gt;

&lt;p&gt;The result is two levels of reflection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;daily&lt;/strong&gt; reflection of “what could I, given the limits of my schedule, done better today” and…&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;monthly&lt;/strong&gt; reflection of “at a meta level, what types of activities do I want to encourage myself to do”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve started to think more about this notion of “gentle nudging.” Where else in our environment does it make sense to add moments of pause or slightly change our environment to slowly bend ourselves towards self-improvement?&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title>Finding Flow in Haskell</title>
      <dc:creator>Benjamin Congdon</dc:creator>
      <pubDate>Thu, 25 Apr 2019 14:30:10 +0000</pubDate>
      <link>https://dev.to/benrcongdon/finding-flow-in-haskell-j41</link>
      <guid>https://dev.to/benrcongdon/finding-flow-in-haskell-j41</guid>
      <description>&lt;p&gt;For the last couple of months, I’ve been working on-and-off in Haskell for my programming languages class. I’ve written previously about my preference for declarative functional syntax, but I’d never really spent the time to learn a pure Functional Programming™️ language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tl;dr:&lt;/strong&gt; I’m glad I learned Haskell. It’s great at expressing some programs that are difficult (or practically impossible) to express in other languages. However, this necessarily makes other types of programs difficult to write in Haskell.&lt;/p&gt;

&lt;p&gt;Keep in mind that I’ve learned just enough Haskell to “be dangerous” (both in the sense of being comfortable enough to write moderately complex programs and in the sense that I’m naive enough to be potentially misguided à la Dunning-Kruger). Take this with a grain of salt.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Entry Point: Higher-Order Functions
&lt;/h3&gt;

&lt;p&gt;I was thinking about the first time I encountered anything that looked remotely like Functional Programming. I think that first interaction was probably when I learned Javascript’s &lt;code&gt;Array.{map, reduce, filter}&lt;/code&gt;. These higher-order functions, so-called because they take a function as an argument, make you think about the execution of a program in a radically different way.&lt;/p&gt;

&lt;p&gt;Internalizing the concept of a higher-order function requires a similar type of mental leap as that of learning recursion. If you follow the “traditional” imperative path of learning to program, recursion is a common stumbling block because it forces you to think about functions not merely as procedures, but as abstracted procedures that can be called within themselves. Higher-order functions impose a similar stumbling block: you have to think of functions as data. Just as you manipulate and pass variables, you can combine and pass functions.&lt;/p&gt;

&lt;p&gt;Once comfortable with &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, and the like, you can express a crazy amount of functionality using HOFs. Some of my favorite parts of Ruby and Rust are in its support for just this small set of HOFs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Haskell is not &lt;code&gt;Array.map&lt;/code&gt;, but “more”
&lt;/h3&gt;

&lt;p&gt;From the above section, you can see that my initial mental model of functional programming was fairly narrow. &lt;em&gt;It’s that thing that allows you to move around functions like you would variables…&lt;/em&gt; Well, kinda. Of course, thoughts about functional programming also elicited the obligatory thoughts of “there are no side effects” and “everything is a function”&lt;/p&gt;

&lt;p&gt;Haskell does make generous use of HOFs. It uses a lot of functions (though &lt;a href="http://conal.net/blog/posts/everything-is-a-function-in-haskell"&gt;not everything is a function&lt;/a&gt;) and, indeed, it’s pretty difficult to have unintentional side-effects in Haskell programs. But, to sell Haskell as “what if we took &lt;code&gt;Array.map&lt;/code&gt; and made a language around that” would be missing the point.&lt;/p&gt;

&lt;p&gt;I’d argue that what makes Haskell unique and useful is an altogether different set of features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pattern Matching&lt;/li&gt;
&lt;li&gt;Immutability&lt;/li&gt;
&lt;li&gt;Algebraic Data Types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These three features alone (as well as some necessaries like functional composition) already make a compelling case for giving Haskell a try.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pattern Matching
&lt;/h4&gt;

&lt;p&gt;First-class &lt;a href="http://learnyouahaskell.com/syntax-in-functions"&gt;pattern matching&lt;/a&gt; might be my favorite thing in Haskell. Take the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;mySearch&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Eq&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;
&lt;span class="n"&gt;mySearch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;mySearch&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;
&lt;span class="n"&gt;mySearch&lt;/span&gt; &lt;span class="kt"&gt;[]&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;False&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mySearch&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="kt"&gt;True&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mySearch&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="kt"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mySearch&lt;/span&gt; &lt;span class="kt"&gt;[]&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="kt"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;mySearch&lt;/code&gt; checks if an element (&lt;code&gt;target&lt;/code&gt;) is present in the list (which is the first argument). The first line pattern matches on a non-empty list. If the list is non-empty, &lt;code&gt;x&lt;/code&gt; is the first element in the list, and &lt;code&gt;xs&lt;/code&gt; is the rest of the list. If the list is empty, the second case will be used (&lt;code&gt;[]&lt;/code&gt; pattern matches on the empty list), and we return &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pattern matching on lists is awesome in itself. You can also pattern match on specific values and on algebraic data types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;isMeaningOfLife&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;
&lt;span class="n"&gt;isMeaningOfLife&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;True&lt;/span&gt;
&lt;span class="n"&gt;isMeaningOfLife&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;False&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isMeaningOfLife&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
&lt;span class="kt"&gt;False&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isMeaningOfLife&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This, of course, just scratches the surface of what’s possible. You can pattern match each variable independently and have tons of different cases for a given function. This becomes super powerful in more complicated programs and is a good shorthand for decomposing complicated functions into their simpler cases. (Many recursive functions written in Haskell feel like writing mathematical proofs; “there are 3 cases to consider…”)&lt;/p&gt;

&lt;p&gt;My pet theory on why pattern matching is so great in Haskell is that for purely functional programs, a function’s output is much more tightly bound to its input. As side-effects are prohibited, the only way a function can actually &lt;em&gt;do&lt;/em&gt; anything is by returning something. Similarly, functional programming is syntactically more declarative. Pattern matching simply makes it &lt;em&gt;a lot easier&lt;/em&gt; to write declarative pure functions. Patterns allow you to describe behaviors of a function under different forms of input without much syntactic boilerplate.&lt;/p&gt;

&lt;h4&gt;
  
  
  Immutability
&lt;/h4&gt;

&lt;p&gt;Haskell expressions are immutable. Once you construct a piece of data, it cannot be changed. To change data (i.e. appending to a list, adding a key to a dictionary, etc.) a new data structure is created. This prevents large classes of bugs. You never have to care about some other thread or function changing the internal state of some data structure because, well, &lt;em&gt;they can’t&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Other language communities have picked up on immutability too, either as libraries (notably Google’s &lt;a href="https://github.com/google/guava"&gt;Guava&lt;/a&gt; for Java and &lt;a href="https://github.com/immutable-js/immutable-js"&gt;immutable-js&lt;/a&gt; for Javascript) or as language defaults (like in Rust).&lt;/p&gt;

&lt;p&gt;Immutability can be a real pain to deal with. (i.e. “I just want to do in-place array operations!”) However, I think Haskell mostly gets away with it because it uses immutability &lt;em&gt;everywhere&lt;/em&gt;. When mutating internal state isn’t an option, it becomes less of a temptation — you start to think in ways that don’t necessitate mutability.&lt;/p&gt;

&lt;h4&gt;
  
  
  Algebraic Data Types
&lt;/h4&gt;

&lt;p&gt;“Algebraic Data Type” is one of those scary-sounding phrases that end up being pretty harmless when explained.&lt;/p&gt;

&lt;p&gt;Put simply, there are &lt;em&gt;product types&lt;/em&gt; (which are analogous to tuples or structs) and &lt;em&gt;sum types&lt;/em&gt; (which are kinda like &lt;code&gt;enum&lt;/code&gt;s with an associated value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Example Product Type&lt;/span&gt;
&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Point&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;

&lt;span class="c1"&gt;-- Example Sum Type&lt;/span&gt;
&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;MyMaybe&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
               &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The product type &lt;code&gt;Point&lt;/code&gt; is a type that contains 2 integers. For example, we could represent the origin as &lt;code&gt;(Point 0 0)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Sum types are like enums, in that there is a set of valid symbolic forms for the given type. &lt;code&gt;MyMaybe&lt;/code&gt; is parametrized over type &lt;code&gt;a&lt;/code&gt; (like &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; in an OOP language). It can have the form &lt;code&gt;Nothing&lt;/code&gt; or &lt;code&gt;Just a&lt;/code&gt;. This is a useful way to describe optional values. For example, if we wanted to describe an optional integer, we could have a function that returns &lt;code&gt;Just 42&lt;/code&gt; if the operation is successful and &lt;code&gt;Nothing&lt;/code&gt; otherwise.&lt;/p&gt;

&lt;p&gt;Sum types are especially powerful, as they can easily be used to represent syntax trees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Exp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;IntExp&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;PlusExp&lt;/span&gt; &lt;span class="kt"&gt;Expression&lt;/span&gt; &lt;span class="kt"&gt;Expression&lt;/span&gt;
         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;IfExp&lt;/span&gt; &lt;span class="kt"&gt;Exp&lt;/span&gt; &lt;span class="kt"&gt;Exp&lt;/span&gt; &lt;span class="kt"&gt;Exp&lt;/span&gt;
         &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;GreaterThanExp&lt;/span&gt; &lt;span class="kt"&gt;Exp&lt;/span&gt; &lt;span class="kt"&gt;Exp&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="s"&gt;"if 1 &amp;gt; 0 then 2 else 3"&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;IfExp&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;GreaterThanExp&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;IntExp&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;IntExp&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;IntExp&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;IntExp&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that sum types can be recursive. In &lt;code&gt;PlusExp&lt;/code&gt; there are 2 subexpressions, each of which have their own internal syntax tree.&lt;/p&gt;

&lt;p&gt;Recall that we can pattern match on algebraic data types, which means that if we wanted to write an evaluator for a syntax tree like the one presented above, we could do so pretty easily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;eval&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Expression&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="n"&gt;eval&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;IntExp&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;span class="n"&gt;eval&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PlusExp&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt; &lt;span class="n"&gt;e2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eval&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt;
    &lt;span class="n"&gt;e2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eval&lt;/span&gt; &lt;span class="n"&gt;e2&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I really enjoy using ADTs (especially in combination with pattern matching) in Haskell. They’re a surprisingly good way of representing certain types of data, and it allows the type-checker to do a lot of reasoning on your behalf about the correctness of programs.&lt;/p&gt;

&lt;p&gt;I’m encouraged by Rust’s &lt;a href="https://doc.rust-lang.org/rust-by-example/custom_types/enum.html"&gt;typed enums&lt;/a&gt; and Swift’s &lt;a href="https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html"&gt;associated value enums&lt;/a&gt;, both of which give similar functionality in a non-functional setting.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;$&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;, Oh My!
&lt;/h3&gt;

&lt;p&gt;So with all that gushing about Haskell out of the way, I should mention some areas that frustrated me.&lt;/p&gt;

&lt;p&gt;Haskell syntax is definitively &lt;em&gt;not&lt;/em&gt; C-derived, so there’s a bit of a burden to relearn basic syntax. However, the real weirdness comes in when you start going a bit deeper into Haskell’s language features.&lt;/p&gt;

&lt;p&gt;The basics of Haskell’s type system will be familiar for programmers of other languages. Functions take typed inputs and produce typed outputs. However, there are also &lt;a href="http://learnyouahaskell.com/types-and-typeclasses"&gt;type classes&lt;/a&gt;, which are kinda like protocols or traits for types.&lt;/p&gt;

&lt;p&gt;Common type classes include &lt;a href="https://wiki.haskell.org/Functor"&gt;Functor&lt;/a&gt;/&lt;a href="https://wiki.haskell.org/Applicative_functor"&gt;Applicative&lt;/a&gt;, &lt;a href="https://wiki.haskell.org/Foldable_and_Traversable"&gt;Foldable&lt;/a&gt;, and &lt;a href="https://wiki.haskell.org/Monad"&gt;Monad&lt;/a&gt;. As these type classes are used so often (and have associated operations that are used frequently), Haskell has a number of syntactic operators that allow you to invoke type class functions easily. &lt;code&gt;&amp;lt;$&amp;gt;&lt;/code&gt; is identical to Functor’s &lt;code&gt;fmap&lt;/code&gt;, &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt; is Monad’s &lt;code&gt;bind&lt;/code&gt;. There are a &lt;a href="https://haskell.fpcomplete.com/tutorial/operators"&gt;bunch more operators&lt;/a&gt;, including a few variations of each of the ones I’ve mentioned so far. The result can be a bit of symbol soup, which is difficult to read at a glance.&lt;/p&gt;

&lt;p&gt;I mean, there’s the very real question (if posed somewhat in jest) of &lt;a href="https://stackoverflow.com/questions/3242361/haskell-how-is-pronounced"&gt;“how do you pronounce &lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt;?”&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To its credit, Haskell has a really excellent REPL, and you can ask it the type signature of an operator when you get confused.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Monad&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There’s also the concern that some types of programs just don’t lend themselves to being written in a functional way. For anything involving super heavy system programming, file IO, or GUI interactions, I don’t think I’d want to use Haskell.&lt;/p&gt;

&lt;p&gt;I was also a bit surprised about the story for &lt;a href="https://wiki.haskell.org/Debugging"&gt;debugging in Haskell&lt;/a&gt;. It’s… not amazing (in my opinion). You can still do &lt;code&gt;printf&lt;/code&gt; debugging with &lt;a href="http://hackage.haskell.org/package/base/docs/Debug-Trace.html"&gt;&lt;code&gt;Debug.Trace&lt;/code&gt;&lt;/a&gt;, but putting &lt;code&gt;trace&lt;/code&gt; as a shim in between function calls feels more obtrusive than a &lt;code&gt;printf&lt;/code&gt; statement. To its credit, Haskell’s REPL is great, so you can debug smaller components there easily. GHCI (Haskell’s REPL) also has breakpoint support. Safe to say though, just as you’ll need to relearn parts of programming when picking up FP, you also need to relearn parts of debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aside: Category/Type Theory
&lt;/h3&gt;

&lt;p&gt;As an aside, one can’t help but notice that the average Haskell programmer seems to be more interested in Category and/or Type theory (also formal methods) than, say, the average Python developer.&lt;/p&gt;

&lt;p&gt;Type theory has always been something that I “feel” like I should be interested in, but more from an intellectual perspective than for any practical reason.&lt;/p&gt;

&lt;p&gt;At the risk of sounding dismissive, I think you can probably ignore most of the discussions about “&lt;a href="https://stackoverflow.com/questions/3870088/a-monad-is-just-a-monoid-in-the-category-of-endofunctors-whats-the-problem"&gt;a monad being just a monoid in the category of endofunctors&lt;/a&gt;” and still get along just fine in Haskell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;logether, I find the programming experience in Haskell to be really enjoyable. When working in a domain well-suited to Haskell’s strengths, I find it pretty easy to get into a flow state. I don’t feel like I’m fighting thetype-checker; rather, it feels like it’s keeping me honest.&lt;/p&gt;

&lt;p&gt;I’m sure this doesn’t generalize, but when working in Haskell I get the feeling that if my code passes the type-checker, I’m reasonably confident that I’ve written a “correct” program. Many people also feel this about Rust’s type-checker. It’s a refreshing feeling. When working in Go or Python (or Javascript, for that matter), writing code feels like just the first half of the battle — you need to exercise it at runtime to build confidence in its correctness. Of course, semantic bugs are easy to commit in Haskell. But, just as a baseline, I feel more confident in “onced-over” Haskell code than I would code written in other languages.&lt;/p&gt;

&lt;p&gt;I’m glad I took the time to learn Haskell. It comes at writing programs from a very different perspective than languages I’ve used before, and it’s made me more attuned to aspects of type systems that aren’t as easily explored in non-functional languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further Reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.haskell.org/Functional_programming#Immutable_data"&gt;Functional Programming Intro (Haskell Wiki)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mmhaskell.com/blog/2017/1/9/immutability-is-awesome"&gt;Immutability is Awesome (Monday Morning Haskell)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>haskell</category>
      <category>functional</category>
      <category>learning</category>
    </item>
    <item>
      <title>Live Refreshing Cargo Docs</title>
      <dc:creator>Benjamin Congdon</dc:creator>
      <pubDate>Wed, 22 Aug 2018 21:03:28 +0000</pubDate>
      <link>https://dev.to/benrcongdon/live-refreshing-cargo-docs-5bke</link>
      <guid>https://dev.to/benrcongdon/live-refreshing-cargo-docs-5bke</guid>
      <description>&lt;p&gt;&lt;code&gt;rustdoc&lt;/code&gt; is a great tool, but as of now there isn’t an official way to have its generated docs refresh as you make edits. Running &lt;code&gt;cargo doc&lt;/code&gt; with the &lt;code&gt;--open&lt;/code&gt; argument will open the generated docs in browser window. If you make changes to your source code, you’ll need to re-run &lt;code&gt;cargo doc&lt;/code&gt; to have the changes reflected in your browser. By chaining together a few other Rust tools, we can pretty easily get the functionality of live-reloading docs.&lt;/p&gt;

&lt;p&gt;We’ll be 2 tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/passcod/cargo-watch"&gt;cargo-watch&lt;/a&gt; to watch when our project’s source has changed and trigger the docs rebuild.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/thecoshman/http"&gt;http&lt;/a&gt; as a static server for the generated docs.

&lt;ul&gt;
&lt;li&gt;This isn’t &lt;em&gt;strictly&lt;/em&gt; necessary: As mentioned earlier, you can use the &lt;code&gt;--open&lt;/code&gt; argument with &lt;code&gt;cargo doc&lt;/code&gt; to view docs using the &lt;code&gt;file://&lt;/code&gt; protocol, but I like having a &lt;code&gt;localhost&lt;/code&gt; address to visit.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll assume that you already have &lt;code&gt;cargo&lt;/code&gt; installed. If you don’t, then you can use &lt;a href="https://rustup.rs/"&gt;rustup&lt;/a&gt; to install it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install &lt;code&gt;cargo-watch&lt;/code&gt; and &lt;code&gt;https&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;First, install both commands we’ll need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;cargo-watch https
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Run Watch Command
&lt;/h3&gt;

&lt;p&gt;Now, navigate to the project directory that contains your &lt;code&gt;Cargo.toml&lt;/code&gt; file. Then, run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo watch &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;'cargo doc &amp;amp;&amp;amp; http target/doc'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should now see something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Running cargo doc &amp;amp;&amp;amp; http target/doc]
 Documenting docs-example v0.1.0 (file:///path/to/project/docs-example)
    Finished dev [unoptimized + debuginfo] target(s) in 0.43s
Hosting "target/doc" on port 8000 without TLS...
Ctrl-C to stop.

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

&lt;/div&gt;



&lt;p&gt;You can visit &lt;code&gt;localhost:8000&lt;/code&gt; in your browser to view the generated docs. (Note: you’ll initially see a directory page, so you’ll have to navigate to one of the package listings to see actual docs)&lt;/p&gt;

&lt;p&gt;If you make any changes to any source file in your project, you’ll see that &lt;code&gt;cargo-watch&lt;/code&gt; will automatically re-run &lt;code&gt;cargo doc&lt;/code&gt; and restart the file server. You should be able to refresh your browser and see the documentation changes live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Auto-refresh
&lt;/h2&gt;

&lt;p&gt;One annoyance with this approach is that editing a source file does not trigger a refresh in the browser (i.e. &lt;em&gt;you&lt;/em&gt; still have to refresh the page manually).&lt;/p&gt;

&lt;p&gt;If you’re fine with using a node-based tool, &lt;a href="https://browsersync.io/"&gt;browser-sync&lt;/a&gt; fixes this problem.&lt;/p&gt;

&lt;p&gt;Install with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; browser-sync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;… then edit your &lt;code&gt;cargo-watch&lt;/code&gt; command to use &lt;code&gt;browser-sync&lt;/code&gt; instead of &lt;code&gt;http&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo watch &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;'cargo doc &amp;amp;&amp;amp; browser-sync start --ss target/doc -s target/doc --directory --no-open'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, visit &lt;code&gt;localhost:3000&lt;/code&gt; (or whichever port is listed on startup). Any subsequent changes to your Rust source code will now trigger any open browsers to refresh automatically with the updated documentation.&lt;/p&gt;




&lt;p&gt;I’ve found that using this tweak to have auto-refreshing docs makes it much more pleasant to document my Rust crates. I’d love to see if there’s a more streamlined way to have auto-refreshing docs – be sure to let me know! 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To learn the basics of &lt;code&gt;rustdoc&lt;/code&gt; (which powers &lt;code&gt;cargo doc&lt;/code&gt;), check &lt;a href="https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html"&gt;this chapter&lt;/a&gt; in the rust book.&lt;/li&gt;
&lt;li&gt;These issues give context as to why this functionality isn’t officially supported (as of now): &lt;a href="https://github.com/rust-lang/cargo/issues/1472"&gt;cargo#1472&lt;/a&gt;, &lt;a href="https://github.com/rust-lang/cargo/issues/4966"&gt;cargo#4966&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
      <category>documentation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Lossy Numeric Casting in Rust</title>
      <dc:creator>Benjamin Congdon</dc:creator>
      <pubDate>Mon, 06 Aug 2018 20:28:01 +0000</pubDate>
      <link>https://dev.to/benrcongdon/lossy-numeric-casting-in-rust-1c6a</link>
      <guid>https://dev.to/benrcongdon/lossy-numeric-casting-in-rust-1c6a</guid>
      <description>&lt;p&gt;Recently, I was trying out &lt;a href="https://github.com/rust-lang-nursery/rust-clippy"&gt;clippy&lt;/a&gt; — a new linting and static analysis tool for Rust, when I ran into a lint warning that wasn’t immediately clear to me: &lt;code&gt;warning: casting u8 to u16 may become silently lossy if types change&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For context, this is the snippet of code I ran through &lt;code&gt;clippy&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0x12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0x34&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;silly_max&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;b&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;silly_max&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="nb"&gt;u8&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="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&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;as&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essentially, we take two 8-bit unsigned integers, cast them to 16-bit unsigned integers, and compare the casted results, returning the greater of the two.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;clippy&lt;/code&gt; on this code, this is the lint error I received:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warning: casting u8 to u16 may become silently lossy if types change
 --&amp;gt; src/main.rs:8:13
  |
8 | let x = a as u16;
  | ^^^^^^^^ help: try: `u16::from(a)`
  |
  = note: #[warn(cast_lossless)] on by default
  = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.212/index.html#cast_lossless

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

&lt;/div&gt;



&lt;p&gt;Now, the issue with this code isn’t immediately obvious. And that’s because this code is &lt;em&gt;”correct”&lt;/em&gt; in that, at present, it does what it should do.&lt;/p&gt;

&lt;p&gt;The potential error, as &lt;code&gt;clippy&lt;/code&gt; suggests, is what &lt;em&gt;could&lt;/em&gt; happen if I later change this code. Suppose in the future, the design of the program changes and I actually want to find the max of two &lt;code&gt;u32&lt;/code&gt;s. Look what would happen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0x00000002&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0x10000001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;silly_max&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;b&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;silly_max&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="nb"&gt;u32&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="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&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;as&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we try to run this code, we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Running `target/debug/silly_max`
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `2`,
 right: `1`', src/main.rs:4:5

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

&lt;/div&gt;



&lt;p&gt;Clearly something went wrong. This is a classic truncation issue. When we cast &lt;code&gt;u32-&amp;gt;u16&lt;/code&gt;, we lose the top 16 most significant bits of our integers. &lt;code&gt;0x10000001&lt;/code&gt; gets truncated to &lt;code&gt;0x0001&lt;/code&gt; and &lt;code&gt;0x00000002&lt;/code&gt; becomes &lt;code&gt;0x0002&lt;/code&gt;. Under truncation, our comparison operation doesn’t always work how we’d expect.&lt;/p&gt;

&lt;p&gt;Luckily in this case, the truncation was rather clear. However, our code still compiled. We only noticed &lt;em&gt;at runtime&lt;/em&gt; that we’d silently introduced a bug. (Just as &lt;code&gt;clippy&lt;/code&gt; warned)&lt;/p&gt;

&lt;p&gt;Let’s go back to the first version and implement the fix &lt;code&gt;clippy&lt;/code&gt; suggested, using &lt;code&gt;u16::from&lt;/code&gt; instead of casting via &lt;code&gt;as&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;silly_max&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="nb"&gt;u8&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="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code compiles and works as expected. Now, lets make the same code change (switching the types of &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; to &lt;code&gt;u32&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;silly_max&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="nb"&gt;u32&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="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;y&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we get a friendly compiler error:&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; src/main.rs:8:13
  |
8 | let x = u16::from(a);
  | ^^^^^^^^^ the trait `std::convert::From&amp;lt;u32&amp;gt;` is not implemented for `u16`
  |
  = help: the following implementations were found:
            &amp;lt;u16 as std::convert::From&amp;lt;bool&amp;gt;&amp;gt;
            &amp;lt;u16 as std::convert::From&amp;lt;u8&amp;gt;&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;This is what we want! Instead of silently introducing the possibility of truncation into our program, the compiler lets us know that we’re trying to do an unsafe translation.&lt;/p&gt;

&lt;p&gt;But what if we &lt;em&gt;want&lt;/em&gt; this possible truncation behavior? Well, you can still use &lt;code&gt;as&lt;/code&gt; and you’ll get truncated casts. Interestingly, &lt;code&gt;clippy&lt;/code&gt; doesn’t complain if you do &lt;code&gt;u32 -&amp;gt; u16&lt;/code&gt; via &lt;code&gt;as&lt;/code&gt; — it assumes you know what you’re doing.&lt;/p&gt;

&lt;p&gt;So, what’s the moral of the story?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prefer using the &lt;code&gt;std::convert::From&lt;/code&gt; trait for doing type conversions. The &lt;code&gt;as&lt;/code&gt; keyword performs “safe” casts (casting won’t cause a panic), but you can still run into classes of errors that can be avoided by using designated converter methods.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are some resources if you’re interested in learning more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics"&gt;Cast Operation Semantics - The Rust Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rust-lang-nursery.github.io/rust-clippy/v0.0.212/index.html#cast_lossless"&gt;cast_lossless Explanation - Clippy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
      <category>clippy</category>
      <category>linter</category>
    </item>
    <item>
      <title>Switching from Jekyll to Hugo</title>
      <dc:creator>Benjamin Congdon</dc:creator>
      <pubDate>Wed, 06 Jun 2018 07:22:07 +0000</pubDate>
      <link>https://dev.to/benrcongdon/switching-from-jekyll-to-hugo-1gj7</link>
      <guid>https://dev.to/benrcongdon/switching-from-jekyll-to-hugo-1gj7</guid>
      <description>&lt;p&gt;I recently went through the process of switching my blog’s static site generator from &lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; to &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt;. Both are great tools, but as I’ve updated my website over time, I began to feel constrained by Jekyll — and wanted to switch to something more stable and robust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;I really like Jekyll. It’s fast to setup, comes with an extremely expressive templating language (sometimes dangerously so), and has the full support of Github — all of which lowers the barrier to deploying and maintaining a personal site.&lt;/p&gt;

&lt;p&gt;That being said, Jekyll’s generation times start to skyrocket when you develop a site with meaningful complexity. I frequently had site generation times of 7+ seconds, which made working on formatting fixes on my website a complete slog.&lt;/p&gt;

&lt;p&gt;Additionally, I’m not the biggest fan of the Ruby ecosystem — mostly due to the trouble I seem to have when installing dependencies. I’ve learned to accept Python’s dependency management warts — they’re generally ameliorated by sticking with a single tool and using it as intended. Ruby… I’ve never gotten to behave well. Without fail, I run into some byzantine installation bug with Nokogiri or Bundler when setting up a completely clean environment. I inevitably fall down some rabbit-hole of desperate StackOverflow questions, costing me an afternoon of annoyance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jekyll’s Moat
&lt;/h2&gt;

&lt;p&gt;Despite this, I stuck with Jekyll for several years — I had a large switching cost in moving away from it: it’s the SSG that I have the most experience with and have used with my site since I started college. However, I reached a tipping point.&lt;/p&gt;

&lt;p&gt;After using Netlify for a bit, the “moat” that Github Pages’ blessed support afforded Jekyll fell away. It’s just as easy to deploy a Hugo-, Gatsby-, or Pelican-generated site on Netlify as it is a Jekyll-generated one (and with HTTPS, no less!).&lt;/p&gt;

&lt;p&gt;In fact, the experience of deploying using Netlify is (in my opinion) superior to Github Pages because &lt;em&gt;you can actually see deploy logs and build failure messages&lt;/em&gt; instead of getting a generic email from Github saying “Something went wrong”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Hugo?
&lt;/h2&gt;

&lt;p&gt;Just as much as I wanted to switch &lt;em&gt;away&lt;/em&gt; from Jekyll, I was intrigued in switching &lt;em&gt;to&lt;/em&gt; Hugo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hugo is Fast&lt;/strong&gt; My biggest complaint with Jekyll was the page generation times. Hugo boasts that it can have sub-millisecond page generation times — I’ve found that to be a slightly over-optimistic. However, my site’s total generation time dropped from 7+ seconds to ~300ms, so I’d score that as a win.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hugo is written in Go&lt;/strong&gt; This is a pretty superficial reason to change SSGs, but… I like Go. It’s a verbose language, but that makes projects written in it easy to read. Its templating system is really good, and Hugo makes smart additions to get similar expressiveness to Liquid (Jekyll’s templating system) with notable performance improvements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hugo is a Single Binary&lt;/strong&gt; The installation and dependency management process for maintaining a Hugo site is trivial compared to Jekyll — you just have to download the single &lt;code&gt;hugo&lt;/code&gt; binary. That’s it. No messing with package installers or system libraries (&lt;em&gt;cough&lt;/em&gt; Nokogiri’s love-hate relationship with lxml &lt;em&gt;cough&lt;/em&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Hiccups During Conversion
&lt;/h2&gt;

&lt;p&gt;To get a grasp on Hugo’s conventions, I followed Sara Soueidan’s excellent “&lt;a href="https://www.sarasoueidan.com/blog/jekyll-ghpages-to-hugo-netlify/"&gt;Migrating from Jekyll+Github Pages to Hugo+Netlify&lt;/a&gt;” guide. There are many Hugo introductions out there, but I found this one to be comprehensive.&lt;/p&gt;

&lt;p&gt;Essentially the process for switching from Hugo to Jekyll was this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rewrite my Jekyll page templates in Go template language.&lt;/li&gt;
&lt;li&gt;Restructure my site’s templates and content to fit Hugo’s directory structure.&lt;/li&gt;
&lt;li&gt;Restructure my &lt;code&gt;config.yaml&lt;/code&gt; file to conform to Hugo’s expectations.&lt;/li&gt;
&lt;li&gt;Add some asset pipeline magic with &lt;code&gt;gulp&lt;/code&gt; to minify assets and compile SASS.&lt;/li&gt;
&lt;li&gt;Fix any miscellaneous errors that I didn’t catch in steps 1-4.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most of this was fairly self-explanatory — once you understand Hugo’s “philosophy.” However, I still encountered a couple hiccups that are worth mentioning:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hugo is much more sensitive to directory structure than Jekyll.&lt;/strong&gt; This was the single most annoying thing about Hugo. Jekyll will render just about anything. Except for a few special directories (i.e. &lt;code&gt;_partials&lt;/code&gt;, &lt;code&gt;_includes&lt;/code&gt;, etc.) Jekyll renders essentially every file in your site source to the build directory.&lt;/p&gt;

&lt;p&gt;Hugo is selective. If a page doesn’t have a valid template or there’s something wrong with a template, the page simply doesn’t get built — often quietly, without error.&lt;/p&gt;

&lt;p&gt;You really do have to follow the template lookup orders that Hugo lists in the documentation, else you risk severe frustration. I suggest making default layouts (i.e. in the &lt;code&gt;_default&lt;/code&gt; folder) for every page type so you don’t run into the issue of “quiet non-rendering”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hugo is much less flexible in templating than Jekyll.&lt;/strong&gt; In Jekyll, anything goes. Want to put some Liquid interpolation in your front-matter? Sure why not. Pull in all your SCSS and run a SCSS compiler in a template? Yes, you can.&lt;/p&gt;

&lt;p&gt;Hugo is much more conservative. It draws a much clearer distinction between what is a template and what is “content”. This was a bit of an annoyance for some custom pages I have (i.e. my &lt;a href="https://benjamincongdon.me/projects"&gt;projects&lt;/a&gt; page) that are highly custom — it doesn’t “feel” right to have these pages be templated, but Hugo requires that they be templates anyway.&lt;/p&gt;

&lt;p&gt;However, I find that in the long run, I spend much less time writing and editing templates than adding Markdown-formatted content. As long as I could get a comfortable set of Hugo templates that span the distinction between content and template, Hugo is really not any more restrictive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hugo is more of a CMS than Jekyll is.&lt;/strong&gt; Many times in the conversion process, I felt like Hugo was over-engineered for my use case. I don’t have a site with multiple authors/feeds or produce enough content that first-class support for categories and tags is crucial.&lt;/p&gt;

&lt;p&gt;Yet Hugo includes all of this and more. It’s a bit overwhelming. Hugo has the marks of a top-down engineered product — “prescriptive to what it thinks users need” — in comparison to Jekyll’s bottom-up approach — “you build only the features you actually use”.&lt;/p&gt;

&lt;p&gt;However, by having &lt;em&gt;someone else&lt;/em&gt; make all these project layout decisions for you, the result is a fairly clean and consistent project directory.&lt;/p&gt;

&lt;p&gt;I still found myself having to &lt;em&gt;turn off&lt;/em&gt; many of Hugo’s more advanced features to avoid needless page generations (such as a separate page for &lt;em&gt;each&lt;/em&gt; blog post tag).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hugo’s Plugin Ecosystem is Less Rich&lt;/strong&gt; Want a SASS compiler or HTML minifier plugin for your SSG? Those exist for Jekyll, but not for Hugo. Fortunately, many have encountered this problem and so the support for Hugo in the &lt;code&gt;gulp&lt;/code&gt; ecosystem is really good. Gulp has top-notch asset pipeline management plugins, so this becomes a non-issue if you’re willing to sprinkle a little Node.js in with your SSG.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Final Setup
&lt;/h2&gt;

&lt;p&gt;In the end, my asset pipeline looks a lot like Netlify’s &lt;a href="https://github.com/netlify/victor-hugo"&gt;victor-hugo&lt;/a&gt; template. I use gulp to compile my SASS and minify my assets (HTML, images, etc). The “victor-hugo” template also brings in &lt;a href="https://browsersync.io/"&gt;BrowserSync&lt;/a&gt;, which adds automatic refresh on rebuilds, among other niceties.&lt;/p&gt;

&lt;p&gt;You may be saying that I’ve effectively traded the Ruby ecosystem for the Golang &lt;em&gt;and&lt;/em&gt; Node.js ecosystems — and you’d be right. However, I’m significantly more confident in my ability to fix issues in this environment than I am in Ruby’s ecosystem, so I count that as a win.&lt;/p&gt;

&lt;p&gt;I’m hoping that I won’t have to mess with the setup too much. Stability is valuable for a project like this where what I &lt;em&gt;actually care about&lt;/em&gt; is writing, and all the SSG scaffolding is a distant second priority.&lt;/p&gt;

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

&lt;p&gt;Ultimately, this can be read as just another “Why I moved from $X to $Y” post. I’ve given Hugo a spin and I like it so far. It’s fast, expressive where it should be, and conservative where it needs to be.&lt;/p&gt;

&lt;p&gt;I try, as a rule, to not switch tech stacks on a whim. I’ve convinced myself that there are significant benefits in changing to Hugo, and so I’m hopeful that I’ll stick with this new setup for the next several years.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>writing</category>
    </item>
    <item>
      <title>Corral: A Serverless MapReduce Framework</title>
      <dc:creator>Benjamin Congdon</dc:creator>
      <pubDate>Wed, 02 May 2018 09:09:54 +0000</pubDate>
      <link>https://dev.to/benrcongdon/introducing-corral-a-serverless-mapreduce-framework-47bn</link>
      <guid>https://dev.to/benrcongdon/introducing-corral-a-serverless-mapreduce-framework-47bn</guid>
      <description>&lt;p&gt;I’ve been working recently with Hadoop and Spark for a class I help teach. PySpark is fantastic, but Hadoop MapReduce never really “clicked” for me until I found &lt;a href="https://pythonhosted.org/mrjob/"&gt;mrjob&lt;/a&gt;. The concept of MapReduce is incredibly powerful, but the amount of boilerplate needed to write even a simple Hadoop job in Java is, in my opinion, rather off-putting.&lt;/p&gt;

&lt;p&gt;Hadoop and Spark also require at least some infrastructure knowledge. Services like &lt;a href="https://aws.amazon.com/emr/"&gt;EMR&lt;/a&gt; and &lt;a href="https://cloud.google.com/dataproc/"&gt;Dataproc&lt;/a&gt; make this easier, but at a hefty cost.&lt;/p&gt;

&lt;p&gt;There have been past rumblings about using Lambda as a MapReduce platform. AWS published a (limited) &lt;a href="https://github.com/awslabs/lambda-refarch-mapreduce/"&gt;reference architecture&lt;/a&gt; and there are some enterprise solutions that seem to be taking this approach as well. However, I couldn’t find a fully developed open source project that took this approach.&lt;/p&gt;

&lt;p&gt;Around the same time, &lt;a href="https://aws.amazon.com/blogs/compute/announcing-go-support-for-aws-lambda/"&gt;AWS announced native Go support&lt;/a&gt; for Lambda. Go’s short startup time, ease of deployment (i.e. single-binary packages), and general speed made it a great candidate for this project.&lt;/p&gt;

&lt;p&gt;My idea was this: use Lambda as an execution environment, much like Hadoop MapReduce uses YARN. A local driver coordinates function invocation, and S3 is used for data storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="///img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/architecture.svg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xJeJnY9x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://benjamincongdon.me/img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/architecture.svg" alt="architecture.svg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The result is &lt;a href="https://github.com/bcongdon/corral"&gt;corral&lt;/a&gt;, a framework for writing arbitrary MapReduce applications that can be executed in AWS Lambda.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Golang Interface for MapReduce
&lt;/h2&gt;

&lt;p&gt;As Go famously doesn’t have generics, I had to scratch my head a bit to think of a compelling interface for mappers and reducers. Hadoop MapReduce has a large degree of flexibility in specifying input/output formats, the way records are split, and so on.&lt;/p&gt;

&lt;p&gt;I considered using &lt;code&gt;interface{}&lt;/code&gt; values for keys and values, but &lt;a href="https://www.youtube.com/watch?v=PAAkCSZUG1c&amp;amp;t=7m36s"&gt;in the words of Rob Pike&lt;/a&gt;, “&lt;code&gt;interface{}&lt;/code&gt; says nothing”. I decided on a minimalist interface: keys and values are strings. Input files are split by newlines. These simplifying assumptions made the implementation of the whole system simpler and cleaner. Hadoop MapReduce wins as far as customizability, so I decided to go for ease-of-use.&lt;/p&gt;

&lt;p&gt;I’m happy with the final interface for Map and Reduce (some of which was inspired by Damian Gryski’s &lt;a href="https://github.com/dgryski/dmrgo"&gt;dmrgo&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Mapper&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Map&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="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;emitter&lt;/span&gt; &lt;span class="n"&gt;Emitter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Reducer&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="n"&gt;ValueIterator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;emitter&lt;/span&gt; &lt;span class="n"&gt;Emitter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Emitter&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Emit&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="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ValueIterator&lt;/code&gt; has just one method: &lt;code&gt;Iter()&lt;/code&gt;, which iterates over a &lt;code&gt;range&lt;/code&gt; of strings.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Emitter&lt;/code&gt; and &lt;code&gt;ValueIterator&lt;/code&gt; hide a lot of internal framework implementation (shuffling, partitioning, filesystem interactions, etc). I’m also pleased that I decided on using an iterator for values instead of a normal slice (which would perhaps be more idiomatic), as an iterator allows for more flexibility on the framework’s side (i.e. to lazily stream values instead of having them all in memory).&lt;/p&gt;

&lt;h2&gt;
  
  
  Serverless MapReduce
&lt;/h2&gt;

&lt;p&gt;From the framework side of things, it took me a while to determine a performant way to implement MapReduce as a completely stateless system.&lt;/p&gt;

&lt;p&gt;Hadoop MapReduce’s architecture gives it the benefits of…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Persistent, long-running worker nodes&lt;/li&gt;
&lt;li&gt;Data locality at worker nodes&lt;/li&gt;
&lt;li&gt;Abstracted, fault-tolerant master/worker containers via YARN/Mesos/etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last 2 aspects of this are fairly easy to replicate with the AWS stack. Bandwidth between S3 and Lambda tends to be pretty good (at least for my purposes), and Lambda is built so that developers “don’t have to think about servers”.&lt;/p&gt;

&lt;p&gt;The trickiest thing to replicate on Lambda is persistent worker nodes. Lambda has a maximum timeout of 5 minutes. So, a lot of the way that Hadoop approaches MapReduce no longer work.&lt;/p&gt;

&lt;p&gt;For example, directly transferring data between a mapper worker and a reducer worker is infeasible because the mapper needs to be done “as quickly as possible”. Otherwise, you risk the mapper timing-out while the reducer is still working.&lt;/p&gt;

&lt;p&gt;This limitation manifests itself most during the shuffle/partition phase. Ideally, mappers would “live” long enough to transfer data to reducers on-demand (even &lt;em&gt;during&lt;/em&gt; the map phase), and reducers would “live” long enough to do a full secondary sort using their disk as spill-over for a large merge sort. The 5-minute cap makes these approaches tricky to infeasible.&lt;/p&gt;

&lt;p&gt;In the end, I decided to use S3 as the backend for a stateless partition/shuffle.&lt;/p&gt;

&lt;p&gt;&lt;a href="///img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/intermediate.svg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N1CnexIj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://benjamincongdon.me/img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/intermediate.svg" alt="Semantic Intermediate Filenames Used for Partition/Shuffle"&gt;&lt;/a&gt;Semantic Intermediate Filenames Used for Partition/Shuffle&lt;/p&gt;

&lt;p&gt;By using “prefix-friendly” names for mapper output, reducers can easily select which files they need to read.&lt;/p&gt;

&lt;p&gt;Dealing with input data was significantly more straightforward. Like Hadoop MapReduce, input files are split into chunks. Corral groups these file chunks into “input bins”, and each mapper reads/processes an input bin. The size of input splits and bins is configurable as needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="///img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/input_splits.svg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1VYaNrYs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://benjamincongdon.me/img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/input_splits.svg" alt="input_splits.svg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Self-deploying Applications
&lt;/h2&gt;

&lt;p&gt;One of the bits of corral that I was most excited about was that it’s able to self-deploy to AWS Lambda. I wanted it to be quick to deploy corral jobs to Lambda — having to manually re-upload deployment packages to Lambda via the web interface is a drag, and frameworks like Serverless rely on non-Go tools, which would be cumbersome to include.&lt;/p&gt;

&lt;p&gt;My initial thought was that the built corral binary would upload &lt;em&gt;itself&lt;/em&gt; to Lambda as a deployment package. This idea actually works… until you deal with cross-platform build targets. Lambda expects a binary compiled with &lt;code&gt;GOOS=linux&lt;/code&gt; , so any binary compiled on macOS or Windows wouldn’t work.&lt;/p&gt;

&lt;p&gt;I almost abandoned the idea at this point, but then I stumbled upon Kelsey Hightower’s &lt;a href="https://www.youtube.com/watch?v=XPC-hFL-4lU"&gt;Self Deploying Kubernetes Applications&lt;/a&gt; from GopherCon 2017. Kelsey described a similar approach, though his code ran on Kubernetes instead of Lambda. However, he described the “missing link” that I needed: Have the platform-specific binary recompile &lt;em&gt;itself&lt;/em&gt; to target &lt;code&gt;GOOS=linux&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, in sum, the process that corral uses to deploy to Lambda is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user compiles their corral application targeting their platform of choice.&lt;/li&gt;
&lt;li&gt;Upon execution, the corral app recompiles itself for &lt;code&gt;GOOS=linux&lt;/code&gt;, and compresses that generated binary into a zip file.&lt;/li&gt;
&lt;li&gt;Corral then uploads that zip file to Lambda, creating a Lambda function.&lt;/li&gt;
&lt;li&gt;Corral invokes this Lambda function as an executor for map/reduce tasks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Corral is able to use the &lt;em&gt;exact same&lt;/em&gt; source code as both a driver and remote executor by doing some clever inspection of the environment at runtime. If the binary detects that it’s in a Lambda environment it listens for an invocation request; otherwise, it behaves normally.&lt;/p&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;As an aside, the idea of self-uploading or self-recompiling applications is rather thrilling to me. I remember when I was taking a theory of computation class the concept of “self-embedding” programs (often referenced in the context of Undecidability proofs) were interesting, but I couldn’t think of a case in which you’d &lt;em&gt;actually&lt;/em&gt; want a program with that level of internal reflection.&lt;/p&gt;

&lt;p&gt;Self-deploying apps are, in a way, a pragmatic example of this idea. It’s a program that recompiles &lt;em&gt;itself&lt;/em&gt;, uploads &lt;em&gt;itself&lt;/em&gt; to the cloud, and invokes &lt;em&gt;itself&lt;/em&gt; remotely (albeit through distinct code paths). Neat stuff!&lt;/p&gt;

&lt;p&gt;Once deployed, the binary that corral uploads to Lambda conditionally behaves as a Mapper or Reducer depending on the input its invoked with. The binary that you execute locally keeps running and invokes Lambda functions during the Map/Reduce phases.&lt;/p&gt;

&lt;p&gt;&lt;a href="///img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/timeline.svg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OfcZbTbr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://benjamincongdon.me/img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/timeline.svg" alt="Corral Job Timeline"&gt;&lt;/a&gt;Corral Job Timeline&lt;/p&gt;

&lt;p&gt;Each component in the system is running the same source, but there are many parallel copies running in Lambda (as coordinated by the driver). This results in the parallelism that makes MapReduce &lt;em&gt;fast&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treating S3 Like a File System
&lt;/h2&gt;

&lt;p&gt;Corral, like mrjob, tries to be agnostic to the filesystem it runs on. This allows it to transparently switch between local and Lambda execution (and allows room for extension, such as if GCP begins to support Go in cloud functions).&lt;/p&gt;

&lt;p&gt;However, S3 isn’t &lt;em&gt;really&lt;/em&gt; a filesystem; it’s an object store. Using S3 like a filesystem requires a bit of cleverness. For example, when reading input splits corral needs to seek to a certain portion of a file and begin reading. By default, a GET request to S3 returns &lt;em&gt;the entire object&lt;/em&gt;. This isn’t great when your objects are potentially tens of gigabytes.&lt;/p&gt;

&lt;p&gt;Fortunately, &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html#RESTObjectGET-requests-request-headers"&gt;you can set a Range header&lt;/a&gt; in S3 GET requests to receive chunks of objects. Corral’s &lt;a href="https://github.com/bcongdon/corral/blob/master/internal/pkg/corfs/s3.go#L104"&gt;S3FileSystem&lt;/a&gt; leverages this, downloading chunks of an object at a time as necessary.&lt;/p&gt;

&lt;p&gt;Writing to S3 also requires a bit of thought. For small uploads, a standard “PUT Object” request is fine. For larger uploads, &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuoverview.html"&gt;multipart uploads&lt;/a&gt; become more appealing. Multipart uploads allow for the functional equivalent of writing to a local file; you “stream” data to a file, instead of retaining it in memory to write all at once.&lt;/p&gt;

&lt;p&gt;To my surprise, there wasn’t a great S3 client that provided &lt;code&gt;io.Reader&lt;/code&gt; and &lt;code&gt;io.Writer&lt;/code&gt; interfaces. &lt;a href="https://github.com/rlmcpherson/s3gof3r"&gt;s3gof3r&lt;/a&gt; is the closest thing I could find; it’s pretty good, but (in my experience) leaks so much memory that I couldn’t use it in the memory-limited Lambda environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Management in Lambda
&lt;/h2&gt;

&lt;p&gt;While AWS Lambda has been gaining steam for the past few years, it feels like the tooling for profiling Lambda functions is lacking. Lambda does, by default, log to Cloudwatch. If your function panics, a stack trace is logged. As such, “crashing” errors are relatively straightforward to debug.&lt;/p&gt;

&lt;p&gt;However, if your function runs out of memory or time, all you’ll see is 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;REPORT RequestId: 16e55aa5-4a87-11e8-9c63-3f70efb9da7e Duration: 1059.94 ms Billed Duration: 1100 ms Memory Size: 1500 MB Max Memory Used: 1500 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Locally, tools like &lt;a href="https://golang.org/pkg/runtime/pprof/"&gt;pprof&lt;/a&gt; are fantastic for getting a sense of where memory leaks come from. In Lambda, you have no such luck.&lt;/p&gt;

&lt;p&gt;In an early version of corral, I spent hours tracking down a memory leak that ultimately was caused by &lt;a href="https://github.com/rlmcpherson/s3gof3r"&gt;s3gof3r&lt;/a&gt;. Since &lt;a href="https://aws.amazon.com/blogs/compute/container-reuse-in-lambda/"&gt;Lambda containers are reused&lt;/a&gt;, even small memory leaks will result in eventual failure. In other words, memory usage persists across invocations — a leaky abstraction (no pun intended).&lt;/p&gt;

&lt;p&gt;It’d be great to see better profiling tools for AWS Lambda, especially since Golang is a notably easy runtime to profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Lambda Becomes Expensive
&lt;/h2&gt;

&lt;p&gt;Ostensibly, the goal of corral is to provide a cheap, fast alternative to Hadoop MapReduce. AWS Lambda is cheap, so this should be a slam dunk, right?&lt;/p&gt;

&lt;p&gt;Yes and no. The free tier of Lambda gives you 400,000 GB-seconds per month. This sounds like a lot but gets used up quickly by long-running applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="///img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/lambda_pricing.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jrV1oHta--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://benjamincongdon.me/img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/lambda_pricing.png" alt="Lambda Pricing Scheme as of 4/29/2018"&gt;&lt;/a&gt;Lambda Pricing Scheme as of 4/29/2018&lt;/p&gt;

&lt;p&gt;Ultimately, corral can still end up being very inexpensive. However, you’ll want to tune your application to use as little memory as possible. Set the maximum memory in corral as low as possible to reduce cost.&lt;/p&gt;

&lt;p&gt;Time is an as-you-use-it resource in AWS Lambda — you’re charged for as many milliseconds as you use. Memory is billed by use-it-or-lose-it. If you set the max memory to 3GB but only use 500MB, you’re still paying for the full 3GB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;While not a primary design consideration, corral’s performance is fairly respectable. Much of this is due to the nearly infinite parallelism that Lambda offers. I used the &lt;a href="https://amplab.cs.berkeley.edu/benchmark/"&gt;Amplab “Big Data Benchmark”&lt;/a&gt; to get a sense of corral’s performance. This benchmark tests basic filters, aggregations, and joins.&lt;/p&gt;

&lt;p&gt;As I anticipated, corral does quite well on filtering and aggregation. However, it falls flat on joins. Without a &lt;a href="https://www.safaribooksonline.com/library/view/data-algorithms/9781491906170/ch01.html"&gt;secondary sort&lt;/a&gt;, joins become expensive.&lt;/p&gt;

&lt;p&gt;The Amplab benchmark tests up to ~125GB of input data. I’d be curious to do more benchmarking with around ~1TB of data to see if performance continues to scale more-or-less linearly.&lt;/p&gt;

&lt;p&gt;More information and benchmark statistics can be found in the &lt;a href="https://github.com/bcongdon/corral/tree/master/examples"&gt;corral examples folder&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;So that’s it: corral let’s you write a simple MR job, frictionlessly deploy it to Lambda, and run jobs on datasets in S3.&lt;/p&gt;

&lt;p&gt;&lt;a href="///img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/word_count.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TD_2Jx4c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/http://benjamincongdon.me/img/2018-05-02-Introducing-Corral-A-Serverless-MapReduce-Framework/word_count.gif" alt="Running a word count job in Lambda"&gt;&lt;/a&gt;Running a word count job in Lambda&lt;/p&gt;

&lt;p&gt;It’s also worth noting that I’m not wedded to the AWS ecosystem. Corral is mostly agnostic to Lambda and S3 so that, in the future, connectors to GCP’s Cloud Functions and Datastore could be added (if/when GCP adds Go support to CF).&lt;/p&gt;

&lt;p&gt;On a personal note, I found this project to be quite rewarding to work on. There were many fewer resources online for &lt;em&gt;building&lt;/em&gt; a MapReduce system than for &lt;em&gt;using&lt;/em&gt; one, so there were some implementation details that I got to work out.&lt;/p&gt;

&lt;p&gt;Feel free to make issues in the &lt;a href="https://github.com/bcongdon/corral"&gt;corral repository&lt;/a&gt;. I’m curious to see if there’s a big enough niche that this project fills to justify continued development. 😁&lt;/p&gt;

</description>
      <category>go</category>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Counting Scanned Bytes in Go</title>
      <dc:creator>Benjamin Congdon</dc:creator>
      <pubDate>Tue, 10 Apr 2018 11:30:59 +0000</pubDate>
      <link>https://dev.to/benrcongdon/counting-scanned-bytes-in-go-2lbo</link>
      <guid>https://dev.to/benrcongdon/counting-scanned-bytes-in-go-2lbo</guid>
      <description>&lt;p&gt;For a recent project, I needed to read data from a specific chunk of a file. The data was a sequence of serialized records, so I used a &lt;code&gt;bufio&lt;/code&gt; Scanner for splitting. Scanners are great, but they obscure the exact number of bytes read. In working through the problem, I found a solution that worked quite nicely.&lt;/p&gt;

&lt;p&gt;Essentially, the problem boiled down to this: I wanted to use &lt;code&gt;bufio&lt;/code&gt;’s Scanner to cleanly split data records, but I also needed fine-grain control over exactly how many bytes were being read. Simply counting the bytes in the input record is insufficient, because data records may be split using variable-width delimiters&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;. (i.e. &lt;code&gt;\n&lt;/code&gt; vs &lt;code&gt;\r\n&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="///img/2018-04-10-Counting-Scanned-Bytes-in-Go/chunk_setup.svg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dukw43_a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://benjamincongdon.me/img/2018-04-10-Counting-Scanned-Bytes-in-Go/chunk_setup.svg" alt="Problem: Read &amp;amp; Split Records until Chunk Boundary Is Reached"&gt;&lt;/a&gt;Problem: Read &amp;amp; Split Records until Chunk Boundary Is Reached&lt;/p&gt;

&lt;p&gt;My initial thought was to wrap the &lt;code&gt;io.Reader&lt;/code&gt; that I was reading records from. The result looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;CountingReader&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reader&lt;/span&gt;
    &lt;span class="n"&gt;BytesRead&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;CountingReader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BytesRead&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method &lt;em&gt;does&lt;/em&gt; work as advertised, in that it counts the number of bytes read from the reader. However, it &lt;em&gt;doesn’t&lt;/em&gt; actually solve my problem – counting the number of bytes read as records. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewBuffer&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo bar baz"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;CountingReader&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;scanner&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewScanner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ScanWords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c"&gt;// "foo"&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BytesRead&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 11 :(&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(You can try this on the &lt;a href="https://play.golang.org/p/fRgb06S-LlH"&gt;Go Playground&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The reason for this behavior, as I found out, is that &lt;code&gt;bufio.Scanner&lt;/code&gt; maintains an &lt;a href="https://golang.org/src/bufio/scan.go?s=1184:1841#L20"&gt;internal buffer&lt;/a&gt; which it reads to in large chunks. My &lt;code&gt;CountingReader&lt;/code&gt; could (correctly) say that 11 bytes had been read from it, even though only, say, 4 bytes of data (&lt;code&gt;"foo "&lt;/code&gt;) had been yielded from the Scanner.&lt;/p&gt;

&lt;p&gt;My next thought was to implement a &lt;code&gt;CountingScanner&lt;/code&gt; by wrapping or reimplementing &lt;code&gt;buffio.Scanner&lt;/code&gt; to count processed bytes. Neither of these options was appealing. The &lt;code&gt;io&lt;/code&gt; module also has &lt;a href="https://golang.org/pkg/io/#LimitedReader"&gt;LimitReader&lt;/a&gt; which enforces a maximum number of bytes read. For my problem, this wouldn’t work; my reader needs to completely read the last record in the chunk of the file, even it if spans the cutoff point.&lt;/p&gt;

&lt;p&gt;&lt;a href="///img/2018-04-10-Counting-Scanned-Bytes-in-Go/split_diagram.svg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s2T4Hq6q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://benjamincongdon.me/img/2018-04-10-Counting-Scanned-Bytes-in-Go/split_diagram.svg" alt="io.LimitReader would not allow Logical Splitting"&gt;&lt;/a&gt;io.LimitReader would not allow Logical Splitting&lt;/p&gt;

&lt;p&gt;In the end, I tried wrapping the scanner’s &lt;a href="https://golang.org/pkg/bufio/#SplitFunc"&gt;SplitFunc&lt;/a&gt;. For reference, SplitFunc has the following signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SplitFunc&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;atEOF&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;advance&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essentially, &lt;code&gt;SplitFunc&lt;/code&gt; takes a slice of bytes and returns how many bytes forward the Scanner should advance along with the “token” extracted from the byte slice.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;advance&lt;/code&gt; return value is exactly what I want: how many bytes were truly processed by the Scanner.&lt;/p&gt;

&lt;p&gt;From here, I put together a simple struct that wraps a &lt;code&gt;SplitFunc&lt;/code&gt;, and increments an internal counter each time a split is performed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ScanByteCounter&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;BytesRead&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ScanByteCounter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SplitFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SplitFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;atEOF&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;adv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;atEOF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BytesRead&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;adv&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;adv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo bar baz"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ScanByteCounter&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="n"&gt;scanner&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewScanner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;splitFunc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ScanWords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;splitFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Split Text: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bytes Read: %d&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BytesRead&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// Split Text: foo&lt;/span&gt;
    &lt;span class="c"&gt;// Bytes Read: 4&lt;/span&gt;

    &lt;span class="c"&gt;// Split Text: bar&lt;/span&gt;
    &lt;span class="c"&gt;// Bytes Read: 8&lt;/span&gt;

    &lt;span class="c"&gt;// Split Text: baz&lt;/span&gt;
    &lt;span class="c"&gt;// Bytes Read: 11&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the results were successful! Try this on the &lt;a href="https://play.golang.org/p/YOo7BJOhITO"&gt;Go Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are some lessons learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function wrapping is a good way to extend the usefulness of standard library features&lt;/li&gt;
&lt;li&gt;Beware of making assumptions about how much data is being read from/to buffers (especially when Readers/Writers are consumed by other interfaces)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m also curious if there’s an official way for solving this problem. If there’s a cleaner solution, let me know! 😄&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover: &lt;a href="https://pixabay.com/en/city-travel-cityscape-aerial-3142651/"&gt;Pixabay&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

&lt;p&gt;&lt;span id="fn:1"&gt;1.&lt;/span&gt; I also wanted to support the general case of an arbitrary SplitFunc, so anything based on delimiter size was out.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Python Idioms in Rust</title>
      <dc:creator>Benjamin Congdon</dc:creator>
      <pubDate>Fri, 23 Mar 2018 12:23:22 +0000</pubDate>
      <link>https://dev.to/benrcongdon/python-idioms-in-rust-4381</link>
      <guid>https://dev.to/benrcongdon/python-idioms-in-rust-4381</guid>
      <description>&lt;p&gt;I’ve been going through a period of programming language wanderlust over the past couple months. Recently, I’ve been quite interested in Rust. Coming from Python, I’ve found a lot of Rust’s language features to be quite powerful.&lt;/p&gt;

&lt;p&gt;Earlier this year, I dug deep into Go. For the most part, I enjoy Go: It’s a simple language that can be learned in a few hours (literally). Its structure promotes good programming practices and it has a wonderful ecosystem.&lt;/p&gt;

&lt;p&gt;However, in Go, I felt limited by the expressiveness of the language. Its much-bemoaned lack of generics is less disruptive than one would expect but makes clever functional-programming tricks essentially impossible. That’s fine — it’s not what Go was designed for — but as a result, I found Go a bit less “fun” to work in.&lt;/p&gt;

&lt;p&gt;While Rust does have additional complications coming from it’s &lt;a href="https://m-decoster.github.io//2017/01/16/fighting-borrowchk/"&gt;infamous borrow checker&lt;/a&gt; and the complexity of generics, I’ve found that what you gain in expressiveness is worth the tradeoff.&lt;/p&gt;

&lt;p&gt;In fact, I found Rust to be rather Pythonic&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;. ✨ Sure, you have to be careful about types and ownership, but there is a strong case to be made that Rust shares many of the strengths of Python’s syntax.&lt;/p&gt;

&lt;p&gt;After doing a bit of work in Rust, I identified some idioms&lt;sup id="fnref:2"&gt;2&lt;/sup&gt; common to Rust and Python. These common features are all things that I enjoy using in Python, and I’ve found to be useful while coming up-to-speed on Rust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enumerate
&lt;/h2&gt;

&lt;p&gt;A common pattern in when iterating over lists in Python is to use &lt;code&gt;enumerate&lt;/code&gt; to have get both the index and value of list elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, {}"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# 0, a
# 1, b
# 2, c
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rust iterators also support &lt;code&gt;enumerate&lt;/code&gt;! (And you don’t even have to learn a new name for the same functionality)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.enumerate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Zip
&lt;/h2&gt;

&lt;p&gt;Another function on iterators that you see pretty frequently in Python is &lt;code&gt;zip&lt;/code&gt;, which combines 2 iterators element-wise, creating an iterator of tuples with an element of each list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, {}"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# a, 1
# b, 2
# c, 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, Rust iterators also support &lt;code&gt;zip&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;zipped&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zipped&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// (1, 'a')&lt;/span&gt;
&lt;span class="c"&gt;// (2, 'b')&lt;/span&gt;
&lt;span class="c"&gt;// (3, 'c')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like Python’s &lt;code&gt;zip&lt;/code&gt;, Rust’s &lt;code&gt;zip&lt;/code&gt; halts when either of the iterators is exhausted. This allows you to do cool tricks with infinite iterators:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;start_at_10&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;zipped&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;start_at_10&lt;/span&gt;&lt;span class="nf"&gt;.zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zipped&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// (10, 'a')&lt;/span&gt;
&lt;span class="c"&gt;// (11, 'b')&lt;/span&gt;
&lt;span class="c"&gt;// (12, 'c')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tuples
&lt;/h2&gt;

&lt;p&gt;Rust has tuples! This is a feature that I sorely missed in Go. Yes, &lt;code&gt;struct&lt;/code&gt;s work just as well, but for “scripting” or prototype work, tuples are a great language feature.&lt;/p&gt;

&lt;p&gt;Python’s tuple system is pretty flexible. Functionally, Python tuples act like immutable lists. Tuples can be aliased into separate variables via unpacking, and are indexed-into like lists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="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;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'foo'&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'foo'&lt;/span&gt;

&lt;span class="c1"&gt;# Tuples are immutable in Python
&lt;/span&gt;&lt;span class="n"&gt;tup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="n"&gt;tup&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="c1"&gt;# TypeError: 'tuple' object does not support item assignment
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rust’s &lt;a href="https://rustbyexample.com/primitives/tuples.html"&gt;tuple feature&lt;/a&gt; is also quite powerful. Similar to Python, you can alias tuple values into separate variables using syntactic sugar, although in Rust this is called “destructuring” instead of “unpacking”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&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="nn"&gt;None&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&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;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;// "foo"&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;// "foo"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, Rust tuples aren’t indexed using square brackets (&lt;code&gt;foo[0]&lt;/code&gt;), but rather by the dot operator (&lt;code&gt;foo.0&lt;/code&gt;). This is a byproduct of the fact that Rust tuples are sized at compile-time, unlike Python tuples which are dynamic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dynamically sized tuples in Python
&lt;/span&gt;&lt;span class="n"&gt;tup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'foo'&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike in Python, Rust tuples can be made mutable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;tup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="n"&gt;tup&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  List Comprehensions (kind of)
&lt;/h2&gt;

&lt;p&gt;List comprehensions are the bread-and-butter of Python syntactic sugar. It’s a super expressive way of generating/filtering lists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;evens_squared&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&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;# [0, 4, 16, 36, 64]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rust doesn’t have list comprehensions &lt;em&gt;per se&lt;/em&gt;, but Rust iterators &lt;em&gt;do&lt;/em&gt; have &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;filter&lt;/code&gt;, which allow you to perform similarly expressive “list” generation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;evens_squared&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;evens_squared&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c"&gt;// [0, 4, 16, 36, 64]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Personally, I like Rust’s extensive iterator functions &lt;em&gt;even better&lt;/em&gt; than Python’s. I found functions like &lt;a href="https://doc.rust-lang.org/1.15.1/std/iter/trait.Iterator.html#method.flat_map"&gt;flat_map&lt;/a&gt; and &lt;a href="https://doc.rust-lang.org/1.15.1/std/iter/struct.Scan.html"&gt;scan&lt;/a&gt; (among others) to be quite useful. These iterator functions bring aspects of functional programming to Rust that I really enjoy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Single-Line If
&lt;/h2&gt;

&lt;p&gt;Neither Python nor Rust has &lt;a href="https://en.wikipedia.org/wiki/Ternary_operation"&gt;ternary operators&lt;/a&gt; (which may be for the best). However, they both support single-line conditional expressions. This can be useful in certain conditions, but it’s really just syntactic sugar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;expensive_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;some_condition&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nb"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;some_condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;expensive_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lambda Functions
&lt;/h2&gt;

&lt;p&gt;An oft complained-about language feature of Python is its &lt;code&gt;lambda&lt;/code&gt; functions. They’re useful, but the syntax isn’t great. Other languages like Ruby and Javascript have more terse syntax for specifying closures or inline functions.&lt;/p&gt;

&lt;p&gt;Python &lt;code&gt;lambda&lt;/code&gt;s take a set of arguments and return the evaluation of the expression that follows the &lt;code&gt;:&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# [10, 15, 3]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rust closures are similarly expressive. They use pipes (&lt;code&gt;|&lt;/code&gt;) to hold arguments and the expression that follows is used as the return value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&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="n"&gt;arr&lt;/span&gt;&lt;span class="nf"&gt;.sort_by_key&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="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;-&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;.abs&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rust closures can also be multiline functions using brackets, which is quite handy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&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="n"&gt;arr&lt;/span&gt;&lt;span class="nf"&gt;.sort_by_key&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;intermediate_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;some_function&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;intermediate_value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both Python &lt;code&gt;lambda&lt;/code&gt;s and Rust closures perform variable capture, so you can have access to variables that are in-scope where the lambda/closure is created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;plus_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&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;plus_a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;plus_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&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;plus_a&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="c"&gt;// 15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  First-Class Functions
&lt;/h2&gt;

&lt;p&gt;In Python, functions are essentially objects that are invoked with the &lt;code&gt;__call__&lt;/code&gt; magic function. They can be passed around like any other object and can even have attributes assigned to them. This can be useful for passing callback functions. While idiomatic Python doesn’t make extensive use of functions-as-variables, this feature comes in handy pretty often.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;plus_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;map_on_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="n"&gt;map_on_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plus_one&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# [2, 3, 4]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rust also has first-class functions. Functions and closures can be used as argument to other functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;plus_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;map_on_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;new_vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;new_vec&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;new_vec&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;map_on_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plus_one&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c"&gt;// [2, 3, 4]&lt;/span&gt;

&lt;span class="c"&gt;// Equivalently:&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;map_on_vec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interestingly, there are some subtle differences between Rust functions and closures. &lt;sup id="fnref:3"&gt;3&lt;/sup&gt; In general, they can be treated as the same thing. Of course, functions are &lt;em&gt;not&lt;/em&gt; objects in Rust, but a Rust struct can implement the &lt;a href="https://doc.rust-lang.org/std/ops/trait.Fn.html"&gt;Fn&lt;/a&gt;, &lt;a href="https://doc.rust-lang.org/std/ops/trait.FnMut.html"&gt;FnMut&lt;/a&gt;, or &lt;a href="https://doc.rust-lang.org/std/ops/trait.FnOnce.html"&gt;FnOnce&lt;/a&gt; traits to similar effect of Python’s &lt;code&gt;__call__&lt;/code&gt; (though this is &lt;a href="https://stackoverflow.com/a/38672502/2421634"&gt;not recommended&lt;/a&gt;).&lt;/p&gt;

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

&lt;p&gt;Hopefully, I’ve given a bit of a hint as to why a Python dev might be interested in picking up Rust (for aesthetic reasons, if nothing else!). There’s a definite learning curve to Rust, but it’s a speedy language that still remains quite expressive.&lt;/p&gt;

&lt;p&gt;From a syntactic sense, I found Rust to be more similar to Python than Python is to Go. Using generics and type inference, you can end up writing Rust code that has only minimal “type boilerplate” and &lt;em&gt;feels&lt;/em&gt; pretty similar to Python.&lt;/p&gt;

&lt;p&gt;If you’re interested in looking into Rust, I’d highly recommend the following resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://doc.rust-lang.org/book/second-edition/"&gt;The Rust Programming Language&lt;/a&gt; - Official (free) book that walks you through the Rust language&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://doc.rust-lang.org/std/"&gt;Rust Language Documentation&lt;/a&gt; - The API docs of the Rust language — it’s search functionality is pretty great&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/rust/"&gt;/r/rust&lt;/a&gt; - The Rust Subreddit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Cover: &lt;a href="https://pixabay.com/en/crab-baskets-scotland-fishing-2550284/"&gt;Pixabay&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;

&lt;p&gt;&lt;span id="fn:1"&gt;1.&lt;/span&gt; &lt;a href="https://twitter.com/mitsuhiko"&gt;Armin Ronacher&lt;/a&gt; did a &lt;a href="https://www.youtube.com/watch?v=zmtHaZG7pPc"&gt;great talk&lt;/a&gt; about pairing Rust and Python that expands upon this notion of Rust being “Pythonic”&lt;/p&gt;

&lt;p&gt;&lt;span id="fn:2"&gt;2.&lt;/span&gt; Some of these are probably better defined as syntactic sugar or language features. 😛&lt;/p&gt;

&lt;p&gt;&lt;span id="fn:3"&gt;3.&lt;/span&gt; Ricardo Martins wrote a &lt;a href="https://ricardomartins.cc/2015/10/12/practical_differences_between_rust_closures_and_functions"&gt;blog post&lt;/a&gt; about this distinction between functions and closures&lt;/p&gt;

</description>
      <category>python</category>
      <category>rust</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
