<?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: Ary Borenszweig</title>
    <description>The latest articles on DEV Community by Ary Borenszweig (@asterite).</description>
    <link>https://dev.to/asterite</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%2F32475%2Ff1bbe688-bffc-4623-8eb6-441c146f0369.png</url>
      <title>DEV Community: Ary Borenszweig</title>
      <link>https://dev.to/asterite</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/asterite"/>
    <language>en</language>
    <item>
      <title>Incremental compilation for Crystal - Part 3</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Thu, 05 Jan 2023 13:48:40 +0000</pubDate>
      <link>https://dev.to/asterite/incremental-compilation-for-crystal-part-2-3184</link>
      <guid>https://dev.to/asterite/incremental-compilation-for-crystal-part-2-3184</guid>
      <description>&lt;h1&gt;
  
  
  Recap from the previous two posts
&lt;/h1&gt;

&lt;p&gt;In the last two posts we saw a way to generate dependencies between files like this: if a method call is made, the file where that call happens depends on the file where the method is defined. And that dependencies are transitive because of how Crystal works.&lt;/p&gt;

&lt;p&gt;Then we saw that the file dependencies graph is quite messy for real programs and that changing one file usually affects most of the other files.&lt;/p&gt;

&lt;h1&gt;
  
  
  An observation
&lt;/h1&gt;

&lt;p&gt;After writing the last post I realized there's something slightly wrong in the way dependencies, and more precisely transitive dependencies, are tracked.&lt;/p&gt;

&lt;p&gt;Consider the following files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# foo.cr&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;
  &lt;span class="n"&gt;bar&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt;

&lt;span class="c1"&gt;# bar.cr&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"baz"&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"qux"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;
  &lt;span class="n"&gt;baz&lt;/span&gt;
  &lt;span class="n"&gt;qux&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# baz.cr&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;baz&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# qux.cr&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;qux&lt;/span&gt;
  &lt;span class="s2"&gt;"hello"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Doing a dependencies graph for the above program gives this:&lt;/p&gt;

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

&lt;p&gt;So &lt;code&gt;bar.cr&lt;/code&gt; depends on both &lt;code&gt;baz.cr&lt;/code&gt; and &lt;code&gt;qux.cr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we change the method &lt;code&gt;qux&lt;/code&gt; to return an int, &lt;code&gt;bar&lt;/code&gt; will start retuning an int, and so &lt;code&gt;foo&lt;/code&gt; will start returning an int: transitive dependencies doing their stuff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BUT&lt;/strong&gt;, and this is the important bit, if we change the method &lt;code&gt;baz&lt;/code&gt; to return a different type, no matter what type, and no matter how many changes we do to it, we do need to re-compile and re-analize &lt;code&gt;bar&lt;/code&gt;, but it doesn't affect &lt;code&gt;foo&lt;/code&gt; because &lt;code&gt;baz&lt;/code&gt; is not being used as a return value of &lt;code&gt;bar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That means that the messy dependencies graph we have so far might not be that messy after all. And also, that we have two graphs: direct dependencies and transitive dependencies.&lt;/p&gt;

&lt;p&gt;When we checked the method &lt;code&gt;IO#&amp;lt;&amp;lt;&lt;/code&gt; and saw that it calls &lt;code&gt;obj.to_s&lt;/code&gt;, so &lt;code&gt;io.cr&lt;/code&gt; depends on whatever type we give to &lt;code&gt;IO#&amp;lt;&amp;lt;&lt;/code&gt;, the method definition is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But note that the &lt;code&gt;obj.to_s&lt;/code&gt; call isn't part of the return type. That means that, yes, if the file where the type of &lt;code&gt;obj&lt;/code&gt; changes we need to recompile &lt;code&gt;io.cr&lt;/code&gt;, but it doesn't mean we have to recompile files that depend on &lt;code&gt;io.cr&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Computing actual transitive dependencies
&lt;/h1&gt;

&lt;p&gt;Now, the main issue is determining which method calls affect the return type.&lt;/p&gt;

&lt;p&gt;For example, consider this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&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;bar&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the method returns &lt;code&gt;x&lt;/code&gt;, and &lt;code&gt;x&lt;/code&gt; came from a call to &lt;code&gt;bar&lt;/code&gt;, so &lt;code&gt;foo&lt;/code&gt; transitively depends on &lt;code&gt;bar&lt;/code&gt;. So we have to keep track of how variables came to exist, and their dependencies. Luckily the Crystal compiler already keeps track of this to actually compute the type of &lt;code&gt;x&lt;/code&gt;, so in theory this should be easy to do.&lt;/p&gt;

&lt;p&gt;Another example is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;
  &lt;span class="n"&gt;qux&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt;
    &lt;span class="n"&gt;bar&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;baz&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the last expression in the method is an &lt;code&gt;if&lt;/code&gt;, so the actual dependencies of &lt;code&gt;foo&lt;/code&gt; are &lt;code&gt;bar&lt;/code&gt; and &lt;code&gt;baz&lt;/code&gt;, but not &lt;code&gt;qux&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another dependency that might not be easy to see is call arguments. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;
  &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;foo&lt;/code&gt; depends on &lt;code&gt;bar&lt;/code&gt;. But does it depend on &lt;code&gt;baz&lt;/code&gt;? Well, if &lt;code&gt;baz&lt;/code&gt; suddenly changes and returns a different type, another overload of &lt;code&gt;bar&lt;/code&gt; might be hit that returns a different type, and so &lt;code&gt;foo&lt;/code&gt; might start returning a different type. So it seems that call arguments need to be taken into account.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's next?
&lt;/h1&gt;

&lt;p&gt;I'll need some time to code this and get it right. Once I do that I'll post my findings. Will the dependencies graph be leaner? Will we find happiness? Will it make us cry? Stay tuned!&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>incremental</category>
      <category>compilers</category>
      <category>compilation</category>
    </item>
    <item>
      <title>Incremental compilation for Crystal - Part 2</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Wed, 04 Jan 2023 18:27:25 +0000</pubDate>
      <link>https://dev.to/asterite/incremental-compilation-for-crystal-part-2-5h59</link>
      <guid>https://dev.to/asterite/incremental-compilation-for-crystal-part-2-5h59</guid>
      <description>&lt;p&gt;In the last post we found out that we could build a file dependencies graph for a given project. We also saw that, depending on the code, a file could depend on one another even if it's not immediately clear that that's the case.&lt;/p&gt;

&lt;p&gt;But... is that dependency issue really an issue?&lt;/p&gt;

&lt;h1&gt;
  
  
  Checking the tool against real-world projects
&lt;/h1&gt;

&lt;p&gt;In this section I'll look at the dependencies graph of two medium/big projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mint-lang/mint"&gt;Mint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Crystal compiler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can use &lt;a href="%5Bbranch%5D(https://github.com/asterite/crystal-1/tree/dot-dependencies)"&gt;this branch&lt;/a&gt; of the compiler to compile Mint and the compiler to get the "dependencies.dot" files.&lt;/p&gt;

&lt;p&gt;Then we can use &lt;a href="https://gist.github.com/asterite/c96cef663e4700d7512ad251b0e31494"&gt;this program&lt;/a&gt; to analyze the above files. The program will read a "dependencies.dot" file, build the graph in memory, and then for each node in that graph count how many nodes are, recursively, affected by it. This answers this question: if we make a change to a file, what are all the files that we need to re-analyze?&lt;/p&gt;

&lt;h1&gt;
  
  
  Transitive dependencies
&lt;/h1&gt;

&lt;p&gt;Before looking at that, though, note that I said "recursively". If a file A depends on B, and B depends on C, why if we make changes to C we need to re-analyze A?&lt;/p&gt;

&lt;p&gt;Let's take a look at an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# foo.cr&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;
  &lt;span class="no"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt;

&lt;span class="c1"&gt;# bar.cr&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"baz"&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Bar&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;
    &lt;span class="no"&gt;Baz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;baz&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# baz.cr&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Baz&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;baz&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have that &lt;code&gt;foo.cr&lt;/code&gt; depends on &lt;code&gt;bar.cr&lt;/code&gt;, and &lt;code&gt;bar.cr&lt;/code&gt; depends on &lt;code&gt;baz.cr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What does &lt;code&gt;foo&lt;/code&gt; return? It returns an integer, because &lt;code&gt;foo&lt;/code&gt; calls &lt;code&gt;Bar.bar&lt;/code&gt;, which in turn calls &lt;code&gt;Baz.baz&lt;/code&gt;, which returns 1.&lt;/p&gt;

&lt;p&gt;If we change &lt;code&gt;Baz.baz&lt;/code&gt; to return a string, &lt;code&gt;foo&lt;/code&gt; will start returning a string too. So, effectively, changing &lt;code&gt;baz.cr&lt;/code&gt; affected &lt;code&gt;foo.cr&lt;/code&gt;. And note that the program still compiles just fine.&lt;/p&gt;

&lt;p&gt;Does this transitive dependency re-analysis happen in other languages too? I don't know. But let's imagine Crystal forces you to specify argument and return types for methods, like Java, C#, Go, Rust, and essentially every statically typed language out there.&lt;/p&gt;

&lt;p&gt;Now we have these files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# foo.cr&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;
  &lt;span class="no"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt;

&lt;span class="c1"&gt;# bar.cr&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"baz"&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Bar&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;
    &lt;span class="no"&gt;Baz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;baz&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# baz.cr&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Baz&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;baz&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we change &lt;code&gt;Baz.baz&lt;/code&gt; to return a &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Bar&lt;/code&gt; will stop compiling. We can change &lt;code&gt;Bar.bar&lt;/code&gt; to return a &lt;code&gt;String&lt;/code&gt; and then change &lt;code&gt;foo&lt;/code&gt; to return a &lt;code&gt;String&lt;/code&gt; and then it will compile again. But doing that we changed all those files, so they naturally have to be re-analyzed.&lt;/p&gt;

&lt;p&gt;But files don't always have to be re-analyzed like this. Let's say we change &lt;code&gt;Baz.baz&lt;/code&gt; to return a &lt;code&gt;String&lt;/code&gt;. We can make &lt;code&gt;Bar&lt;/code&gt; still compile and return an &lt;code&gt;Int32&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Bar&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;
    &lt;span class="no"&gt;Baz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="c1"&gt;# The size of the string&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we ended up changing &lt;code&gt;Bar&lt;/code&gt; because of changes made to &lt;code&gt;Baz&lt;/code&gt;, but we didn't have to change &lt;code&gt;foo&lt;/code&gt;. Not only that: we don't have to re-analyze &lt;code&gt;foo&lt;/code&gt; because &lt;code&gt;Bar.bar&lt;/code&gt; still returns an int. We need to re-compile &lt;code&gt;bar.cr&lt;/code&gt;, but &lt;code&gt;foo&lt;/code&gt; can still keep calling the same method.&lt;/p&gt;

&lt;p&gt;With all this, another partial conclusion is that not having mandatory type signatures in methods means even more that a change in one file can affect files that are far away in the dependency graph.&lt;/p&gt;

&lt;h1&gt;
  
  
  Checking affected files counts
&lt;/h1&gt;

&lt;p&gt;If we run the &lt;a href="%5Bthis%20program%5D(https://gist.github.com/asterite/c96cef663e4700d7512ad251b0e31494)"&gt;above mentioned program&lt;/a&gt; on the "dependencies.dot" file for Mint, we'll see 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;src/macros.cr: 1
src/mint.cr: 1
src/utils/index_html.ecr: 1
src/utils/service_worker.ecr: 1
src/constants.cr: 2
src/app_init/scaffold.cr: 1193
src/artifact_cleaner.cr: 1193
src/assets.cr: 1193
src/ast.cr: 1193
...
1059 lines more
...

Total files: 1405
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I forgot to mention that this only outputs files in "your project". That is, the most common scenario is that you'll change files in your project, not in shards or the standard library.&lt;/p&gt;

&lt;p&gt;Also, the output is sorted by number of affected files for a given file.&lt;/p&gt;

&lt;p&gt;In this project there are a total of 1405 files, including files from shards and the standard library. And for the vast majority of files, if we make a change to them it ends up affecting 1193 files. That means that we'll end up needing to re-analyze most of the files anyway.&lt;/p&gt;

&lt;p&gt;Doing this with the compiler is similar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/compiler/crystal.cr: 1
src/compiler/crystal/tools/doc/html/_head.html: 1
src/compiler/crystal/tools/doc/html/_list_items.html: 1
src/compiler/crystal/tools/doc/html/_method_detail.html: 1
src/compiler/crystal/tools/doc/html/_method_summary.html: 1
src/compiler/crystal/tools/doc/html/_methods_inherited.html: 1
src/compiler/crystal/tools/doc/html/_other_types.html: 1
src/compiler/crystal/tools/doc/html/_sidebar.html: 1
src/compiler/crystal/tools/doc/html/js/doc.js: 1
src/compiler/crystal/tools/doc/html/main.html: 1
src/compiler/crystal/tools/doc/html/sitemap.xml: 1
src/compiler/crystal/tools/doc/html/type.html: 1
src/compiler/crystal/tools/init/template/example.cr.ecr: 1
src/compiler/crystal/tools/init/template/example_spec.cr.ecr: 1
src/compiler/crystal/tools/init/template/gitignore.ecr: 1
src/compiler/crystal/tools/init/template/license.ecr: 1
src/compiler/crystal/tools/init/template/readme.md.ecr: 1
src/compiler/crystal/tools/init/template/shard.yml.ecr: 1
src/compiler/crystal/tools/playground/views/_workbook.html.ecr: 1
src/compiler/crystal/tools/playground/views/layout.html.ecr: 1
src/crystal/compiler_rt/divmod128.cr: 1
src/crystal/compiler_rt/fixint.cr: 1
src/crystal/compiler_rt/float.cr: 1
src/crystal/compiler_rt/mul.cr: 1
src/crystal/once.cr: 1
src/crystal/system/process.cr: 1
src/http/server/handlers/static_file_handler.html: 1
src/log.cr: 1
src/log/setup.cr: 3
src/compiler/crystal/command.cr: 6
src/compiler/crystal/command/cursor.cr: 6
src/compiler/crystal/command/eval.cr: 6
src/compiler/crystal/command/repl.cr: 6
src/compiler/crystal/command/spec.cr: 6
src/compiler/crystal/command/docs.cr: 7
src/compiler/crystal/command/env.cr: 7
src/compiler/crystal/command/format.cr: 7
src/compiler/crystal/command/playground.cr: 7
src/compiler/crystal/tools/print_hierarchy.cr: 7
src/spec/cli.cr: 7
src/array.cr: 451
src/base64.cr: 451
...
444 lines more
...

Total files: 513
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, with a total of 513 files, making changes to most files ends up affecting 451 other files, which are almost all of them. So trying to reuse previous compilation data won't be a lot of benefit.&lt;/p&gt;

&lt;h1&gt;
  
  
  The end?
&lt;/h1&gt;

&lt;p&gt;Is this the end of the incremental compilation exploration? Is there nothing we can do about this? No! This is just the beginning. We have to look deeper into how things depend on each other. Maybe files aren't the incremental compilation unit we are looking for? Maybe we could introduce some small changes to the language to prevent transitive dependencies? Maybe the analysis can still be reused for methods that have a specified return type?&lt;/p&gt;

&lt;p&gt;Like before, I didn't explore any of these options yet. Maybe I will!&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>incremental</category>
      <category>compilers</category>
      <category>compilation</category>
    </item>
    <item>
      <title>Incremental compilation for Crystal - Part 1</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Tue, 03 Jan 2023 14:26:35 +0000</pubDate>
      <link>https://dev.to/asterite/incremental-compilation-for-crystal-part-1-414k</link>
      <guid>https://dev.to/asterite/incremental-compilation-for-crystal-part-1-414k</guid>
      <description>&lt;p&gt;I strongly believe that the &lt;a href="https://crystal-lang.org/" rel="noopener noreferrer"&gt;Crystal programming language&lt;/a&gt; has great potential. The only thing that, in my mind, is holding it back a bit is its slow compile times, which become more and more noticeable as your project grows.&lt;/p&gt;

&lt;p&gt;Why is the compiler slow? And can we improve the situation? This is what I'm going to talk about here, and think about solutions as we go.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why the compiler is slow?
&lt;/h1&gt;

&lt;p&gt;The main reason is that the compiler compiles the entire program, from scratch, every time you invoke it. Well, it at least does a full semantic analysis of your program: there is some caching going on regarding producing object files. But semantic analysis is always done, from scratch, for the entire program.&lt;/p&gt;

&lt;p&gt;And when I say "the entire program" it's the code that you wrote, but also the code from shards you use, and even the standard library. And, well, it's not the "entire program" because only those types and methods that are effectively used need to be analyzed and compiled, but it can still be quite a lot of code.&lt;/p&gt;

&lt;p&gt;The actual algorithms used in the compiler are good and fast. We could try to make them even faster. But, as you add more and more code to your program, inevitably, no matter how fast the algorithms, it will take more and more time to compile programs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why is semantic analysis done from scratch every time?
&lt;/h1&gt;

&lt;p&gt;Not doing semantic analysis from scratch means doing it by chunks, and reusing that previous knowledge.&lt;/p&gt;

&lt;p&gt;Most, if not all, compiled programming languages will analyze and compile individual files and then link them afterwards. Can we do the same in Crystal?&lt;/p&gt;

&lt;p&gt;Let's consider this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# dependency.cr&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&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;y&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;y&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, we have &lt;strong&gt;no idea&lt;/strong&gt; what are the types of &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;. If we call it with two ints then we can type and compile that method with that information. And the same is true if we pass it two strings. Or any object that has a &lt;code&gt;+&lt;/code&gt; method with an argument. So we can't type and compile that file just like that.&lt;/p&gt;

&lt;p&gt;That's one thing. Another thing is not knowing what types resolve to. For example in this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# dependency.cr&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;something&lt;/span&gt;
  &lt;span class="no"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;something&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;something&lt;/code&gt; doesn't take any arguments so we could try to type and compile it right away. But if we do so... what's &lt;code&gt;Foo&lt;/code&gt;? And what's the class method &lt;code&gt;bar&lt;/code&gt; in it? We can't know. Well, maybe a require is missing in that file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# dependency.cr&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"foo"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;something&lt;/span&gt;
  &lt;span class="no"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;something&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and now if &lt;code&gt;foo.cr&lt;/code&gt; defines &lt;code&gt;Foo&lt;/code&gt; all is good. But Crystal (and Ruby) allow not requiring a dependency like that, and instead it can come from somewhere else. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# caller.cr&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"dependency"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;caller.cr&lt;/code&gt; defines a class &lt;code&gt;Foo&lt;/code&gt; with a class method &lt;code&gt;bar&lt;/code&gt;, and requires &lt;code&gt;dependency&lt;/code&gt; which in turns defines &lt;code&gt;something&lt;/code&gt; that uses that &lt;code&gt;Foo&lt;/code&gt;. And this is perfectly fine, even though there's no &lt;strong&gt;explicit&lt;/strong&gt; mention of where does &lt;code&gt;Foo&lt;/code&gt; come from in &lt;code&gt;something&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The conclusion so far is that it's almost always impossible to look at a single file and type it without knowing the full program.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why Crystal allows writing programs like that?
&lt;/h1&gt;

&lt;p&gt;At this point one might wonder "is it a good idea that a file can work without it specifying where do types and methods come from?" But here I'm not going to try to answer that question, which is mainly subjective, and instead try to focus on how we could improve Crystal as it is right now. Of course Ruby could be "improved" (made faster) in many ways if we changed it (like, disallow some dynamisms, force some type declarations, etc.) but Ruby is being improved while not changing the way it is, while keeping its philosophy. Ruby has a vision, and it's being improved while keeping that vision. And I think that with Crystal we should strive to do the same.&lt;/p&gt;

&lt;h1&gt;
  
  
  Incremental compilation
&lt;/h1&gt;

&lt;p&gt;So let's discard for now the idea of being able to compile files individually. What else can we do?&lt;/p&gt;

&lt;p&gt;One idea is to compile the entire program first, and then try to reuse that knowledge for subsequent compilations. It would work like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We compile the entire program and build a dependencies graph: which files depend on which other files?&lt;/li&gt;
&lt;li&gt;We also remember the types used in methods? For example if &lt;code&gt;add(x, y)&lt;/code&gt; was called with two ints, we remember that it returns an int.&lt;/li&gt;
&lt;li&gt;Next time we compile a program, if we find a call to &lt;code&gt;add(x, y)&lt;/code&gt; with two ints, we check if the file where &lt;code&gt;add&lt;/code&gt; was defined, or any of its dependencies (recursively) changed, and if not, we could avoid typing that method again as we would know that it returns an int.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Would that really work?&lt;/p&gt;

&lt;h1&gt;
  
  
  Looking at file dependencies in real programs
&lt;/h1&gt;

&lt;p&gt;I created a &lt;a href="https://github.com/asterite/crystal-1/tree/dot-dependencies" rel="noopener noreferrer"&gt;branch&lt;/a&gt; that modifies the compiler to output a file dependencies graph for a given program. You can try it by checking out that branch, creating a compiler from it and then compiling any program. This will generate a &lt;code&gt;dependencies.dot&lt;/code&gt; file which you can then turn into a PDF by using this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dot &lt;span class="nt"&gt;-Tpdf&lt;/span&gt; dependencies.dot &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; dependencies.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(you'll need to install graphviz first)&lt;/p&gt;

&lt;p&gt;Running it against this program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# foo.cr&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will produce this graph:&lt;/p&gt;

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

&lt;p&gt;What a lovely tree-like graph! It's very easy to see how no cycles exist here.&lt;/p&gt;

&lt;p&gt;They say "beauty lies in the eyes of the beholder" but I hope we can all agree that the graph above is a mess.&lt;/p&gt;

&lt;p&gt;Still, within all that mess, we can find this:&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;kernel.cr&lt;/code&gt; defines &lt;code&gt;puts&lt;/code&gt;, so it's natural that &lt;code&gt;foo.cr&lt;/code&gt; dependes on it. But what's interesting is that nobody depends on &lt;code&gt;foo.cr&lt;/code&gt; (naturally.) And that also means that if next time we only change &lt;code&gt;foo.cr&lt;/code&gt; then we can reuse everything else from the previous compilation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Trouble ahead
&lt;/h1&gt;

&lt;p&gt;This looks promising. But running the tool with some bigger programs I found something. Let's take a look at this program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# foo.cr&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;io&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"foo"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The graph near &lt;code&gt;foo.cr&lt;/code&gt; now looks like this:&lt;/p&gt;

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

&lt;p&gt;Now &lt;code&gt;foo.cr&lt;/code&gt; has more dependencies, but something curious is that someone is now depending on &lt;code&gt;foo.cr&lt;/code&gt;. Who?&lt;/p&gt;

&lt;p&gt;We could play the "trace the line" game to find it, but looking at the dot file there's this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;  &lt;span class="s2"&gt;"src/io.cr"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"foo.cr"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above means "src/io.cr" depends on "foo.cr". WAT? How can the file that defines &lt;code&gt;IO&lt;/code&gt; depend on "foo.cr"? It should be the other way around!&lt;/p&gt;

&lt;p&gt;Debugging this a bit, we can see that the call the program makes is this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we have that the definition of &lt;code&gt;puts&lt;/code&gt; is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Nil&lt;/span&gt;
  &lt;span class="no"&gt;STDOUT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;puts&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So that's calling &lt;code&gt;puts&lt;/code&gt; on an &lt;code&gt;IO&lt;/code&gt; (&lt;code&gt;STDOUT&lt;/code&gt;). Let's take a look at that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Nil&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is calling &lt;code&gt;IO#&amp;lt;&amp;lt;(obj)&lt;/code&gt; where &lt;code&gt;obj&lt;/code&gt; is an instance of &lt;code&gt;Foo&lt;/code&gt;. Let's take a look at that &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So this is calling &lt;code&gt;obj.to_s(self)&lt;/code&gt;, where &lt;code&gt;obj&lt;/code&gt; is an instance of &lt;code&gt;Foo&lt;/code&gt;. And where is that method defined? In &lt;code&gt;foo.cr&lt;/code&gt;! Bingo!&lt;/p&gt;

&lt;p&gt;That's why suddenly &lt;code&gt;io.cr&lt;/code&gt; depends on &lt;code&gt;foo.cr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One way to understand this is to know that in Crystal all methods are monomorphized. Monomorwhat? It just means that if you call &lt;code&gt;IO#puts&lt;/code&gt; with a type &lt;code&gt;X&lt;/code&gt;, a method will be generated for that particular &lt;code&gt;X&lt;/code&gt;. If you call it with a &lt;code&gt;Y&lt;/code&gt;, a method will be generated for that particular &lt;code&gt;Y&lt;/code&gt; (for that particular &lt;strong&gt;type&lt;/strong&gt;.) In the example above, an &lt;code&gt;IO#&amp;lt;&amp;lt;(obj)&lt;/code&gt; method was generated where &lt;code&gt;obj&lt;/code&gt; is of type &lt;code&gt;Foo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is one reason that, I think, explains how messy the graph above is.&lt;/p&gt;

&lt;p&gt;In other compiled, statically typed programming languages, this doesn't happen. Usually &lt;code&gt;obj&lt;/code&gt; responds to some explicit interface and then the method lies behind a virtual table and a virtual dispatch. None of this happens in Crystal.&lt;/p&gt;

&lt;h1&gt;
  
  
  Does it matter?
&lt;/h1&gt;

&lt;p&gt;Does it matter that &lt;code&gt;io.cr&lt;/code&gt; depends on &lt;code&gt;foo.cr&lt;/code&gt;? Maybe it's not a big deal. Well, it probably is. It means that changes to a file are likely to affect seemingly unrelated files. And so if we try to use the "reuse previous compilation" strategy, not a lot could be reused in the end.&lt;/p&gt;

&lt;h1&gt;
  
  
  The end?
&lt;/h1&gt;

&lt;p&gt;This is not the end of the story. It's just the end of this blog post. I didn't continue thinking about how to approach this problem, but hopefully these posts spark some interest and some thoughts from others about how to solve this interesting problem.&lt;/p&gt;

</description>
      <category>crystal</category>
      <category>incremental</category>
      <category>compilers</category>
      <category>compilation</category>
    </item>
    <item>
      <title>Why I love Ruby: the secret algorithms</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Tue, 01 Mar 2022 13:15:53 +0000</pubDate>
      <link>https://dev.to/asterite/why-i-love-ruby-the-secret-algorithms-424d</link>
      <guid>https://dev.to/asterite/why-i-love-ruby-the-secret-algorithms-424d</guid>
      <description>&lt;p&gt;It's no secret that Crystal's standard library looks almost exactly the same as Ruby. Ruby's one has a very well designed API, with lots of useful things in it, so why not have a similar API in Crystal? Why rethink names and other things from scratch?&lt;/p&gt;

&lt;p&gt;So a few years ago we started adding these methods as we needed them for the compiler, or just for fun and completeness. While doing that, we would always compare Ruby's performance with Crystal. The idea was that, because Crystal is statically typed and compiled, relying on LLVM optimizations, it would always beat Ruby. It turns out, that wasn't always the case! We would think "How can Ruby be faster here? What's this magic?." Well, looking at Ruby's source code we found so many beautiful and performant algorithms. And they are all hidden. Most people don't know about them.&lt;/p&gt;

&lt;p&gt;So here I will talk about some of them.&lt;/p&gt;

&lt;h1&gt;
  
  
  Multiplying strings or arrays
&lt;/h1&gt;

&lt;p&gt;In Ruby you can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "hellohellohello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's the most obvious way to implement this? Like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The string consists of 5 bytes&lt;/li&gt;
&lt;li&gt;We are multiplying it by 3, so we'll need a string of 15 bytes&lt;/li&gt;
&lt;li&gt;Iterate 3 times by copying those 5 bytes over and over  (for efficiency, we can use something like &lt;a href="https://man7.org/linux/man-pages/man3/memcpy.3.html" rel="noopener noreferrer"&gt;memcpy&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that was the first implementation we did in Crystal. And Ruby was faster!&lt;/p&gt;

&lt;p&gt;So what does Ruby do? Let's say we need to multiply the string by 16. We can do this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The string consists of 5 bytes&lt;/li&gt;
&lt;li&gt;We are multiplying it by 16, so we need 80 bytes total&lt;/li&gt;
&lt;li&gt;First we copy 5 bytes from the original string. Great! 75 to go&lt;/li&gt;
&lt;li&gt;Next we copy 5 bytes more. Great! 70 to go.&lt;/li&gt;
&lt;li&gt;Now that we have 10 bytes ("hellohello"), we can copy those 10 bytes in the next position. Now we copied 20 bytes. 60 to go.&lt;/li&gt;
&lt;li&gt;Now that we have 20 bytes ("hellohellohellohello") let's copy those over. Now we copied 40 bytes! 40 to go.&lt;/li&gt;
&lt;li&gt;Next we copy the 40 bytes we have to the next position. Done! All 80 bytes copied.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This doesn't look like an optimization at all, right? After all we end up copying 80 bytes in any case. However, copying 40 bytes with a single &lt;code&gt;memcpy&lt;/code&gt; call is more efficient than doing 8 &lt;code&gt;memcpy&lt;/code&gt; calls copying 5 bytes. &lt;code&gt;memcpy&lt;/code&gt; is really well optimized! I don't know what tricks it does, but it can copy large memory portions very fast.&lt;/p&gt;

&lt;p&gt;Of course this works great when the amount with are multiplying by is a power of two. If that's not the case we can fill the remaining bytes by using the simpler algorithm.&lt;/p&gt;

&lt;p&gt;Because I haven't read many algorithm books, maybe this is a well known algorithm? I don't know. But here's something. &lt;a href="https://github.com/ruby/ruby/commit/35cb0f807b4689b0405dfbb2821e13f14c1fca45" rel="noopener noreferrer"&gt;Ruby introduced this optimization 14 years ago&lt;/a&gt;, while &lt;a href="https://github.com/golang/go/commit/7bcbb65d7879f17b185cee9ab4ab392da0bd865f" rel="noopener noreferrer"&gt;Go introduced it 8 years ago&lt;/a&gt;. In both cases the first algorithm to use was the simplest one, so at least it doesn't look like this optimization is immediately obvious.&lt;/p&gt;

&lt;h2&gt;
  
  
  There's more!
&lt;/h2&gt;

&lt;p&gt;Ruby also has another optimization, which I didn't see in Go. This isn't to prove Ruby is better than Go or anything like that, it's just to show how much care there is in every single Ruby method in the standard library, and to show that this isn't like that in every language out there.&lt;/p&gt;

&lt;p&gt;If we are doing something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ruby will notice that the string we are multiplying occupies only one byte. In that case, it does the following optimization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new string of size 100 bytes&lt;/li&gt;
&lt;li&gt;Call &lt;a href="https://man7.org/linux/man-pages/man3/memset.3.html" rel="noopener noreferrer"&gt;memset&lt;/a&gt; to fill those 100 bytes with the single byte from the original string.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Arrays
&lt;/h1&gt;

&lt;p&gt;Before meeting Ruby I was mainly coding in Java and C#. If you need some sort of collection in those languages you have many choices. Let's see Java:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html" rel="noopener noreferrer"&gt;ArrayList&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/Vector.html" rel="noopener noreferrer"&gt;Vector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html" rel="noopener noreferrer"&gt;LinkedList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is also similar in &lt;a href="https://doc.rust-lang.org/std/collections/index.html" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/std/collections/index.html#use-a-vec-when" rel="noopener noreferrer"&gt;Vec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/std/collections/index.html#use-a-vecdeque-when" rel="noopener noreferrer"&gt;VecDeque&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/std/collections/index.html#use-a-linkedlist-when" rel="noopener noreferrer"&gt;LinkedList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reason there are many collection types is that each one of them has better performance in some use cases, but worse performance in others. Depending on your use case you should choose one or another.&lt;/p&gt;

&lt;p&gt;So, before you just start collecting elements somewhere, you have to think about how that collection of elements is going to be used, by you and potentially others! Maybe you need to document "Do this, but please don't do that because it could be inefficient," and so on.&lt;/p&gt;

&lt;p&gt;Where are all these collection types in Ruby?&lt;/p&gt;

&lt;h2&gt;
  
  
  One type to rule them all
&lt;/h2&gt;

&lt;p&gt;In one of my many trips to Rubyland I found an old sheet that contained ancient writing. I didn't understand the meaning, so I copied the contents to a &lt;code&gt;foo.rb&lt;/code&gt; file and ran it with &lt;code&gt;ruby&lt;/code&gt;. This was the output:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Three Types for the Java-kings under the beans,&lt;br&gt;
Seven for the Rust-lords in their halls of stone,&lt;br&gt;
Nine for Mortal Men doomed to use C++,&lt;br&gt;
One for the Happy Lord on his shiny throne&lt;br&gt;
In the Land of Ruby where Happiness lies.&lt;br&gt;
One Type to rule them all, One Type to find them,&lt;br&gt;
One Type to bring them all, and in the bliss bind them,&lt;br&gt;
In the Land of Ruby where Hapiness lies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F209371%2F156172728-ba9c52f5-e500-4d99-b3f2-2c6d63f6ab89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F209371%2F156172728-ba9c52f5-e500-4d99-b3f2-2c6d63f6ab89.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Ruby, there's only one type for this: &lt;code&gt;Array&lt;/code&gt;. And it's implemented in a way that covers a lot of uses cases. When you need a collection of elements you don't need to think what to use: the answer is to use &lt;code&gt;Array&lt;/code&gt;. Simplifying users lives is what Ruby is all about.&lt;/p&gt;

&lt;p&gt;First, it's implemented like Java's &lt;code&gt;ArrayList&lt;/code&gt; and never like a &lt;code&gt;LinkedList&lt;/code&gt;. A linked list looks nice in paper, but having to allocate memory for every node when you want to insert an element is very expensive! Then traversing the list is also not great, when the memory for these nodes can be scattered, so cache locally can't be used.&lt;/p&gt;

&lt;p&gt;I don't want to get too technical, but &lt;code&gt;Array&lt;/code&gt; is implemented by allocating some memory, let's say with an initial &lt;strong&gt;capacity&lt;/strong&gt; of 10 elements, but it starts empty. Whenever you insert an element, as long as the current size didn't reach the current capacity, you do it. If not, you ask a bit more memory (let's say, 20 elements), copy what you had before into this new space, and then put the new element.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Array&lt;/code&gt; has methods like &lt;code&gt;push&lt;/code&gt; and &lt;code&gt;pop&lt;/code&gt; that let you use it like a stack, and that's easy to do with the structure described above. But then it has methods like &lt;code&gt;shift&lt;/code&gt; and &lt;code&gt;unshift&lt;/code&gt; that let you use it as a queue or dequeue too! Normally if you want to insert an element right at the beginning of an array you would have to move all the existing contents forward, then put an element. I'm not sure what Ruby does here, but that's definitely not what it does. It looks like Ruby knows where the array starts, so when you &lt;code&gt;shift&lt;/code&gt;, it just moves that pointer forward. It's really efficient!&lt;/p&gt;

&lt;h1&gt;
  
  
  A lot more
&lt;/h1&gt;

&lt;p&gt;There are a lot more operations you can do on an Array, so many that it's a lot to cover in a blogpost, and they are all handled with extreme care and thought, so you can use arrays however you need them and have a good guarantee that things will work well and fast.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coming up next...
&lt;/h1&gt;

&lt;p&gt;I don't know! I thought this post was going to be the final part, but it seems I still have many nice things to say about Ruby, so we'll see :-)&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>crystal</category>
    </item>
    <item>
      <title>Why I love Ruby: blocks</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Tue, 22 Feb 2022 08:55:53 +0000</pubDate>
      <link>https://dev.to/asterite/why-i-love-ruby-part-6-4hja</link>
      <guid>https://dev.to/asterite/why-i-love-ruby-part-6-4hja</guid>
      <description>&lt;p&gt;If you already know what are blocks in Ruby you can skip to the "Ruby blocks are not just anonymous functions" section. Otherwise, here's a small tutorial.&lt;/p&gt;

&lt;h1&gt;
  
  
  Small introduction to Ruby blocks
&lt;/h1&gt;

&lt;p&gt;Ruby methods can accept a block. Here's the simplest example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example &lt;code&gt;run&lt;/code&gt; yields. When we call &lt;code&gt;run&lt;/code&gt; we give it a block (&lt;code&gt;do&lt;/code&gt; ... &lt;code&gt;end&lt;/code&gt;) Then the block's contents are executed exactly where &lt;code&gt;yield&lt;/code&gt; was used.&lt;/p&gt;

&lt;p&gt;With this, we can define something a bit more useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;twice&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;twice&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because we do &lt;code&gt;yield&lt;/code&gt; twice, the block gets executed... twice!&lt;/p&gt;

&lt;p&gt;This general idea of executing something a number of times can also be achieved like this in Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And blocks can receive arguments, so you can also do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello number &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above outputs this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello number 0!
Hello number 1!
Hello number 2!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Ruby blocks are not just anonymous functions
&lt;/h1&gt;

&lt;p&gt;At first glance Ruby blocks are similar to a concept that exists in many languages: passing anonymous functions to functions that, in turn, receive functions and execute them.&lt;/p&gt;

&lt;p&gt;Let's try defining a &lt;code&gt;times&lt;/code&gt; function in Go:&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;times&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;block&lt;/span&gt; &lt;span class="k"&gt;func&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;block&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function takes an integer &lt;code&gt;n&lt;/code&gt; and will invoke the given function named &lt;code&gt;block&lt;/code&gt; that many times.&lt;/p&gt;

&lt;p&gt;Here's a full program that uses it:&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;times&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;block&lt;/span&gt; &lt;span class="k"&gt;func&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;block&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="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;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&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;i&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="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;"Hello number %v!&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;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is the same as the &lt;code&gt;3.times&lt;/code&gt; Ruby snippet mentioned before.&lt;/p&gt;

&lt;p&gt;Aside from having to write a bit more code, and having a bit more noise in it, it might seem that blocks aren't that special in Ruby after all... you can do the above thing in Go, Java, C#, Rust, and many more.&lt;/p&gt;

&lt;p&gt;To show that Ruby blocks are different, I came up with this program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet_20_numbers&lt;/span&gt;
  &lt;span class="n"&gt;seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sec&lt;/span&gt;

  &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello number &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Oh no, time's up!"&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Bye!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;greet_20_numbers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above program doesn't make a lot of sense, but here's how it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It prints 20 times "Hello number ...!" followed by priting "Bye!"&lt;/li&gt;
&lt;li&gt;However, if while printing the above it happens that the number to greet is the number of seconds on the clock, we print "Oh no, time's up!". Note that we don't print "Bye!" in this case because we return from the method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's try to translate the above program to Go:&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"time"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;times&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;block&lt;/span&gt; &lt;span class="k"&gt;func&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="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;block&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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;greet20numbers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;20&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;i&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="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;"Hello number %v!&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;i&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;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;second&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="s"&gt;"Oh, time's up!"&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="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;"Bye!"&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;greet20numbers&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;Running the above program doesn't work like the Ruby program. Can you spot why?&lt;/p&gt;

&lt;p&gt;In Go we also use &lt;code&gt;return&lt;/code&gt; to exit the function. But this &lt;code&gt;return&lt;/code&gt; returns from the function we gave to &lt;code&gt;times&lt;/code&gt;, it doesn't return from &lt;code&gt;greet20numbers&lt;/code&gt;! In Ruby, &lt;code&gt;return&lt;/code&gt; returns from the enclosing method, not the enclosing block.&lt;/p&gt;

&lt;p&gt;This is the most important difference between Ruby blocks and passing functions around.&lt;/p&gt;

&lt;p&gt;For example many languages (C, Java, C#, Go, Rust) have &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt; or &lt;code&gt;for&lt;/code&gt;. These constructs also have a "block" of sorts where we do things. In the case of &lt;code&gt;if&lt;/code&gt;, whatever we put inside that &lt;code&gt;if&lt;/code&gt; gets executed if the condition holds. For &lt;code&gt;while&lt;/code&gt; it's similar: the "block" gets executed while the condition holds. With &lt;code&gt;for&lt;/code&gt; you can use more complex conditions. And in all of them if you &lt;code&gt;return&lt;/code&gt; from inside these "blocks", you return from the enclosing function. But then you can't define other constructs that behave in the same way: you might be able to pass "blocks" around, but if you use &lt;code&gt;return&lt;/code&gt; then you return from those "blocks", not from the enclosing method.&lt;/p&gt;

&lt;p&gt;In Ruby, with blocks, you can create your own constructs that behave like &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt; or &lt;code&gt;for&lt;/code&gt; would. If you return from inside &lt;code&gt;3.times do ... end&lt;/code&gt;, you return from the method. If you do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"some_file.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;some_condition&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then that &lt;code&gt;return&lt;/code&gt; which is nested inside two blocks will return from the enclosing method! Then all of these blocks don't look like anonymous functions anymore, they look like augmented language syntax.&lt;/p&gt;

&lt;h1&gt;
  
  
  Give me a break
&lt;/h1&gt;

&lt;p&gt;There's one more thing you can do inside blocks that you can't do with regular anonymous functions from other languages: you can &lt;code&gt;break&lt;/code&gt; from them.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello number &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;

  &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will print "Hello number 0!", then "Hello number 1!" and stop.&lt;/p&gt;

&lt;p&gt;Just like you can &lt;code&gt;break&lt;/code&gt; from a &lt;code&gt;while&lt;/code&gt; in many languages, breaking from loops lets you create your own loops that enjoy all the benefits of regular &lt;code&gt;while&lt;/code&gt; loops: you can return from them and you can break from them! This further reinforces the notion that these methods look like new language constructs rather than anonymous functions.&lt;/p&gt;

&lt;p&gt;Finally, you can call &lt;code&gt;next&lt;/code&gt; inside a block to go to the next iteration, just like you can call &lt;code&gt;next&lt;/code&gt; or &lt;code&gt;continue&lt;/code&gt; inside a &lt;code&gt;while&lt;/code&gt; in other languages. However, you can do this with anonymous functions: just &lt;code&gt;return&lt;/code&gt; from them.&lt;/p&gt;

&lt;h1&gt;
  
  
  There's more to Ruby blocks
&lt;/h1&gt;

&lt;p&gt;Ruby blocks can also be captured and passed around. But I won't cover that here because that does look like anonymous functions or passing functions around. That said, you can also execute blocks in the context of another object, which again I won't cover here. But all of these things make Ruby blocks even more versatile, useful and fun to use!&lt;/p&gt;

&lt;h1&gt;
  
  
  Other languages that have blocks
&lt;/h1&gt;

&lt;p&gt;Of course Crystal has blocks and they can work like Ruby. Here's the sample program in Crystal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet_20_numbers&lt;/span&gt;
  &lt;span class="n"&gt;seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;second&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;

  &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello number &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Oh, it's time to get back to work!"&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Bye!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;greet_20_numbers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only difference is that we use &lt;code&gt;Time.local.second&lt;/code&gt; instead of &lt;code&gt;Time.now.sec&lt;/code&gt;, but otherwise it works exactly the same as Ruby.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kotlinlang.org/docs/inline-functions.html#non-local-returns"&gt;Kotlin&lt;/a&gt; is another language where you can also augment the syntax with methods that receive functions or "blocks" and where using &lt;code&gt;return&lt;/code&gt; actually returns from the enclosing function. This is great! I think Kotlin is a really good language that, and this is just a guess, took a lot of inspiration from Ruby. That said, &lt;a href="https://kotlinlang.org/docs/returns.html#return-to-labels"&gt;it seems you can't &lt;code&gt;break&lt;/code&gt; from these like you can in Ruby&lt;/a&gt; but there are small workarounds you can use for that. &lt;/p&gt;

&lt;h1&gt;
  
  
  Coming up next
&lt;/h1&gt;

&lt;p&gt;I'll be talking about Ruby's secret algorithms.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>crystal</category>
    </item>
    <item>
      <title>Why I love Ruby: a great standard library</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Mon, 21 Feb 2022 11:37:12 +0000</pubDate>
      <link>https://dev.to/asterite/why-i-love-ruby-part-5-3caa</link>
      <guid>https://dev.to/asterite/why-i-love-ruby-part-5-3caa</guid>
      <description>&lt;p&gt;In many programs it's very common to want to read a file and process the contents line by line. Here's what you needed to do in Java some time ago (around the time I found out Ruby) to do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;BufferedReader&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;try&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BufferedReader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileReader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/path/to/file.txt"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;line&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="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// read next line&lt;/span&gt;
    &lt;span class="n"&gt;line&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="na"&gt;readLine&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works, but there's a lot to read and write, and the intent of the code is not immediately clear.&lt;/p&gt;

&lt;p&gt;Here's how you do it in Go, based on &lt;a href="https://stackoverflow.com/a/16615559/4990850"&gt;this StackOverflow answer&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="n"&gt;file&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/path/to/file.txt"&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;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;defer&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&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;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// optionally, resize scanner's capacity for lines over 64K, see next example&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;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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&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;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Err&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="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, it works but it involves a few steps.&lt;/p&gt;

&lt;p&gt;Here's how you do it in Rust, based on &lt;a href="https://stackoverflow.com/a/45882510/4990850"&gt;this StackOverflow answer&lt;/a&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;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BufReader&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&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;line&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="nf"&gt;.lines&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;line&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's actually pretty concise, but it still involves a &lt;code&gt;BufReader&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's how you do it in Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/file.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So simple and concise! You want to read a file line by line, so you just tell Ruby to do that. No intermediate steps. No intermediate concepts like buffered readers.&lt;/p&gt;

&lt;p&gt;Now, I know what you are thinking: in Java, Go, Rust, and probably any language, you can define a helper function to do that. Then the code ends up being as concise as Ruby.&lt;/p&gt;

&lt;p&gt;But here's the thing: Ruby had this in the standard library right from the get-go. There's no need for all of us to write the same helper function in our projects.&lt;/p&gt;

&lt;p&gt;And this was just about reading files line by line. When you start to use Ruby, you realize how many useful things are there in the standard library.&lt;/p&gt;

&lt;h2&gt;
  
  
  A comment about Java
&lt;/h2&gt;

&lt;p&gt;Recent Java versions added helper functions to the standard library to read files line by line. Now &lt;a href="https://stackoverflow.com/a/17866514/4990850"&gt;it seems&lt;/a&gt; you can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Files&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Charset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;defaultCharset&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEachOrdered&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neat! I think this shows that eventually they realized that this was a common operation, and that it made sense to have this somewhere in the standard library. Ruby was a pioneer.&lt;/p&gt;

&lt;h1&gt;
  
  
  The hidden work Ruby does for us
&lt;/h1&gt;

&lt;p&gt;So to read files line by line in Java, Go and Rust we needed to open a file and then use something else on top of that: a buffered reader in Java and Rust, and a &lt;code&gt;bufio.Scanner&lt;/code&gt; in Go. What's going on?&lt;/p&gt;

&lt;p&gt;Well, the operating system interface for reading things from a file is &lt;a href="https://man7.org/linux/man-pages/man2/read.2.html"&gt;fill out this chunk of bytes with what you've got, and tell me how many bytes you put there&lt;/a&gt;. You can see this interface bubbling up into existing programming languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Java it's the &lt;a href="https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read(byte%5B%5D)"&gt;&lt;code&gt;read&lt;/code&gt; method of &lt;code&gt;InputStream&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;In Go it's the &lt;a href="https://pkg.go.dev/io#Reader"&gt;&lt;code&gt;Reader&lt;/code&gt; interface&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;In Crystal it's the &lt;a href="https://crystal-lang.org/api/1.3.2/IO.html#read%28slice%3ABytes%29-instance-method"&gt;&lt;code&gt;IO#read&lt;/code&gt; method&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then reading a file line by line has to be built on top of this interface.&lt;/p&gt;

&lt;p&gt;However, doing these primitive calls involve system calls, and doing many system calls is very expensive! So one way to deal with this is to introduce an intermediary, a buffer: the buffer will read as much as possible from the file, and then we can process the buffer's contents in-memory. In this way we produce the least amount of system calls.&lt;/p&gt;

&lt;p&gt;When you open a file in Go or Java, they are just handles to files. If you want to use them efficiently you need to put a buffer on top of them.&lt;/p&gt;

&lt;p&gt;What did Ruby do? Remove the need to know this, and all this complexity, from users. When you open a file in Ruby, it internally has a buffer. It's already doing what you are most likely to be doing in other languages in a more complex way! Thank you, Ruby!&lt;/p&gt;

&lt;p&gt;Why did Ruby do this? I don't know. One guess could be reducing complexity from users, which it tries to do all the time. Another guess could be: if to use files efficiently you'll have to use a buffer in 99% of the cases, why not make them buffered by default?&lt;/p&gt;

&lt;h1&gt;
  
  
  IO objects in Ruby are even more powerful!
&lt;/h1&gt;

&lt;p&gt;But wait, there's more!&lt;/p&gt;

&lt;p&gt;Let's say you need to read each line of a file... but this file is encoded in a non-UTF-8 encoding, for example EUC-JP.&lt;/p&gt;

&lt;p&gt;It's very likely that in most languages you will need to introduce a new intermediary object to do the encoding, so you'll need a few more lines of code for this. It's probably fine.&lt;/p&gt;

&lt;p&gt;In Ruby, you can directly set in which encoding you want to read or write things, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/file.txt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;encoding: &lt;/span&gt;&lt;span class="s2"&gt;"EUC-JP"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;h1&gt;
  
  
  The rest of the standard library...
&lt;/h1&gt;

&lt;p&gt;This post was just about one thing: reading files line by line. But Ruby's standard library has things like these in many places. In the end you can get a lot out of the standard library by writing very little code, and also by not needing to use external dependencies.&lt;/p&gt;

&lt;h1&gt;
  
  
  The community
&lt;/h1&gt;

&lt;p&gt;It's my impression that the Ruby community tried to do Ruby gems by mimicking the standard library way: simplify a user's life, provide helpful methods to do things by needing as few lines as possible.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coming up next...
&lt;/h1&gt;

&lt;p&gt;I'll be talking about a feature that's almost unique to Ruby: blocks!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>crystal</category>
    </item>
    <item>
      <title>Why I love Ruby: powerful calls</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Sun, 20 Feb 2022 17:59:35 +0000</pubDate>
      <link>https://dev.to/asterite/why-i-love-ruby-part-4-279p</link>
      <guid>https://dev.to/asterite/why-i-love-ruby-part-4-279p</guid>
      <description>&lt;h1&gt;
  
  
  Designing the perfect API
&lt;/h1&gt;

&lt;p&gt;In the last part I talked about how in Ruby method calls are used a lot and in many different ways. If users are going to write calls all the time, well, they better be nice to work with!&lt;/p&gt;

&lt;p&gt;It turns out, Ruby calls are extremely flexible and powerful. Let's take a look at a few examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# No arguments, splits by whitespace&lt;/span&gt;
&lt;span class="s2"&gt;"a  b  c"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; ["a", "b", "c"]&lt;/span&gt;

&lt;span class="c1"&gt;# With a string&lt;/span&gt;
&lt;span class="s2"&gt;"a,b,c"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; ["a", "b", "c"]&lt;/span&gt;

&lt;span class="c1"&gt;# With a string and a limit&lt;/span&gt;
&lt;span class="s2"&gt;"a,b,c"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; ["a", "b,c"]&lt;/span&gt;

&lt;span class="c1"&gt;# With a block&lt;/span&gt;
&lt;span class="s2"&gt;"a,b,c"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;piece&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;piece&lt;/span&gt; &lt;span class="c1"&gt;# prints "a", "b" and "c" in order&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# With a block and a limit&lt;/span&gt;
&lt;span class="s2"&gt;"a,b,c"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;piece&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;piece&lt;/span&gt; &lt;span class="c1"&gt;# prints "a", then "b,c"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# With a regular expression&lt;/span&gt;
&lt;span class="s2"&gt;"a,,,b,,c"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/,+/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; ["a", "b", "c"]&lt;/span&gt;

&lt;span class="c1"&gt;# With a regular expression and a limit&lt;/span&gt;
&lt;span class="s2"&gt;"a,,,b,,c"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/,+/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; ["a", "b,,c"]&lt;/span&gt;

&lt;span class="s2"&gt;"a&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="c1"&gt;# prints "a\n", then "b\n"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="s2"&gt;"a&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;chomp: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="c1"&gt;# prints "a", then "b"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"usr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"mail"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# =&amp;gt; "usr/mail"&lt;/span&gt;
&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"usr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"mail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"gumby"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "usr/mail/gumby"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are just three methods, namely &lt;code&gt;String#split&lt;/code&gt;,  &lt;code&gt;String#each_line&lt;/code&gt; and &lt;code&gt;File.join&lt;/code&gt;, but we can already see a lot of what methods support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They can behave differently depending on the number of arguments given. In this case, calling &lt;code&gt;split&lt;/code&gt; without any arguments splits by whitespace. Then one can pass an extra integer to specify the maximum number of pieces to return.&lt;/li&gt;
&lt;li&gt;They can behave differently depending on the type of argument. We can give &lt;code&gt;split&lt;/code&gt; a &lt;code&gt;String&lt;/code&gt;, but also a &lt;code&gt;Regexp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;They can also behave differently if a block is given. In the case of &lt;code&gt;split&lt;/code&gt;, if a block is given then each piece is yielded to the block.&lt;/li&gt;
&lt;li&gt;Some arguments can be specified with a name, like in the case of &lt;code&gt;chomp&lt;/code&gt;, which drops a trailing newline from a string, if there's any.&lt;/li&gt;
&lt;li&gt;Some methods can accept a variable number of arguments: &lt;code&gt;File.join&lt;/code&gt; will join all arguments given, no need to put them first in an array&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From a user's perspective, if they want to split a string, all they need to do is call &lt;code&gt;split&lt;/code&gt;. Maybe they want to use a string for that. Maybe a regular expression. Maybe with an optional limit. Or maybe they don't need to capture things in an array and it's fine if each piece is yielded to a block. It's fine! In all these cases the operation is a &lt;code&gt;split&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I really like this, because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The operation is really a &lt;code&gt;split&lt;/code&gt;. Why have possibly multiple names for the same operation?&lt;/li&gt;
&lt;li&gt;Given how flexible this is, it means that if you'd like to design an API, you can choose exactly how users are going to call it. If you prefer arguments to be named, you can do it. If you want optional arguments, you can do that too. You can design the API you had in mind! The language rarely constrains you here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What about other languages?
&lt;/h1&gt;

&lt;p&gt;So now I'm going to compare this with other languages. If I like this in Ruby it must mean that not every language works like that. I'm just noting that in this series of blog posts I compare Ruby with others just to say "I really like how Ruby handled this" and not "I really dislike how this other language did it."&lt;/p&gt;

&lt;p&gt;Java has method overloads so you can define methods that operate on different number of arguments and different types. Then Java doesn't have default arguments, but you can kind of work around it by defining two overloads and having one method call the other one with a default value. Then Kotlin, which compiles to Java bytecode (among other things) supports default arguments and named arguments. Nice!&lt;/p&gt;

&lt;p&gt;C# started being very similar to Java but slowly evolved in a great direction: they now support default argument values and even named arguments. Pretty cool!&lt;/p&gt;

&lt;p&gt;Go has no overloads, no default argument values and no named arguments. If we want to split a string we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Split&lt;/code&gt;: splits by a string&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SplitN&lt;/code&gt;: splits by a string returning at most N results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then if they wanted these to work with a regex they would need to add &lt;code&gt;SplitRegex&lt;/code&gt; and &lt;code&gt;SplitRegexN&lt;/code&gt;. If they want to add more options to split they will have to combine all these names and options into the function name. I know, I know, it's not a big deal. But I like it better in Ruby. In Ruby if I need to add a limit, I just add it. In Go I need to add it too, but then I need to go back and change the function name to add &lt;code&gt;N&lt;/code&gt;. And of course I might forget what all these functions are named... in Ruby it's always &lt;code&gt;split&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Rust is also a recent, modern language that has no default arguments and no named arguments.&lt;/p&gt;

&lt;p&gt;Then we have Haskell and Elm, which are a completely different story. In Haskell and Elm you can call a function with less arguments than those required, and that's fine. &lt;strong&gt;Yes, you read that right&lt;/strong&gt;. What happens is that the result is another function that expects the missing arguments. I think this is called partial application. Partial application is very powerful and useful! But because it's how the language works by default, this happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you forget to pass an argument you don't get an error message at the call site. You will get it later when you try to use that result value, where you wanted something but you got a function. This makes understanding what went wrong really hard. &lt;/li&gt;
&lt;li&gt;You can't have default arguments: if you don't pass an argument, should the default value be used, or is it partial application?&lt;/li&gt;
&lt;li&gt;You can't have overloads based on the number of arguments for a similar reason than the last point&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice having less flexibility in these cases also means having to think about how to name your functions. I know of Haskell functions where &lt;code&gt;'&lt;/code&gt; or &lt;code&gt;''&lt;/code&gt; appended to the name to support different number of arguments or different types. This in my opinion leads to code that's harder to understand or easily memorize.&lt;/p&gt;

&lt;p&gt;In languages without default arguments people would come up with ways to simulate them, which means there's some boilerplate and also a chance that everyone has their own way of doing it, leading to less code uniformity.&lt;/p&gt;

&lt;h1&gt;
  
  
  One more thing about Ruby methods...
&lt;/h1&gt;

&lt;p&gt;There's more! In Ruby method names don't have restrictions. For example, you can't have a function called &lt;code&gt;void&lt;/code&gt; in Java, it's a keyword. You can't have a function called &lt;code&gt;type&lt;/code&gt; in Go: it's a keyword! I recently found out that in Elm you can't have a record field be named &lt;code&gt;type&lt;/code&gt;, even though, unless I'm mistaken, there would be a way to allow that without a problem.&lt;/p&gt;

&lt;p&gt;So this is Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;def&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Foo&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="nf"&gt;def&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use names like &lt;code&gt;begin&lt;/code&gt;, &lt;code&gt;end&lt;/code&gt;, &lt;code&gt;class&lt;/code&gt;... it's all good! Calling these requires a dot, so there's no ambiguity. Actually... you can also call methods that don't have a receiver (something before the dot,) but then you can do &lt;code&gt;self.def&lt;/code&gt; in those cases and it will work.&lt;/p&gt;

&lt;h1&gt;
  
  
  Crystal
&lt;/h1&gt;

&lt;p&gt;Because we really like how flexibly Ruby is, we wanted the same thing in Crystal. And so, Crystal supports default arguments, named arguments, variable number of arguments, overloading based on different types, and overloading based on whether a method receives a block or not. You can even define methods that require arguments to be passed by name, and overload based on different names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Arguments that come after a `*` must be passed by name&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s2"&gt;"I got an x: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s2"&gt;"I got a y: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="ss"&gt;x: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "I got an x: 1"&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="ss"&gt;y: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; "I got a y: 2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In fact, the very first code snippet in this post compiles and runs fine in Crystal, and it behaves almost exactly like in Ruby (in Crystal the &lt;code&gt;chomp&lt;/code&gt; argument is &lt;code&gt;true&lt;/code&gt; by default, while in Ruby it's &lt;code&gt;false&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;In practice, you get all the flexibility that Ruby has, which lets you define delightful APIs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coming up next
&lt;/h1&gt;

&lt;p&gt;It's time we talk about how great Ruby's standard library is!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>crystal</category>
    </item>
    <item>
      <title>Why I love Ruby: almost everything is a call</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Sat, 19 Feb 2022 09:57:46 +0000</pubDate>
      <link>https://dev.to/asterite/why-i-love-ruby-part-3-2oin</link>
      <guid>https://dev.to/asterite/why-i-love-ruby-part-3-2oin</guid>
      <description>&lt;p&gt;Right on the &lt;a href="https://www.ruby-lang.org/en/about/" rel="noopener noreferrer"&gt;main page of the Ruby language&lt;/a&gt; there's this beautiful quote from Matz:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ruby is simple in appearance, but is very complex inside, just like our human body.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's Ruby's simplicity that I really like.&lt;/p&gt;

&lt;p&gt;If you ask me "What do you see when you see Ruby code?" my answer is &lt;strong&gt;method calls&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F209371%2F154746251-d1beb1a6-29a0-43cd-9b8f-9bb72cd380f8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F209371%2F154746251-d1beb1a6-29a0-43cd-9b8f-9bb72cd380f8.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take a look at this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"set"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MySet&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Enumerable&lt;/span&gt;

  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:inner_set&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are some things here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we &lt;code&gt;require&lt;/code&gt; some external code&lt;/li&gt;
&lt;li&gt;we declare a class with the &lt;code&gt;class&lt;/code&gt; keyword&lt;/li&gt;
&lt;li&gt;we include functionality from another module with &lt;code&gt;include&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;we declare a read-only property with &lt;code&gt;attr_reader&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It turns out, only &lt;code&gt;class&lt;/code&gt; is special here: it's a language construct that lets you define classes. But &lt;a href="https://ruby-doc.org/core-3.1.0/Kernel.html#method-i-require" rel="noopener noreferrer"&gt;require&lt;/a&gt; is a method call defined by Ruby, and the same is true about &lt;a href="https://ruby-doc.org/core-3.1.0/Module.html#method-i-include" rel="noopener noreferrer"&gt;include&lt;/a&gt; and &lt;a href="https://ruby-doc.org/core-3.1.0/Module.html#method-i-attr_reader" rel="noopener noreferrer"&gt;attr_reader&lt;/a&gt;. They &lt;strong&gt;look&lt;/strong&gt; like keywords, like something special, but they are just regular methods.&lt;/p&gt;

&lt;p&gt;This ability of having almost everything look the same, in a consistent way, is what lets you, the Ruby user, also define things that look like language keywords, but are just ordinary methods.&lt;/p&gt;

&lt;p&gt;In fact, it's very easy to define &lt;code&gt;attr_reader&lt;/code&gt; ourselves. Because &lt;code&gt;attr_reader&lt;/code&gt; already exists, lets use the name &lt;code&gt;getter&lt;/code&gt; for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Module&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"@&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;
    &lt;span class="n"&gt;define_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="nb"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;
  &lt;span class="n"&gt;getter&lt;/span&gt; &lt;span class="ss"&gt;:x&lt;/span&gt;
  &lt;span class="n"&gt;getter&lt;/span&gt; &lt;span class="ss"&gt;:y&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&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="vi"&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="vi"&gt;@y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&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="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;x&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 1&lt;/span&gt;
&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;y&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there we have it!&lt;/p&gt;

&lt;p&gt;Well, using &lt;code&gt;getter&lt;/code&gt; is simple. Maybe defining it is a bit more complex... but it's definitely possible!&lt;/p&gt;

&lt;p&gt;Maybe the additional feature of not having to put parentheses around method calls makes this look more like a keyword than a method. Imagine if parentheses were required for method calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"set"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MySet&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Enumerable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nb"&gt;attr_reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:inner_set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They don't look like keywords anymore, right? My guess is that allowing to omit parentheses was done for exactly this reason, but of course you can omit parentheses anywhere because Ruby doesn't know if you are going to use something "like a keyword" or not.&lt;/p&gt;

&lt;p&gt;This of course is used in Ruby &lt;strong&gt;a lot&lt;/strong&gt;. Here's an example of Rails' ActiveRecord:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:posts&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be honest, a snippet like that might have been one of the first code snippets I stumbled upon when I was learning Ruby together with Ruby on Rails. With this, you can kind of create your own mini-language for users. And all these languages will be relatively easy to use: they will all be based around method calls. Of course the names will vary, or the number of arguments. But in the end they are all method calls.&lt;/p&gt;

&lt;p&gt;One other language that did this, and it actually did it better, or more consistently, is Elixir. In Elixir you define a module like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;SomeModule&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You define a function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You use an if like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that there's always a &lt;code&gt;do&lt;/code&gt; in the end. These are all functions defined by Elixir! (well, technically they are macros) For example, here are the docs of &lt;a href="https://hexdocs.pm/elixir/1.13/Kernel.html#defmodule/2" rel="noopener noreferrer"&gt;defmodule&lt;/a&gt;, from which you can jump to the source code. This is brilliant!&lt;/p&gt;

&lt;p&gt;Like in Ruby, this also means that in Elixir you will be using the same small language (calls) for almost everything.&lt;/p&gt;

&lt;p&gt;In other languages you might be able to do the same thing, but there might be other syntax involved. For example in Rust you call macros with a bang at the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, {}!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Julia you use &lt;code&gt;@&lt;/code&gt; to call macros:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="k"&gt;macro&lt;/span&gt;&lt;span class="nf"&gt; sayhello&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt; &lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nd"&gt;@sayhello&lt;/span&gt;&lt;span class="x"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In D you can use the &lt;a href="https://dlang.org/articles/mixin.html" rel="noopener noreferrer"&gt;mixin&lt;/a&gt; keyword to generate code at compile-time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight d"&gt;&lt;code&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="n"&gt;GenStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;string&lt;/span&gt; &lt;span class="n"&gt;M1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;GenStruct&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"struct "&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="s"&gt;"{ int "&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="n"&gt;M1&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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;mixin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GenStruct&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="s"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might seem like a little thing, but from a user perspective you have to know what you are using. "Oh, I'm using a macro so I have to do it this way." In Ruby and Elixir it's just "I call it."&lt;/p&gt;

&lt;p&gt;Carole King &lt;a href="https://youtu.be/eAR_Ff5A8Rk?t=80" rel="noopener noreferrer"&gt;couldn't have said it better&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Winter, spring, summer or fall&lt;br&gt;
All you have to do is call&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because with Ruby... you've got a friend 😌&lt;/p&gt;

&lt;p&gt;For Crystal we considered having a different syntax for invoking macros, but in the end we used the same syntax as for method calls. And we really like the end result! Take a look at this Crystal code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="kp"&gt;record&lt;/span&gt; &lt;span class="no"&gt;Point&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="no"&gt;Int32&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="no"&gt;Int32&lt;/span&gt;

&lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like &lt;code&gt;record&lt;/code&gt; is a keyword that defines a type with two properties. But it's actually a macro, &lt;a href="https://crystal-lang.org/api/1.3.2/toplevel.html#record%28name%2C%2Aproperties%29-macro" rel="noopener noreferrer"&gt;here&lt;/a&gt;'s the documentation.&lt;/p&gt;

&lt;p&gt;As a comparison, Java 14 added records to the language (where did they get that name from?! 😮) by introducing a new keyword:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Rectangle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Java had a way to reduce such boilerplate right in the language itself, it wouldn't need to introduce keywords: they could just do it with the language itself. As a bonus things would get automatically documented in the API docs.&lt;/p&gt;

&lt;p&gt;One other benefit of having such constructs be methods or macros in a language is that, at least in Ruby and Crystal, a user can redefine them. For example &lt;a href="https://github.com/fxn/zeitwerk/blob/960dbdc25024a801de0c38a2928c12a450c967da/lib/zeitwerk/kernel.rb#L24" rel="noopener noreferrer"&gt;zeitwerk redefines require&lt;/a&gt; and makes it work in a different, better way. In what other language can you do this?&lt;/p&gt;

&lt;h1&gt;
  
  
  Coming up next...
&lt;/h1&gt;

&lt;p&gt;In the next blog post I'll be talking about being able to design that perfect API.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>crystal</category>
    </item>
    <item>
      <title>Why I love Ruby: string representation</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Fri, 18 Feb 2022 12:39:31 +0000</pubDate>
      <link>https://dev.to/asterite/why-i-love-ruby-part-2-102j</link>
      <guid>https://dev.to/asterite/why-i-love-ruby-part-2-102j</guid>
      <description>&lt;h1&gt;
  
  
  String representation
&lt;/h1&gt;

&lt;p&gt;In Ruby every object responds to &lt;code&gt;to_s&lt;/code&gt; with a good default. There's also &lt;code&gt;inspect&lt;/code&gt; which usually reveals the internal structure of an object.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&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="vi"&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="vi"&gt;@y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Point:0x00007fab148d55d8&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Point:0x00007fab148d55d8 @x=1, @y=2&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, maybe &lt;code&gt;to_s&lt;/code&gt; isn't that useful and &lt;code&gt;inspect&lt;/code&gt; is much more useful, but it's nice that they are there.&lt;/p&gt;

&lt;p&gt;The nice thing about &lt;code&gt;inspect&lt;/code&gt; is that they also takes potential cycles into account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
    &lt;span class="vi"&gt;@sibilings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_sibiling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@sibilings&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Ary"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;gabriel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Gabriel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_sibiling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gabriel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;gabriel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_sibiling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Person:0x00007fe670851160 @name="Ary", @sibilings=[#&amp;lt;Person:0x00007fe6708510c0 @name="Gabriel", @sibilings=[#&amp;lt;Person:0x00007fe670851160 ...&amp;gt;]&amp;gt;]&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;gabriel&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Person:0x00007fe6708510c0 @name="Gabriel", @sibilings=[#&amp;lt;Person:0x00007fe670851160 @name="Ary", @sibilings=[#&amp;lt;Person:0x00007fe6708510c0 ...&amp;gt;]&amp;gt;]&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not only it doesn't crash: it also shows the object ID of objects so you can know that when there's a cycle, what that object is.&lt;/p&gt;

&lt;p&gt;Similar code works fine in Crystal too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@sibilings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="no"&gt;Person&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_sibiling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@sibilings&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Ary"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;gabriel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Gabriel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_sibiling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gabriel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;gabriel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_sibiling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Person:0x107d3aea0 @name="Ary", @sibilings=[#&amp;lt;Person:0x107d3ae60 @name="Gabriel", @sibilings=[#&amp;lt;Person:0x107d3aea0 ...&amp;gt;]&amp;gt;]&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;gabriel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Person:0x107d3ae60 @name="Gabriel", @sibilings=[#&amp;lt;Person:0x107d3aea0 @name="Ary", @sibilings=[#&amp;lt;Person:0x107d3ae60 ...&amp;gt;]&amp;gt;]&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above output is a bit hard to read... so Ruby and Crystal allow you to pretty print objects, every type of object, right out of the box. Here's Ruby with the above value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"pp"&lt;/span&gt;
&lt;span class="n"&gt;pp&lt;/span&gt; &lt;span class="n"&gt;ary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#&amp;lt;Person:0x00007ffad4076fd0
 @name="Ary",
 @sibilings=
  [#&amp;lt;Person:0x00007ffad404b8a8
    @name="Gabriel",
    @sibilings=[#&amp;lt;Person:0x00007ffad4076fd0 ...&amp;gt;]&amp;gt;]&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's Crystal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="n"&gt;pp&lt;/span&gt; &lt;span class="n"&gt;ary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#&amp;lt;Person:0x101418ea0
 @name="Ary",
 @sibilings=
  [#&amp;lt;Person:0x101418e60
    @name="Gabriel",
    @sibilings=[#&amp;lt;Person:0x101418ea0 ...&amp;gt;]&amp;gt;]&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In other languages this ability to easily inspect objects out of the box is not present, or is not great. At least in some languages all objects can be converted to a string, even if the output isn't very useful. But some languages doesn't do that... and I'll mention Haskell now, maybe because I'm using it at work, but I think this is also true in Rust.&lt;/p&gt;

&lt;p&gt;In Haskell you can't turn any value into a string &lt;strong&gt;by default&lt;/strong&gt;. The type has to implement the &lt;code&gt;Show&lt;/code&gt; typeclass. In practice this means that if we have the &lt;code&gt;Point&lt;/code&gt; type I mentioned above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ ghci
GHCi, version 8.10.7: https://www.haskell.org/ghc/  :? for help
Prelude&amp;gt; data Point = Point { x :: Int, y :: Int }
Prelude&amp;gt; p1 = Point { x = 1, y = 2 }
Prelude&amp;gt; p1

&amp;lt;interactive&amp;gt;:8:1: error:
    • No instance for (Show Point) arising from a use of ‘print’
    • In a stmt of an interactive GHCi command: print it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can't see what's &lt;code&gt;p1&lt;/code&gt;. You again have to put &lt;code&gt;deriving (Show)&lt;/code&gt; at the end of the declaration, or define a custom &lt;code&gt;show&lt;/code&gt; function for the &lt;code&gt;Show&lt;/code&gt; typeclass.&lt;/p&gt;

&lt;p&gt;This might not sound like a lot to do, but when you are debugging code and you can't inspect objects and then you have to stop what you are doing and what you were thinking about, to go and open a file and add &lt;code&gt;deriving (Show)&lt;/code&gt; in a lot of places just to see what's going on, it's not fun. It's less fun when those types aren't in your control and it's harder to add a &lt;code&gt;Show&lt;/code&gt; for them. At the end of this process you end up thinking "should I leave these &lt;code&gt;deriving (Show)&lt;/code&gt; or should I remove them now that I'm done with them", and it's where my question "why aren't these derived by default" comes to mind.&lt;/p&gt;

&lt;p&gt;This is also when Ruby's goal, "developer happiness", comes to my mind. Doing all of the above isn't fun. In Ruby we don't have to do that, Ruby took care of that and we can just have fun solving more interesting problems.&lt;/p&gt;

&lt;p&gt;That said, once you add &lt;code&gt;deriving (Show)&lt;/code&gt;, Haskell works fine, and in general &lt;code&gt;show&lt;/code&gt; is very well implemented for "standard library" types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ ghci
GHCi, version 8.10.7: https://www.haskell.org/ghc/  :? for help
Prelude&amp;gt; data Point = Point { x :: Int, y :: Int } deriving (Show)
Prelude&amp;gt; p1 = Point { x = 1, y = 2 }
Prelude&amp;gt; p1
Point {x = 1, y = 2}
Prelude&amp;gt; [p1]
[Point {x = 1, y = 2}]
Prelude&amp;gt; ["hello", "world"]
["hello","world"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Another language as an example: Go
&lt;/h2&gt;

&lt;p&gt;Let's take a look at another language. I randomly chose Go because it's a relatively modern language, very popular, and there's a playground to try things out.&lt;/p&gt;

&lt;p&gt;Here's an example from &lt;a href="https://go.dev/tour/moretypes/6"&gt;Go's tour about arrays&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&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="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&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;"Hello"&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"World"&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;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&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="m"&gt;1&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;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;primes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;6&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="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;13&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;primes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello World
[Hello World]
[2 3 5 7 11 13]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's compare it to the output of Ruby or Crystal. I'm using &lt;code&gt;p&lt;/code&gt; here which invokes &lt;code&gt;inspect&lt;/code&gt; on objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"World"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;

&lt;span class="n"&gt;primes&lt;/span&gt; &lt;span class="o"&gt;=&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;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;primes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Hello"
"World"
["Hello", "World"]
[2, 3, 5, 7, 11, 13]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing to note is that Ruby and Crystal put quotes around strings (well, this isn't the case if you call &lt;code&gt;to_s&lt;/code&gt; on a string, only &lt;code&gt;inspect&lt;/code&gt;.) Then note that array contents use &lt;code&gt;inspect&lt;/code&gt;. This makes it possible to know that the first array has two strings. In Go it's not clear: are there two elements, "Hello" and "World", or is it just one string "Hello World"?&lt;/p&gt;

&lt;p&gt;Another nice thing is that you can copy that array output from Ruby and Crystal, paste it into a program and it will work. This isn't generally true, but it works really well for primitive types, arrays and hashes, which are used a lot! In Go this isn't true. There aren't even commas! I don't know why.&lt;/p&gt;

&lt;p&gt;Now, I'm sure there's a way to show arrays or strings in Go in a better way. For example in Java you can use &lt;code&gt;Arrays.toString&lt;/code&gt;. But not having that as a default adds friction. It's not the most intuitive thing you would expect to happen.&lt;/p&gt;

&lt;p&gt;Another thing is consistency and uniformity. In Go there's the &lt;a href="https://pkg.go.dev/fmt@go1.17.7#Stringer"&gt;Stringer&lt;/a&gt; interface that defines the &lt;code&gt;String()&lt;/code&gt; function to turn objects to a string. So what happens if we call &lt;code&gt;String()&lt;/code&gt; on an array?&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&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;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"World"&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;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&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;We get a compile error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./prog.go:7:15: a.String undefined (type [2]string has no field or method String)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So it seems only &lt;code&gt;fmt&lt;/code&gt; knows how to turn arrays into strings, and we have to rely on this package for that, but for other types we probably should use &lt;code&gt;String()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's those things that rarely exist in Ruby that I really appreciate. When something works in one way in Ruby you understand it and think "well, I guess this also works for these other types, or in these contexts" and that's almost always true. When that's not the case in a language, it's the moment you start building a collection of exceptions in your head, and when you start looking for answers in StackOverflow.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coming up next...
&lt;/h1&gt;

&lt;p&gt;I'll talk about &lt;a href="https://dev.to/asterite/why-i-love-ruby-part-3-2oin"&gt;making a language your own&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>crystal</category>
    </item>
    <item>
      <title>Why I love Ruby: equality</title>
      <dc:creator>Ary Borenszweig</dc:creator>
      <pubDate>Thu, 17 Feb 2022 13:42:18 +0000</pubDate>
      <link>https://dev.to/asterite/why-i-love-ruby-part-1-20h2</link>
      <guid>https://dev.to/asterite/why-i-love-ruby-part-1-20h2</guid>
      <description>&lt;p&gt;In this series of posts I will list the things that I always loved about Ruby. Some of these work differently in other languages or they don't exist at all. I will try to give some comparisons when possible. But in general my feeling is that Ruby always does the most intuitive thing a programmer would expect, and I love that! And it's what I tried to preserve in Crystal.&lt;/p&gt;

&lt;h1&gt;
  
  
  Comparing objects
&lt;/h1&gt;

&lt;p&gt;In Ruby you can compare any two objects and Ruby will do the most intuitive thing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;           &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;         &lt;span class="c1"&gt;# =&amp;gt; true (in math too!)&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="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="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last one about comparing arrays is important: not every language does this. For instance, if you compare two arrays in Java or C#, you only get &lt;code&gt;true&lt;/code&gt; if they are the &lt;strong&gt;same&lt;/strong&gt; array, that is, the same reference to memory. Then if you search "how to compare two arrays in Java/C#" you will get lots of answers in StackOverflow trying to answer this. In Java you can use &lt;code&gt;Arrays.equals&lt;/code&gt;, but that doesn't do a deep comparison, so you also have &lt;code&gt;Arrays.deepEquals&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The tricky part about array comparison is that you might end up having an array with an object that in turn has a reference to the same array, leading to a cycle. When trying to compare them, if you don't take cycles into account, the program will stack overflow, or crash. You don't want that in your program!&lt;/p&gt;

&lt;p&gt;Well, in Ruby &lt;strong&gt;it just works&lt;/strong&gt;. It will compare two arrays by calling &lt;code&gt;==&lt;/code&gt; on each element, and it will also take care of cycles. The following works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;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;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; =&amp;gt; [[...]]&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of the above work just fine in Crystal, except that for the recursive array definition. I &lt;em&gt;thought&lt;/em&gt; it worked fine in Crystal but it seems it also leads to a stack overflow. But &lt;a href="https://github.com/crystal-lang/crystal/issues/11837"&gt;it's something we'll eventually fix&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Ruby you can also compare &lt;code&gt;Hash&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;, and many other types, where the definition of equality is the obvious one, and the same is true in Crystal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Equality everywhere
&lt;/h2&gt;

&lt;p&gt;Another nice thing about equality in Ruby is that you get sensible defaults, and you can compare any two objects out of the box. For example, Ruby has a &lt;a href="https://ruby-doc.org/core-3.0.1/Struct.html"&gt;Struct&lt;/a&gt; type that's used to pack some values together, kind of like a quick definition of an object with some properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;p2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;p1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Crystal you can also define structs, and the default comparison just delegates to comparing the fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight crystal"&gt;&lt;code&gt;&lt;span class="kp"&gt;struct&lt;/span&gt; &lt;span class="no"&gt;Point&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@x&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@y&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;p2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;p1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This all sounds very intuitive. Why would a language &lt;strong&gt;not&lt;/strong&gt; do that? Well, I don't know. Take for example Haskell, where these types of structs are really common:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ ghci
GHCi, version 8.10.7: https://www.haskell.org/ghc/  :? for help
Prelude&amp;gt; data Point = Point { x :: Int, y :: Int }
Prelude&amp;gt; p1 = Point { x = 1, y = 2 }
Prelude&amp;gt; p2 = Point { x = 1, y = 2 }
Prelude&amp;gt; p1 == p2

&amp;lt;interactive&amp;gt;:4:1: error:
    • No instance for (Eq Point) arising from a use of ‘==’
    • In the expression: p1 == p2
      In an equation for ‘it’: it = p1 == p2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Haskell gives a compile-time error because &lt;code&gt;==&lt;/code&gt; is not defined for Point. We need to define one. And we can use a magic &lt;code&gt;deriving&lt;/code&gt; to let the compiler do the obvious thing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ ghci
GHCi, version 8.10.7: https://www.haskell.org/ghc/  :? for help
Prelude&amp;gt; data Point = Point { x :: Int, y :: Int } deriving (Eq)
Prelude&amp;gt; p1 = Point { x = 1, y = 2 }
Prelude&amp;gt; p2 = Point { x = 1, y = 2 }
Prelude&amp;gt; p1 == p2
True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this last point is controversial (maybe this entire blog post is controversial!) Someone might say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But what if you didn't want this comparison by default? It's dangerous! Then you would have a bug in your code. It's better to always think about these cases and make sure the equality you want is really that one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's fine. My answer to that is that you want to have tests to verify that you code works in the way you want it. Compile-time safety is good, but it doesn't prove behavior.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coming up next...
&lt;/h1&gt;

&lt;p&gt;In the next part I'll talk about &lt;a href="https://dev.to/asterite/why-i-love-ruby-part-2-102j"&gt;Ruby's &lt;code&gt;to_s&lt;/code&gt; method&lt;/a&gt;.&lt;/p&gt;

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