<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>soc.me</title>
    <description></description>
    <link>/</link>
    <atom:link href="/feed/" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 02 Jun 2026 13:56:40 +0000</pubDate>
    <lastBuildDate>Tue, 02 Jun 2026 13:56:40 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Language Design: Implicit Numeric Conversions</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; The desire to make unrelated types act as if they were in a
sub-typing relationship, which neither exists nor should exist, combined with
syntax sugar that makes static dispatch look like dynamic dispatch creates a
perfect storm of unintended, harmful consequences.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
Implicit numeric conversions&lt;sup id=&quot;fnref:term&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:term&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; are a special compiler feature in Scala that adds
“convenience” conversions between number types, for instance:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// num = 123.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;
It is a feature that&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;is described as a mistake by the designers of Java&lt;sup id=&quot;fnref:mistake0&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:mistake0&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:mistake1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:mistake1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;silently destroys data, loses numeric precision and changes semantics of overflow and
division-by-zero&lt;/li&gt;
  &lt;li&gt;is inconsistently applied, and will become more inconsistent as new
numeric types are introduced in future versions of Java&lt;/li&gt;
  &lt;li&gt;breaks all methods defined on numbers&lt;/li&gt;
  &lt;li&gt;cannot be defended against&lt;/li&gt;
  &lt;li&gt;cannot be deactivated&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;the-good-intentions&quot;&gt;The Good: Intentions&lt;/h4&gt;

&lt;p&gt;Inferring the type of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List(1, 2.3)&lt;/code&gt; to the useless common supertype of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[AnyVal]&lt;/code&gt; (as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Double&lt;/code&gt; do not have any interface in common) was
deemed to be too confusing for beginners coming from Java.&lt;/p&gt;

&lt;p&gt;Instead, compiler magic in the shape of “implicit numeric conversions” was
added to convert “smaller” number types to “larger” ones, thus inferring
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[Double]&lt;/code&gt; in the example above.&lt;/p&gt;

&lt;p&gt;While the mechanism looks quite innocent, it rears its ugly hand in many
unintuitive and unexpected circumstances, as these kinds of numeric conversions
not only convert smaller integer types to larger integer types and smaller
floating point number types to larger floating point number types, but also
integers to floating point numbers:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;kt&quot;&gt;Long&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Int -&amp;gt; Long&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;123.45f&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Float -&amp;gt; Double&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;wat&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Float&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;123456789L&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Long -&amp;gt; Float&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//           result: 123456792.0f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;the-bad-type-inference&quot;&gt;The Bad: Type Inference&lt;/h4&gt;

&lt;p&gt;Scala’s type inference makes the behavior a lot more confusing compared to
languages with mandatory type annotations.&lt;/p&gt;

&lt;p&gt;Creating a list with two numbers triggers the conversion, concatenating two
lists with one number each does not:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;// List[Double]&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// List[AnyVal]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Numbers of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt; are implicitly converted to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Long&lt;/code&gt;, but not to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BigInt&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2L&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// List[Long]&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BigInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// List[Any]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Although conversion only happens when there isn’t another unrelated type involved:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.2f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.4d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// List[Double]&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.2f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.4d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;abc&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// List[Any]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Assigning a list of integers to a list of doubles works if done in a single line,
but fails when done in two:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nums1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// compiles&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nums2a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nums2b&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nums5a&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;// fails to compile&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On top of that, implicit numeric conversions also interact with type parameters.
Consider this change in type inference due to a binary compatible &lt;a href=&quot;https://github.com/scala/scala/pull/5522&quot;&gt;“widening” of
types in the method signature of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#::&lt;/code&gt; method&lt;/a&gt;
between Scala 2.12.1 and 2.12.2:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#::&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#::&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fibonacci&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;_2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Compiles         in Scala 2.12.1 with def #::(hd: A): Stream[A].&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Fails to compile in Scala 2.12.2 with def #::[B &amp;gt;: A](hd: B): Stream[B]:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// error: type mismatch; found Stream[AnyVal], required Stream[Double]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Experienced developers understand the reasons that cause these differences, but
it turns out to be quite baffling for users new to Scala.&lt;/p&gt;

&lt;h4 id=&quot;the-ugly-extension-methods&quot;&gt;The Ugly: Extension Methods&lt;/h4&gt;

&lt;p&gt;Another feature of Scala, extension methods, makes implicit numeric conversions
much worse.&lt;/p&gt;

&lt;p&gt;Java’s primitive types come without any methods, only operations like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;lt;&lt;/code&gt;.
Scala’s idea of minimizing the distinction between unboxed and boxed
numbers means that numeric types receive “convenience” extension methods
like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;round&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;floor&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toBinaryString&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toDegrees&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This gives rise to another set of puzzlers like the following:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mf&quot;&gt;123456789.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;round&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;123456792&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The reason for this behavior is that the extension methods are not consistently
defined on all number types. As the compiler fails to find methods on some type
(like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;round&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;), implicit numeric conversions are kicking in, silently
converting and mangling numbers to another type that has them.&lt;/p&gt;

&lt;p&gt;In response, another band-aid was applied. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;round&lt;/code&gt; was added to every number
implicitly convertible to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float&lt;/code&gt; to avoid triggering the implicit conversion.&lt;/p&gt;

&lt;p&gt;But even if all the missing methods on numbers were filled in, these efforts are
easily defeated, as extension methods are statically dispatched.
(Extension methods only &lt;em&gt;look&lt;/em&gt; like instance methods, but act like static methods.)
Thus the issue is just pushed down another layer:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mf&quot;&gt;123456789.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;round&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;123456789&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// fixed&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;round&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123456789&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;123456792&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// unfixable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also, this issue does not require conversions to floating point numbers.
Conversions between integer types suffer from the same problem:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bits&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Byte&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;bits&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;toBinaryString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;11111111111111111111111111111111&quot;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// a byte with 32 bits?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is a design failure that cannot be fixed without abandoning implicit numeric
conversions altogether.&lt;/p&gt;

&lt;h4 id=&quot;the-worst-having-a-way-out-but-not-choosing-it&quot;&gt;The Worst: Having a Way Out, but not Choosing It&lt;/h4&gt;

&lt;p&gt;The far-reaching damage of implicit numeric conversions far outweighs the
purported benefit of reducing beginner confusion and increasing convenience,
considering how inconsistent the conversions are applied in the first place from
the point of view of the target audience, new users.&lt;/p&gt;

&lt;p&gt;Union types would have been one way out of this mess. They naturally address the
concern of beginner-unfriendly type inference by removing implicit numeric
conversions and simply letting type inference do its job:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// should be List[Int|Double]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From an operational point of view, inferring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[Int|Double]&lt;/code&gt; is hardly more
useful than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[AnyVal]&lt;/code&gt; before. That’s not the point, though:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[Int|Double]&lt;/code&gt; pinpoints the issue (mixing different number types) in a way
new users can understand, whereas the old &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List[AnyVal]&lt;/code&gt; does not.&lt;/p&gt;

&lt;p&gt;Union types enable the compiler to implement a more direct “what you see is what
you get” approach instead of silently sprinkling magic over users’ code.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
Disappointingly, Dotty, the next version of Scala which adds union types, barely
addresses any of these issues&lt;sup id=&quot;fnref:better&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:better&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; and worsens the situation in some cases.&lt;/p&gt;

&lt;p&gt;The common approach of explicitly specifying the expected supertype stopped
working in Dotty:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// List[Any] = List(1.0, 2.3)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Even explicitly specifying union types does not prevent these conversions:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int|Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// List[Int|Double] = List(1.0, 2.3)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding an unrelated type prevents the conversion though:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;abc&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// List[Any] = List(1, 2.3, abc)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Scala users that have settled on adding the imperfect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ywarn-numeric-widen&lt;/code&gt;
to their list of compiler flags will be hit the hardest, as the warning is not
implemented in Dotty and even if it were, they are now left with fewer options
to address the warning in Dotty.&lt;/p&gt;

&lt;h4 id=&quot;bonus-quirk&quot;&gt;Bonus Quirk&lt;/h4&gt;

&lt;p&gt;Regardless of whether this problem is fixed, the implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;round&lt;/code&gt; on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Double&lt;/code&gt; is still wrong and broken for unrelated reasons.&lt;/p&gt;

&lt;p&gt;Scala repeats another mistake from Java that was originating from C.
Interestingly, while the .NET team copied a lot of design decisions from Java,
they considered the issue to be so egregious that they fixed it before their
first release of .NET.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:term&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;em&gt;Implicit numeric conversion&lt;/em&gt; is used as a term to describe the general concept in this document. In practice, various approaches have been tried to implement the concept: a) literal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit def&lt;/code&gt;s in the &lt;a href=&quot;https://github.com/scala/scala/blob/2.12.x/src/library/scala/Byte.scala#L471&quot;&gt;source code&lt;/a&gt; which exist only for “educational purposes” and are not actually used by the compiler anymore, b) the non-implicit methods that the compiler uses instead, c) the notion of &lt;a href=&quot;https://www.scala-lang.org/files/archive/spec/2.12/03-types.html#weak-conformance&quot;&gt;&lt;em&gt;weak conformance&lt;/em&gt;&lt;/a&gt; and d) the notion of &lt;a href=&quot;https://github.com/lampepfl/dotty/commit/421f29573190fca94e595bbfe30619a23b052aad&quot;&gt;“numeric harmonization”&lt;/a&gt; &lt;a href=&quot;#fnref:term&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:mistake0&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;blockquote&gt;
        &lt;p&gt;It would be totally delightful to go through [Java] Puzzlers, another book that I wrote with Neal Gafter, which contains all the traps and pitfalls in the language and just excise them – one by one. Simply remove them.&lt;br /&gt;There are things that were just mistakes, so for example … [misspeaks] … int to float, is a primitive widening conversion and happens silently, but is lossy if you go from int to float and back to int. You often won’t get the same int that you started with.&lt;br /&gt;Because, you know, floats, some of the bits are used for the exponent rather then the mantissa, so you loose precision. When you go to float and back to int you’ll find that you didn’t have the int you started with.&lt;br /&gt;So, you know, it was a mistake, it should corrected, it would break existing programs. So I do like the idea of essentially writing a new language which is very similar to Java which sort of fixes all these bad things. And if someone’s to call it ‘Java’, that would be great, too. Just so long as traditional Java source code can still be compiled and run against the latest VMs. […]&lt;br /&gt;&lt;cite&gt;Joshua Bloch, Devoxx 2008&lt;/cite&gt;&lt;/p&gt;
      &lt;/blockquote&gt;
      &lt;p&gt;&lt;a href=&quot;#fnref:mistake0&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:mistake1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=hcY8cYfAEwU&amp;amp;t=10m13s&quot;&gt;OSCON Java 2011: Josh Bloch, “Java: The Good, Bad, and Ugly Parts”&lt;/a&gt; &lt;a href=&quot;#fnref:mistake1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:better&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Numbers are not implicitly converted to allow extension methods calls defined on larger numbers anymore, because Dotty invented another slightly different language concept, “numeric harmonization”, which only works on a small predefined set of language constructs like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try&lt;/code&gt; and in arguments to repeated parameters. &lt;a href=&quot;#fnref:better&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 12 May 2017 10:00:00 +0000</pubDate>
        <link>/languages/implicit-numeric-conversions.html</link>
        <guid isPermaLink="true">/languages/implicit-numeric-conversions.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Fixing Rust&apos;s mistakes – Syntax</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;As Rust 2.0 is not going to happen, Rust users will never get these language design fixes:&lt;/strong&gt;&lt;/em&gt;&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:nimfsoft&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:nimfsoft&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;details class=&quot;note&quot;&gt;
  &lt;summary&gt;&lt;b&gt;A note on the lower bar of a hypothetical Rust 2.0&lt;/b&gt;&lt;/summary&gt;

  &lt;p&gt;An &lt;a href=&quot;https://www.ncameron.org/blog/rust-in-2023/&quot;&gt;article touching on &quot;Rust 2.0&quot;&lt;/a&gt; and its reactionary reception
     made it apparent that language evolution has two boundaries, not one:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;Boundary 1 (upper bar of change): Things a hypothetical language &quot;v2.0&quot; is &lt;em&gt;not allowed&lt;/em&gt; to improve for compatibility reasons.&lt;/li&gt;
    &lt;li&gt;Boundary 2 (lower bar of change): Things that a hypothetical language &quot;v2.0&quot; &lt;em&gt;needs to improve&lt;/em&gt; for such an effort to be worthwhile to contributors and users.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;For Rust, we know the exact coordinates of the first boundary, but very little about the second boundary,
  as such &quot;critical&quot; engagement is poorly received by the community.&lt;/p&gt;

  &lt;p&gt;Nevertheless, only a cursory look is needed to conclude that &quot;Rust 2.0&quot; is very unlikely:&lt;br /&gt;
  The lower bar is above the upper one, i. e. the required changes to make it worthwhile are larger than Rust leadership&apos;s acceptance for change.&lt;/p&gt;

  &lt;p&gt;This doesn&apos;t mean that we can&apos;t explore the second boundary, and collect these &quot;unacceptable fixes&quot;
  as a learning opportunity for future language designers!&lt;/p&gt;

&lt;/details&gt;

&lt;h4 id=&quot;drop--struct-initialization-syntax&quot;&gt;Drop &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt; struct initialization syntax&lt;/h4&gt;

&lt;p&gt;There is little reason why invoking functions, initializing structs and enums, and initializing tupled structs and enums
have to follow different rules.&lt;sup id=&quot;fnref:choice&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:choice&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Instead, do away with the distinction between tupled vs. non-tupled structs/enums and standardize on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; for function
invocation and struct/enum initialization.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;rust-struct-initializer-mistake&quot;&gt;this article&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h4 id=&quot;named-parameters-using-&quot;&gt;Named parameters using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;After dropping the special syntax for struct literal initialization, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; to name parameters for any kind of invocations in Rust.&lt;/p&gt;

&lt;p&gt;This allows restoring the intuition that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; is followed by a value and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; is followed by a type, and that every value can receive a type ascription.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;rust-struct-initializer-mistake#appendix-a-detailed-look-at-the-role-of-&quot;&gt;this article’s appendix&lt;/a&gt; for an evaluation of available design options.&lt;/p&gt;

&lt;h4 id=&quot;use--instead-of--for-generics&quot;&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::&amp;lt;&amp;gt;&lt;/code&gt; for generics&lt;/h4&gt;

&lt;p&gt;Turns out “trying to preserve the strangeness budget”&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; can’t fix a &lt;a href=&quot;stop-using-angle-brackets-for-generics&quot;&gt;broken design&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;drop-range-syntax&quot;&gt;Drop range syntax&lt;/h4&gt;

&lt;p&gt;It takes up way too much language footprint for very little actual benefit, is a source of language expansion proposals
and the actual implementation in Rust suffers from quite &lt;a href=&quot;https://ridiculousfish.com/blog/posts/least-favorite-rust-type.html&quot;&gt;a few other problems&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;drop-array-and-slice-syntax&quot;&gt;Drop array and slice syntax&lt;/h4&gt;

&lt;p&gt;This frees up the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; bracket pair for more useful purposes, like &lt;a href=&quot;#use--instead-of--for-generics&quot;&gt;type parameters/arguments&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;fold-index-and-indexmut-into-fn-trait-family&quot;&gt;Fold &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Index&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IndexMut&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fn&lt;/code&gt; trait family&lt;/h4&gt;

&lt;p&gt;Providing traits to let people decide how round they want their function call parentheses to be is not a useful feature.&lt;/p&gt;

&lt;h4 id=&quot;replace-impl-with-purpose-focused-alternatives&quot;&gt;Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; with purpose-focused alternatives&lt;/h4&gt;

&lt;p&gt;There are roughly three different purposes for which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; is used.
Disentangle these purposes, drop the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;impl&lt;/code&gt; keyword, and make the replacements feel more cohesive with the rest of the language:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;details&gt;
      &lt;summary&gt;Replace &lt;code&gt;impl&lt;/code&gt; definitions that add methods to a struct/enum/... with methods in the struct/enum/... body.&lt;/summary&gt;
      Replace &lt;pre&gt;&lt;code&gt;struct Foo { bar: Bar }
impl Foo { fn qux() -&amp;gt; Qux { ... } }&lt;/code&gt;&lt;/pre&gt; with &lt;pre&gt;&lt;code&gt;struct Foo(bar: Bar) {
  fn qux() -&amp;gt; Qux { ... }
}&lt;/code&gt;&lt;/pre&gt;
    &lt;/details&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;details&gt;
      &lt;summary&gt;Replace &lt;code&gt;impl&lt;/code&gt; with &lt;code&gt;trait&lt;/code&gt; in definitions that implement a &lt;code&gt;trait&lt;/code&gt; for a given struct/enum/... type.&lt;/summary&gt;
      Replace &lt;pre&gt;&lt;code&gt;impl SomeTrait for Type&lt;/code&gt;&lt;/pre&gt; with &lt;pre&gt;&lt;code&gt;trait SomeTrait for Type&lt;/code&gt;&lt;/pre&gt;
    &lt;/details&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;details&gt;
      &lt;summary&gt;Replace &lt;code&gt;impl&lt;/code&gt; in definitions that hold &quot;extension&quot; methods.&lt;/summary&gt;
      Replace &lt;pre&gt;&lt;code&gt;impl&amp;lt;T&amp;gt; Option&amp;lt;Option&amp;lt;T&amp;gt;&amp;gt; { ... }&lt;/code&gt;&lt;/pre&gt; with &lt;pre&gt;&lt;code&gt;trait OptionExt&amp;lt;T&amp;gt; for Option&amp;lt;Option&amp;lt;T&amp;gt;&amp;gt; { ... }&lt;/code&gt;&lt;/pre&gt;
    &lt;/details&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;stop-using-macros-to-emulate-varargs&quot;&gt;Stop using macros to emulate varargs&lt;/h4&gt;

&lt;p&gt;Macros are largely used to work around the lack of varargs in Rust.&lt;sup id=&quot;fnref:varargs&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:varargs&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Instead, extend Rust’s vararg support from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern&lt;/code&gt; functions to all functions.&lt;/p&gt;

&lt;h4 id=&quot;drop-&quot;&gt;Drop &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;The distinction between path navigation (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::&lt;/code&gt;) and member access (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;) is not important enough to bother users at every single occasion.&lt;/p&gt;

&lt;p&gt;Instead, let the IDE use some syntax coloring and be done with it.&lt;/p&gt;

&lt;h4 id=&quot;drop-as&quot;&gt;Drop &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;… or at least make it make sense: it should &lt;em&gt;either&lt;/em&gt; do type conversions &lt;em&gt;or&lt;/em&gt; value conversions, but not both.&lt;/p&gt;

&lt;p&gt;Not to mention that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as&lt;/code&gt; caused security vulnerabilities already.&lt;sup id=&quot;fnref:6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h4 id=&quot;drop-if-let&quot;&gt;Drop &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if-let&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;You know a feature is not well-thought-out if it has spawned 4 extensions proposals already.&lt;/p&gt;

&lt;p&gt;Instead, use the vastly superior &lt;a href=&quot;unified-condition-expressions-comparison&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt; design&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;drop-procedure-syntax&quot;&gt;Drop procedure syntax&lt;/h4&gt;

&lt;p&gt;Functions that return no useful value enjoy special syntax privileges over functions that return a value.&lt;/p&gt;

&lt;p&gt;Drop this syntax sugar and require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&amp;gt; ()&lt;/code&gt; to be written down explicitly, like for every other type.&lt;/p&gt;

&lt;h4 id=&quot;drop---in-function-signatures&quot;&gt;Drop &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&amp;gt;&lt;/code&gt; in function signatures&lt;/h4&gt;

&lt;p&gt;No reason to have two different ways to attach a type to the preceding program element. Just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;remove-significance-of-semicola&quot;&gt;Remove significance of semicola&lt;/h4&gt;

&lt;p&gt;Varying the meaning of a piece of code based on the presence of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt; at a specific line is bad user interface design.&lt;/p&gt;

&lt;p&gt;Remove it and implement automatic semicolon inference, such that IDEs can show them, but no user has to ever type them.&lt;sup id=&quot;fnref:7&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:7&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://old.reddit.com/r/rust/comments/wvynot/does_rust_have_any_design_mistakes/&quot;&gt;“Does Rust have any design mistakes?”&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/rust-lang/rust/issues?q=label%3Arust-2-breakage-wishlist&quot;&gt;label:rust-2-breakage-wishlist&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/broken.20and.20un-fixable.20parts.20of.20Rust&quot;&gt;Broken and un-fixable parts of Rust&lt;/a&gt; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:nimfsoft&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://nimfsoft.art/blog/2025/06/26/analysis-of-rust-language-design-flaws/&quot;&gt;An Analysis of Rust’s Language Design Flaws&lt;/a&gt; &lt;a href=&quot;#fnref:nimfsoft&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:choice&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Especially considering that half the people immediately define a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::new()&lt;/code&gt; functions to avoid struct initialization syntax.&lt;br /&gt;Having the choice between both is already a net-negative on its own. &lt;a href=&quot;#fnref:choice&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://steveklabnik.com/writing/the-language-strangeness-budget&quot;&gt;The language strangeness budget&lt;/a&gt; &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:varargs&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;All language designers hate varargs, but handing out macros as a replacement is considerably worse. &lt;a href=&quot;#fnref:varargs&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1940804&quot;&gt;Using u16::max instead of u16::MAX potentially allows very long certificates&lt;/a&gt; &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:7&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;If your sole wisdom on “leaving semicolons out” is JavaScript’s ASI, then you are not qualified to have an opinion on this topic, sorry. &lt;a href=&quot;#fnref:7&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 20 Jul 2017 00:00:00 +0000</pubDate>
        <link>/languages/rust-design-mistakes-syntax.html</link>
        <guid isPermaLink="true">/languages/rust-design-mistakes-syntax.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Generics</title>
        <description>&lt;p&gt;Two interconnected design decisions achieve a particularly interesting sweet-spot in language design:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ident: Type&lt;/code&gt; syntax allows consistent and straight-forward placement of generics, compared
to languages which use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Type ident&lt;/code&gt;&lt;sup id=&quot;fnref:identtype&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:identtype&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:
    &lt;blockquote&gt;
      &lt;p&gt;Generics (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[T]&lt;/code&gt;) always follow the name of a class or a method, both at the definition-site and at the use-site.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;A clearly defined use of brackets results in a more regular, easier to understand syntax that has
superior readability compared to languages that use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; for generics as well as for
comparisons and bitshifts, or use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; to stand for operations on arrays&lt;sup id=&quot;fnref:stop-generics&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:stop-generics&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:
    &lt;blockquote&gt;
      &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; &lt;em&gt;encloses&lt;/em&gt; type parameters or type arguments&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; &lt;em&gt;groups&lt;/em&gt; expressions, parameter/argument lists or tuples&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt; &lt;em&gt;sequences&lt;/em&gt; statements or definitions&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means that generics do not need to be treated as an “advanced” language concept.&lt;/p&gt;

&lt;p&gt;Instead, the mental model becomes so simple that every class or method can be thought of having …&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;zero or one parameter lists for types, followed by&lt;/li&gt;
  &lt;li&gt;zero or more parameter lists for values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;???&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;abc&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s all there is to it!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:identtype&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;type-annotations&quot;&gt;Why is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ident: Type&lt;/code&gt; better than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Type ident&lt;/code&gt;?&lt;/a&gt; &lt;a href=&quot;#fnref:identtype&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:stop-generics&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;stop-using-angle-brackets-for-generics&quot;&gt;Stop Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; for Generics&lt;/a&gt; &lt;a href=&quot;#fnref:stop-generics&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 21 Jul 2017 00:00:00 +0000</pubDate>
        <link>/languages/generics.html</link>
        <guid isPermaLink="true">/languages/generics.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Use `ident: Type`, not `Type ident`</title>
        <description>&lt;p&gt;In expressive languages, developers generally need to use fewer temporary variables.
This means that in a typical piece of code there are fewer names defined, but
those names carry higher importance.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ident: Type&lt;/code&gt; syntax lets developers focus on the name by placing it ahead of its
type annotation. 
This means that the vertical offset of names stays consistent, regardless of a type annotation’s presence or absence&lt;sup id=&quot;fnref:type-inference&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:type-inference&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;23.42&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// vs. (hypothetical syntax)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;hello&quot;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Float&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;23.42&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In addition to this, there are three technical reasons why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ident: Type&lt;/code&gt; is superior:&lt;/p&gt;

&lt;h4 id=&quot;1-input-before-output&quot;&gt;1. Input before output&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i: Int&lt;/code&gt; syntax naturally leads to a method syntax where the inputs
(parameters) are defined before the output (result type), which in turn leads to
more consistency with lambda syntax (whose inputs are also defined before its
output).&lt;/p&gt;

&lt;h4 id=&quot;2-consistency-between-definition-and-usage&quot;&gt;2. Consistency between definition and usage&lt;/h4&gt;

&lt;p&gt;The way a class or method is defined should mirror the way it can be used.
(See &lt;a href=&quot;stop-using-angle-brackets-for-generics&quot;&gt;Stop using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; for generics&lt;/a&gt;.)&lt;/p&gt;

&lt;h4 id=&quot;3-definition-before-usage&quot;&gt;3. Definition before usage&lt;/h4&gt;

&lt;p&gt;A generic type parameter should be declared before it is used.
Otherwise it’s hard to tell to what a type argument refers to:&lt;/p&gt;

&lt;div class=&quot;language-ceylon highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Does the result type T refer to the class&apos; &amp;lt;T&amp;gt; in scope,
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// or to the method&apos;s &amp;lt;T&amp;gt; that comes after it?
&lt;/span&gt;  &lt;span class=&quot;nd&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;                            
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;language-comparison&quot;&gt;Language Comparison&lt;/h4&gt;

&lt;p&gt;As languages have explored various designs&lt;sup id=&quot;fnref:curly&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:curly&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, we can check whether they satisfy
the three properties mentioned above:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;C#&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Kotlin&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Ceylon&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Core&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Only the last approach delivers all three desirable properties:&lt;/p&gt;

&lt;table class=&quot;table-medium table-layout-auto&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Input before output&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Definition/usage consistency&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Definition before usage&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;&lt;em&gt;Java&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;❌&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;❌&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;&lt;em&gt;C#&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;❌&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;❌&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;&lt;em&gt;Kotlin&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;❌&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;&lt;em&gt;Ceylon&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;❌&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;❌&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;&lt;em&gt;Core&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;✅&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:type-inference&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;type inference means that the compiler can figure out types without having a developer writing them down explicitly &lt;a href=&quot;#fnref:type-inference&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:curly&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;focusing on curly-brace languages here, as languages like Haskell, ML and OCaml, Idris have slightly different design optima &lt;a href=&quot;#fnref:curly&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 21 Jul 2017 00:00:00 +0000</pubDate>
        <link>/languages/type-annotations.html</link>
        <guid isPermaLink="true">/languages/type-annotations.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: (More) Mistakes of Rust</title>
        <description>&lt;p&gt;&lt;em&gt;(A random grabbag of things that I haven’t managed to include into the main article yet.)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Strings don’t offer indexing, because it doesn’t make sense for UTF-8. Correct! But Strings offer slicing … WAT?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Inconsistent naming. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;str&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Path&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PathBuf&lt;/code&gt; etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Closures could be made to look much closer to functions, but somehow aren’t.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;“associated” functions in trait impls. I’d prefer separating them from normal functions and drop the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt; where possible.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Arbitrary abbreviations all over the place.
It’s 2017, your computer won’t run out of memory just because your compiler’s symbol table stores &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Buffer&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Buf&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Can someone decide on a casing rule for types, please, instead of mixing lowercase and uppercase names?
Some types being “primitive” is an incredibly poor excuse.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Also, having both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CamelCase&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methods_with_underscores&lt;/code&gt;?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Single-use packages like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::option::Option&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::result::Result&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::default::Default&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iter()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iter_mut()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;into_iter()&lt;/code&gt; … decide prefix &lt;em&gt;or&lt;/em&gt; postfix style and stick with it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Forward and backward annotations: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[foo] struct Foo {}&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct Foo { #![foo] }&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Type bounds are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sized&lt;/code&gt; by default, with some weird special syntax to opt out (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?Sized&lt;/code&gt;).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;///&lt;/code&gt; for normal documentation, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//!&lt;/code&gt; for module level documentation.
Documentation already uses Markdown, so maybe just let people drop a markdown file in the module dir?
That would make documentation much more accessible when browsing through GitHub repositories.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Also, documentation can cause compiler errors … that’s especially fun if you just commented a piece of code for testing/prototyping.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Type alias misuse: In e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;io&lt;/code&gt; crate: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type Result&amp;lt;T&amp;gt; = Result&amp;lt;T, io::Error&amp;gt;&lt;/code&gt; … just call it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IoResult&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Compared to languages where macro invocation do not require special syntax (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;), the “obviousness” of invoking
macros seems to have encouraged Rust developers to go completely over board in terms of magic.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 30 Jul 2017 00:00:00 +0000</pubDate>
        <link>/languages/more-design-mistakes-of-rust.html</link>
        <guid isPermaLink="true">/languages/more-design-mistakes-of-rust.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Equality &amp; Identity – Part 1: Overview</title>
        <description>&lt;p&gt;Most languages have a notion of equality comparisons based on &lt;em&gt;value equality&lt;/em&gt;.
Many of them also provide a more restricted equality comparison that works only
on references, often called &lt;em&gt;reference equality&lt;/em&gt;. Here are a few examples:&lt;/p&gt;

&lt;h4 id=&quot;java&quot;&gt;Java&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; implements reference equality on reference types.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object.equals&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Objects.equals&lt;/code&gt; implement reference equality by default, but can be overridden to implement value equality on reference types.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Arrays.deepEquals&lt;/code&gt; implements value equality on arrays (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;equals&lt;/code&gt; does reference equality on arrays).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; implements value equality on primitive types.
    &lt;ul&gt;
      &lt;li&gt;Primitive types can be implicitly converted to special wrapper classes, which implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;equals&lt;/code&gt; slightly differently.&lt;/li&gt;
      &lt;li&gt;As these wrapper classes are reference types, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; checks for reference equality of the wrapper classes.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;javascript&quot;&gt;JavaScript&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; uses &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Equality_comparisons_and_sameness#loose_equality_using&quot;&gt;“loose equality”&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;===&lt;/code&gt; uses &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Equality_comparisons_and_sameness#strict_equality_using&quot;&gt;“strict equality”&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object.is&lt;/code&gt; uses &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Equality_comparisons_and_sameness#same-value_equality_using_object.is&quot;&gt;“same-value equality”&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Specific methods like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array#includes&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Set#has&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Map#has&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Map#get&lt;/code&gt; use
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Equality_comparisons_and_sameness#same-value-zero_equality&quot;&gt;“same-value-zero equality”&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;rust&quot;&gt;Rust&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eq&lt;/code&gt; (defined on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PartialEq&lt;/code&gt;) implements value equality. It does not require that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x eq x&lt;/code&gt; is true.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; (defined on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt;) implements value equality and requires that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x eq x&lt;/code&gt; is true. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt; implies &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PartialEq&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Reference equality can only be implemented by casting references to pointers and comparing them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;c&quot;&gt;C#&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object.Equals&lt;/code&gt; implements reference equality be default, but can be overridden to implement value equality on reference types.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValueType.Equals&lt;/code&gt; calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Equals&lt;/code&gt; on each field contained within a value types.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object.ReferenceEquality&lt;/code&gt; implements reference equality. The method always returns false for value types.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; implements reference equality on reference types, but can be overloaded to implement value equality (as done on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.String&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; can be overloaded to implement value equality for value types.&lt;/li&gt;
  &lt;li&gt;Numeric types use an extended version of value equality in which different numeric types are equal if they represent the same value.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IEquatable.Equals&lt;/code&gt; can be implemented to reduce boxing for value types, but should return the same results as overridden &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Equals&lt;/code&gt; methods on that type.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;scala&quot;&gt;Scala&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; (defined on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Any&lt;/code&gt;) implements value equality.
    &lt;ul&gt;
      &lt;li&gt;An extended version of value equality is used in which different numeric types can be equal if they represent the same value.&lt;/li&gt;
      &lt;li&gt;This does not extend to arrays, which are plain Java arrays underneath.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eq&lt;/code&gt; (defined on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnyRef&lt;/code&gt;) implements reference equality.&lt;/li&gt;
  &lt;li&gt;The artifacts of Java’s wrapper classes for primitive types are significantly reduced.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 31 Oct 2017 00:00:00 +0000</pubDate>
        <link>/languages/equality-and-identity-overview.html</link>
        <guid isPermaLink="true">/languages/equality-and-identity-overview.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Equality &amp; Identity – Part 2: Problems</title>
        <description>&lt;h4 id=&quot;containment&quot;&gt;Containment&lt;/h4&gt;

&lt;p&gt;The core issue is that equality on its own is insufficient to implement some, rather mundane, algorithms.&lt;/p&gt;

&lt;p&gt;Asking the simple question “is some element contained in this data structure” in different languages demonstrates the problem:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Java:       List.of(Float.NaN).contains(Float.NaN);          // true
JavaScript: [NaN].includes(NaN)                              // true
Rust:       &amp;amp;[0.0/0.0].contains(0.0/0.0)                     // false
C#:         ((List&amp;lt;float&amp;gt;) [float.NaN]).Contains(float.NaN)  // true
Haskell:    elem (0.0/0.0) [0.0/0.0]                         // false
Scala:      List(Float.NaN).contains(Float.NaN)              // false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Only Java and C# get this right, and the reason why it works in Java is quite incidental:&lt;/p&gt;

&lt;p&gt;Methods like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;equals&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contains&lt;/code&gt; box the arguments before comparison, first check for reference equality,
then call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;equals&lt;/code&gt;. Without boxing, it would not be possible to find a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NaN&lt;/code&gt; value in a data structure in Java.&lt;/p&gt;

&lt;h4 id=&quot;complexity&quot;&gt;Complexity&lt;/h4&gt;

&lt;p&gt;The design decisions made by languages also come with a large footprint in language complexity. For instance:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There are many, often confusing options which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;equals&lt;/code&gt; method should be overridden or how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; should be overloaded.&lt;/li&gt;
  &lt;li&gt;It is hard to know which of the many methods to use, and which semantics have been implemented by the author of the type.&lt;/li&gt;
  &lt;li&gt;Value types are often unnecessarily boxed for equality operations.&lt;/li&gt;
  &lt;li&gt;Generic code has to decide at declaration-site whether it requires arguments to be reference or value types.
    &lt;ul&gt;
      &lt;li&gt;Java works around this by only supporting reference types in generics.&lt;/li&gt;
      &lt;li&gt;Scala requires explicit bounds (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;: AnyRef&lt;/code&gt;) to mark types that require reference equality.&lt;/li&gt;
      &lt;li&gt;C# provides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; (reference type) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; (value type) constraints on generic types.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Language creators (Java) or users (Scala) need to decide whether interfaces
support value types, or require that all subtypes are reference types.&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 31 Oct 2017 00:00:00 +0000</pubDate>
        <link>/languages/equality-and-identity-problems.html</link>
        <guid isPermaLink="true">/languages/equality-and-identity-problems.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Equality &amp; Identity – Part 3: Solution</title>
        <description>&lt;p&gt;Let’s take a step back and think about what these equality operations do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Reference equality acts as a built-in, hard-coded comparison of the references themselves.&lt;/li&gt;
  &lt;li&gt;Value equality compares equality according to a user-defined implementation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is it possible to re-interpret reference equality that retains the existing behavior for reference types,
but adds intuitive and useful behavior for value types (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float&lt;/code&gt; etc.)?&lt;/p&gt;

&lt;p&gt;Yes! There is a &lt;em&gt;very&lt;/em&gt; useful reinterpretation of reference equality that
addresses the mentioned issues and solves a few other problems along the way.&lt;/p&gt;

&lt;p&gt;The core insight is that there are two –not one– useful, fundamental questions to ask:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;“Is A &lt;em&gt;identical&lt;/em&gt; to B?”&lt;/li&gt;
  &lt;li&gt;“Is A &lt;em&gt;equal&lt;/em&gt; to B?”&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;defining-equality-and-identity&quot;&gt;Defining Equality and Identity&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;An &lt;em&gt;identity comparison&lt;/em&gt; asks if two things are &lt;em&gt;identical&lt;/em&gt;, based on a language-defined, fixed definition of identity.&lt;/li&gt;
  &lt;li&gt;An &lt;em&gt;equality comparison&lt;/em&gt; asks if two things are &lt;em&gt;equal&lt;/em&gt;, based on a user- or library-defined definition of equality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This definition of an identity comparison extends the concept of reference comparisons to value types,
by comparing the bits (and the type) of the value at hand:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;reference types compare the bits of the reference itself.&lt;/li&gt;
  &lt;li&gt;value types compare the bits of themselves, e. g. the bits of an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float&lt;/code&gt;, or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Complex&lt;/code&gt; value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that an instance of a reference type is only identical to another instance if they are the same reference, and an instance of a value types is only identical to another instance if their values match up exactly.&lt;/p&gt;

&lt;p&gt;Having one operation, which is well-defined on both value types and reference types, also simplifies things in generic contexts.&lt;/p&gt;

&lt;h4 id=&quot;how-do-equality-and-identity-comparisons-work&quot;&gt;How do equality and identity comparisons work?&lt;/h4&gt;

&lt;p&gt;Compared to the rather complicated, indirect approaches shown earlier, the concept of
&lt;em&gt;identity&lt;/em&gt; and &lt;em&gt;equality&lt;/em&gt; provides a simple and consistent design.&lt;/p&gt;

&lt;p&gt;The following table shows how this definition of &lt;em&gt;identity&lt;/em&gt; and &lt;em&gt;equality&lt;/em&gt; could work in practice:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;type&lt;/th&gt;
      &lt;th&gt;∘ means “is identical to”&lt;/th&gt;
      &lt;th&gt;∘ means “is equal to”&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;true ∘ true&lt;/td&gt;
      &lt;td&gt;value&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1 ∘ 1&lt;/td&gt;
      &lt;td&gt;value&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1.0 ∘ 1.0&lt;/td&gt;
      &lt;td&gt;value&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Float.NaN ∘ Float.NaN&lt;/td&gt;
      &lt;td&gt;value&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
      &lt;td&gt;false&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;+0.0 ∘ -0.0&lt;/td&gt;
      &lt;td&gt;value&lt;/td&gt;
      &lt;td&gt;false&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;BigInt(1) ∘ BigInt(1)&lt;/td&gt;
      &lt;td&gt;reference&lt;/td&gt;
      &lt;td&gt;false&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;“abc” ∘ “abc”&lt;/td&gt;
      &lt;td&gt;reference&lt;/td&gt;
      &lt;td&gt;false&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Languages should provide two, distinct operations that provide equality comparisons and identity comparisons.&lt;/p&gt;

&lt;p&gt;Ideally, these operations do not exist on the languages’ top type, but are only available when the type is constrained
  appropriately (e. g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fun same[E : Identity](a: E, b: E) = a === b&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Assuming a language with traits/interfaces, code defining these two concepts would look like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;trait Identity
  fun ===(other: Self): Bool
  fun !==(other: Self): Bool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;trait Equality
  fun == (other: Self): Bool
  fun != (other: Self): Bool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Tue, 31 Oct 2017 00:00:00 +0000</pubDate>
        <link>/languages/equality-and-identity-solution.html</link>
        <guid isPermaLink="true">/languages/equality-and-identity-solution.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Package Objects in Scala</title>
        <description>&lt;p&gt;Scala has the concept of
&lt;a href=&quot;http://www.scala-lang.org/docu/files/packageobjects/packageobjects.html&quot;&gt;&lt;em&gt;package objects&lt;/em&gt;&lt;/a&gt;
which allow the declaration of methods, classes etc. that appear as if they
existed directly inside a package, not enclosed in an object or a class.&lt;/p&gt;

&lt;p&gt;Given the definition of a method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qux&lt;/code&gt; for a package &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.bar&lt;/code&gt;, the method can
be called with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.bar.qux()&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;the-issue&quot;&gt;The Issue&lt;/h4&gt;

&lt;p&gt;Package objects are useful, but the way they are defined is pretty weird, and
one of the obscure, inconsistent and hard to explain decisions of the language:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/package-objects-bad.png&quot; alt=&quot;package-objects-bad&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The package clause is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;, not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.bar&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Given the package clause, the file package.scala is placed &lt;em&gt;outside&lt;/em&gt; of the
directory for which it defines members, further obscuring what it does.&lt;/li&gt;
  &lt;li&gt;The file name (&lt;em&gt;package.scala&lt;/em&gt;) is not in sync with the name of the package
object defined (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;There is some special syntax, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package object&lt;/code&gt;, that is not self-explanatory.&lt;/li&gt;
  &lt;li&gt;It is hard to quickly identify package objects, as IDEs tend to show the name
of the object and not the name of the file in the outline.&lt;/li&gt;
  &lt;li&gt;It also means it is unnecessarily hard to find package objects: To see whether
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.bar&lt;/code&gt; has a package object, you have to scour the parent package &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt;
for an object with the same name as the package (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;the-solution&quot;&gt;The Solution&lt;/h4&gt;

&lt;p&gt;Here is a design that addresses these issues and is intuitive enough to not
require a separate, explicit explanation of what package objects are, which
rules need to be followed and how they work:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// file: foo/bar/package.scala&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;foo.bar&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;qux&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;???&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;the-workaround&quot;&gt;The Workaround&lt;/h4&gt;

&lt;p&gt;As is it unlikely that this will ever be fixed, the best approach to package
objects is to ignore the confusing syntax completely.&lt;/p&gt;

&lt;p&gt;Instead, directly define them this way:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/package-objects-good.png&quot; alt=&quot;package-objects-good&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Coincidentally, this is exactly the transformation the compiler already does
when compiling package objects. It side-steps all the unnecessary language
complexity that was put on top of the concept of package objects.&lt;/p&gt;
</description>
        <pubDate>Wed, 20 Dec 2017 00:00:00 +0000</pubDate>
        <link>/languages/package-objects-in-scala.html</link>
        <guid isPermaLink="true">/languages/package-objects-in-scala.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Unified Condition Expressions – Introduction</title>
        <description>&lt;h4 id=&quot;idea&quot;&gt;Idea&lt;/h4&gt;

&lt;p&gt;Replace the different syntactic forms of&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; statements/expressions&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; on values&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt; on patterns and pattern guards&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt; constructs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;with a single, unified condition expression that scales from simple one-liners to complex pattern matches.&lt;/p&gt;

&lt;h4 id=&quot;motivation&quot;&gt;Motivation&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Cut the different syntax options down to a single one that is still easily recognizable by users.&lt;/li&gt;
  &lt;li&gt;Allow the design to scale seamlessly from simple cases to complicated ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;Minimizing the number of keywords or turning condition syntax into method calls (like Smalltalk) are non-goals.&lt;/p&gt;

&lt;h4 id=&quot;observations&quot;&gt;Observations&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Ternary expressions and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; statements can be fully subsumed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; expressions.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; has a fixed part whose value is compared using an equality relation against a set of branch-specific values.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; supports arbitrary conditions, but allows more than two branches only by chaining &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; to an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Splitting conditions into a &lt;em&gt;shared, common part&lt;/em&gt; and individual &lt;em&gt;condition continuations&lt;/em&gt; conflicts with mandatory parentheses around conditions.&lt;/li&gt;
  &lt;li&gt;To ensure unambiguous parsing …
    &lt;ul&gt;
      &lt;li&gt;the place where the shared part of condition ends and the individual continuations starts
requires either braces around the branch, or a start keyword like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;the place where a branch ends and the next individual condition starts requires either braces
around the branch, a keyword like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;end&lt;/code&gt;, or punctuation like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Indentation-sensitive syntax can be an alternative to both, but may or may not fit into the
target language’s desired overall look and feel.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;considerations&quot;&gt;Considerations&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Alternative keyword choices to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;when&lt;/code&gt;.&lt;br /&gt;
The keyword choice has no impact on the ideas presented.&lt;/li&gt;
  &lt;li&gt;Though not strictly required, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...&lt;/code&gt; may be used to make the division between the shared part of
the condition and the individual condition continuation more apparent to the reader.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;examples&quot;&gt;Examples&lt;/h4&gt;

&lt;p&gt;For the code examples, a hypothetical language with indentation-sensitive syntax and the keywords &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt; has been chosen.&lt;/p&gt;

&lt;h5 id=&quot;simple-if-expression&quot;&gt;simple if expression&lt;/h5&gt;
&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;                         &lt;span class=&quot;n&quot;&gt;/*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;same&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*/&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;                            &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;a-shared-comparison-operator-for-multiple-condition-continuations&quot;&gt;a shared comparison operator for multiple condition continuations&lt;/h5&gt;
&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt;       &lt;span class=&quot;n&quot;&gt;/*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;same&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*/&lt;/span&gt;    &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;             &lt;span class=&quot;n&quot;&gt;/*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;same&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*/&lt;/span&gt;       
  &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;                   &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;        &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;      &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;
  &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b&quot;&lt;/span&gt;                   &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b&quot;&lt;/span&gt;        &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b&quot;&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;                          &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;        &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;                  &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;different-comparison-operators-for-each-condition-continuation&quot;&gt;different comparison operators for each condition continuation&lt;/h5&gt;
&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;                                &lt;span class=&quot;n&quot;&gt;/*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;same&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*/&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt;  &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;                  &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;       &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NaN&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt;                  &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NaN&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b&quot;&lt;/span&gt;
          &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;                  &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;                   &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;method-calls&quot;&gt;method calls&lt;/h5&gt;
&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;                               &lt;span class=&quot;n&quot;&gt;/*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;same&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*/&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEmpty&lt;/span&gt;       &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;e&quot;&lt;/span&gt;           &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEmpty&lt;/span&gt;            &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;e&quot;&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt;           &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt;      
                 &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;           &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;                          &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;pattern-matching-is&quot;&gt;pattern matching (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt;)&lt;/h5&gt;

&lt;p&gt;While &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt; (being “just another” binary operator) is not strictly related to unified condition expressions,
its use in unified condition expressions unlocks support for additional functionality often found in languages with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt; keywords, such as binding values, wildcards (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;) and guards.&lt;/p&gt;

&lt;h6 id=&quot;binding-values&quot;&gt;binding values&lt;/h6&gt;
&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;                 &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Alice&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;_)&lt;/span&gt;     &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Bob&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;
                            &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;flow-typing&quot;&gt;flow typing&lt;/h6&gt;
&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pet&lt;/span&gt;                              &lt;span class=&quot;n&quot;&gt;/*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;same&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*/&lt;/span&gt;       &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pet&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(_)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;                               &lt;span class=&quot;n&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(_)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(_)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;                               &lt;span class=&quot;n&quot;&gt;Dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(_)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;dog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;pattern-guards&quot;&gt;pattern guards&lt;/h6&gt;
&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Alice&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;_)&lt;/span&gt;              &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;alice&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(_,&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;adult&quot;&lt;/span&gt;
                                     &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;minor&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h6 id=&quot;replacement-for-if-let&quot;&gt;replacement for “if-let”&lt;/h6&gt;
&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Alice&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;related-work&quot;&gt;Related Work&lt;/h4&gt;

&lt;dl&gt;
  &lt;dt&gt;PL/I&lt;/dt&gt;
  &lt;dd&gt;&lt;a href=&quot;https://en.wikibooks.org/wiki/Software_Engineers_Handbook/Language_Dictionary/PLI#Multi-branch_Conditionals:_SELECT&quot;&gt;select-when statement&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl&gt;
  &lt;dt&gt;SQL (SQL:2003)&lt;/dt&gt;
  &lt;dd&gt;&lt;a href=&quot;https://modern-sql.com/feature/case#barely-supported-forms&quot;&gt;&quot;extended case&quot; of case-when expression&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl&gt;
  &lt;dt&gt;CommonLisp&lt;/dt&gt;
  &lt;dd&gt;&lt;a href=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/m_cond.htm&quot;&gt;cond macro&lt;/a&gt; and &lt;a href=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/m_case_.htm#case&quot;&gt;case macro&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl&gt;
  &lt;dt&gt;Haskell (language extension)&lt;/dt&gt;
  &lt;dd&gt;&lt;a href=&quot;https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/multiway_if.html&quot;&gt;multi-way if-expressions&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl&gt;
  &lt;dt&gt;Rust&lt;/dt&gt;
  &lt;dd&gt;&lt;a href=&quot;https://doc.rust-lang.org/book/ch06-03-if-let.html&quot;&gt;if-let syntax&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl&gt;
  &lt;dt&gt;Swift&lt;/dt&gt;
  &lt;dd&gt;&lt;a href=&quot;https://docs.swift.org/swift-book/documentation/the-swift-programming-language/optionalchaining/&quot;&gt;Optional chaining&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
</description>
        <pubDate>Sun, 21 Jan 2018 00:00:00 +0000</pubDate>
        <link>/languages/unified-condition-expressions.html</link>
        <guid isPermaLink="true">/languages/unified-condition-expressions.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Rust&apos;s Into in Scala</title>
        <description>&lt;h3 id=&quot;rusts-into&quot;&gt;Rust’s Into&lt;/h3&gt;

&lt;p&gt;Rust’s &lt;a href=&quot;https://doc.rust-lang.org/std/convert/trait.Into.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::convert::Into&lt;/code&gt;&lt;/a&gt;
let’s you define conversion functions for structs like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pub struct Person { name: String }

impl Into&amp;lt;String&amp;gt; for Person {
    fn into(self: Person) -&amp;gt; String { self.name }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way functions can be defined that don’t e. g. require a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;, but accept anything that can be converted into a string. The conversion then happens with an explicit call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;into()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fn string&amp;lt;S: Into&amp;lt;String&amp;gt;&amp;gt;(s: S) -&amp;gt; String { s.into() }

let person = Person { name: &quot;Joe&quot;.to_string() };
string(person); // works
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;translation-into-scala&quot;&gt;Translation into Scala&lt;/h3&gt;

&lt;h4 id=&quot;view-bounds&quot;&gt;View Bounds&lt;/h4&gt;

&lt;p&gt;Interestingly, Scala has view bounds which embody the same concept.
They require an implicit function in scope which takes a given type and returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; (in our case).
View bounds (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;%&lt;/code&gt;) look like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def string[S &amp;lt;% String](s: S): String = s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s define &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; as we did above:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;case class Person(name: String)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And define our implicit method:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;object Person {
  implicit def view(self: Person): String = self.name
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can now call&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;val person = Person(&quot;Joe&quot;)
string(person) // works
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that there is no explicit call to some conversion method unlike in Rust.&lt;/p&gt;

&lt;h4 id=&quot;context-bounds&quot;&gt;Context Bounds&lt;/h4&gt;

&lt;p&gt;As I deprecated view bounds a few years ago, let’s look for an alternative approach to implement Rust’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Into&lt;/code&gt; in Scala!
One possibility is to use path-dependent types and context bounds (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; : &lt;/code&gt;) instead of view bounds (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;view&lt;/code&gt; method from above is kept unchanged):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Has[O] { type Conversion[I] = I =&amp;gt; O }
def string[S : Has[String]#Conversion](s: S) = s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Again, no explicit call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;into&lt;/code&gt; is necessary, but the type signature starts to look quite bulky!&lt;/p&gt;

&lt;h4 id=&quot;scalas-into&quot;&gt;Scala’s Into&lt;/h4&gt;

&lt;p&gt;Talking all of this into account, what other alternatives are there, which don’t rely on deprecated features or require long, ugly type signatures?&lt;/p&gt;

&lt;p&gt;It turns out, it’s possible to pick an approach that is quite close to Rust’s design!&lt;/p&gt;

&lt;p&gt;Let’s define an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Into&lt;/code&gt; trait, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strings&lt;/code&gt; method using it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;trait Into[+O] { def into(): O }
def strings(s: Into[String]) = s.into
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we define &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Into[String]&lt;/code&gt; for our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt;, and it turns out, we can supply the implementation either internally or externally! (Which might be quite useful: we can make the decision whether we want to allow or disallow someone else to provide an alternative conversion function.)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Approach 1:
case class Person(name: String) extends Into[String] {
  def into = name
}
// Approach 2:
case class Person(name: String)
object Person {
  implicit def Into(self: Person): Into[String] = () =&amp;gt; self.name
}

strings(Person(&quot;Joe&quot;)) // works with both approaches
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The only drawback is that, similar to Rust, the conversion method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;into&lt;/code&gt; needs to be called explicitly.&lt;/p&gt;

&lt;h4 id=&quot;javas-supplier&quot;&gt;Java’s Supplier&lt;/h4&gt;

&lt;p&gt;Perhaps amusingly, it’s also possible to completely forgo the definition of our own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Into&lt;/code&gt; type in favor of using Java 8’s
&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Supplier&lt;/code&gt;&lt;/a&gt; interface
(adjusting the types in the approaches above from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Into&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Supplier&lt;/code&gt; accordingly):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def strings(s: Supplier[String]) = s.get
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… and that’s it!&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;We saw how Rust’s very useful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Into&lt;/code&gt; type can be implemented in a different language, in four different ways, all with interesting benefits and drawbacks!&lt;/p&gt;
</description>
        <pubDate>Tue, 27 Mar 2018 00:00:00 +0000</pubDate>
        <link>/languages/rusts-into-in-scala.html</link>
        <guid isPermaLink="true">/languages/rusts-into-in-scala.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Unified Condition Expressions – Exceptions</title>
        <description>&lt;p&gt;A reasonable question that might be asked is whether this design can be extended to also handle thrown exceptions,
and whether such an extension could completely replace the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;try-catch-finally&lt;/code&gt; idiom.&lt;/p&gt;

&lt;p&gt;One language that has done something similar is Ocaml, which has
&lt;a href=&quot;https://blog.janestreet.com/pattern-matching-and-exception-handling-unite/&quot;&gt;extended its pattern matching syntax/semantics&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One option might be something along the lines of&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if readColorFromUri(location)
  // type-based pattern
  throws[IOException](let ex)        then &quot;file error due to \{ex}&quot;
  // value-based pattern
  throws(NetException(let msg))      then &quot;network error with message \{msg}&quot;
  // regular cases as usual
  == Color.RED                       then &quot;red&quot;
                                     else &quot;other color&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This might require adding some amount of language magic to deal with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throws&lt;/code&gt; construct though,
depending on the expressiveness of the core language.&lt;/p&gt;

&lt;p&gt;Considering the costs and the complexity involved, it may be a better approach to simply drop exceptions from the design
of the language and do without this additional layer of control flow.&lt;/p&gt;
</description>
        <pubDate>Sat, 28 Apr 2018 00:00:00 +0000</pubDate>
        <link>/languages/unified-condition-expressions-exceptions.html</link>
        <guid isPermaLink="true">/languages/unified-condition-expressions-exceptions.html</guid>
        
        
      </item>
    
      <item>
        <title>Library Design: Naming Conventions – Part 1: Creation</title>
        <description>&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 18%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th style=&quot;width: 34%&quot;&gt;Code Example&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;–&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3)
Array(12.3, 45.6)
Set(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;primary way of construction&lt;/li&gt;
          &lt;li&gt;resulting instance contains provided arguments verbatim&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;of(val1, ...)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Person.of(name, age)&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;secondary way of construction&lt;/li&gt;
          &lt;li&gt;resulting instance contains provided arguments verbatim&lt;/li&gt;
          &lt;li&gt;result type might use &lt;code&gt;Option&lt;/code&gt; or &lt;code&gt;Result&lt;/code&gt; types to encode failures&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;from(val)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Person.from(personEntity)
Person.from(family)&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;tertiary way of construction&lt;/li&gt;
          &lt;li&gt;arguments are extracted, adapted, and/or converted&lt;/li&gt;
          &lt;li&gt;the value of the instance is derived from the provided arguments&lt;/li&gt;
          &lt;li&gt;result type is likely to use &lt;code&gt;Option&lt;/code&gt; or &lt;code&gt;Result&lt;/code&gt; types to encode failures&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;parse(string)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Person.parse(string)
Int64.parse(string)&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;quaternary way of construction&lt;/li&gt;
          &lt;li&gt;argument is parsed from a less structured representation, such as strings&lt;/li&gt;
          &lt;li&gt;result type is highly likely to use &lt;code&gt;Option&lt;/code&gt; or &lt;code&gt;Result&lt;/code&gt; types to encode failures&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;modification&quot;&gt;Modification&lt;/h4&gt;

&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 18%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th style=&quot;width: 34%&quot;&gt;Code Example&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;with(val)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;person.withAge(23)
person.with(age = 23)&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;returns a copy of a value with parts replaced by the provided argument&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Tue, 19 Jun 2018 00:00:00 +0000</pubDate>
        <link>/languages/naming-conventions-creation.html</link>
        <guid isPermaLink="true">/languages/naming-conventions-creation.html</guid>
        
        
      </item>
    
      <item>
        <title>Library Design: Naming Conventions – Part 2: Conversion</title>
        <description>&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 18%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th style=&quot;width: 34%&quot;&gt;Code Example&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;to&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;array.toList
int32Value.toFloat64
dictionary.to[Queue]&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;implies a (potentially lossy) conversion of a value&lt;/li&gt;
          &lt;li&gt;result type might use &lt;code&gt;Option&lt;/code&gt; or &lt;code&gt;Result&lt;/code&gt; types to encode failures&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;as&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;int64Value.asFloat64
int64Value.as[Float64]
stringBuffer.asByteBuffer
map.asSetOfEntries
setOfEntries.asMap&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;implies a verbatim reinterpretation/wrapping/viewing of a value&lt;/li&gt;
          &lt;li&gt;replacement for numeric &quot;casts&quot;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Wed, 20 Jun 2018 00:00:00 +0000</pubDate>
        <link>/languages/naming-conventions-conversion.html</link>
        <guid isPermaLink="true">/languages/naming-conventions-conversion.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Use Consistent Keyword Length</title>
        <description>&lt;p&gt;&lt;strong&gt;6 letters&lt;/strong&gt; namespacing – declaring and managing namespaces:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;module&lt;/code&gt; (unifies “object” and “package”)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5 letters&lt;/strong&gt; “big” definitions (types):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; (reference type)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; (value type, alternative to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;union&lt;/code&gt; (alternative to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trait&lt;/code&gt; (interface/typeclass)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alias&lt;/code&gt; (type alias)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mixin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4 letters&lt;/strong&gt; control flow:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;when&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt; (alternative to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;while&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;skip&lt;/code&gt; (alternative to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exit&lt;/code&gt; (alternative to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yeet&lt;/code&gt; (alternative to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throw&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3 letters&lt;/strong&gt; “small” definitions (members):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fun&lt;/code&gt; (function)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt; (immutable binding)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var&lt;/code&gt; (mutable binding)&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;Unused alternatives:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6 letters&lt;/strong&gt; “invasive” control flow:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;throws&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2 letters&lt;/strong&gt; control flow:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;or&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 07 Sep 2018 00:00:00 +0000</pubDate>
        <link>/languages/consistent-keyword-length.html</link>
        <guid isPermaLink="true">/languages/consistent-keyword-length.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Comparing and Sorting</title>
        <description>&lt;p&gt;Similarly to &lt;a href=&quot;equality-and-identity-part1&quot;&gt;equality and identity&lt;/a&gt;, most languages have severely restricted facilities to handle distinct ordering relationships like comparison and sorting.&lt;/p&gt;

&lt;p&gt;Languages usually provide only a single operation/protocol, often requiring workarounds for some data types in which the comparison operation and the sorting operation return distinct results.&lt;/p&gt;

&lt;p&gt;Consider the following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Comparable&lt;/code&gt; trait as it frequently exists across many languages
(like &lt;a href=&quot;https://hackage.haskell.org/package/base-4.16.1.0/docs/Data-Ord.html&quot;&gt;Haskell&lt;/a&gt;,
&lt;a href=&quot;https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html&quot;&gt;Rust&lt;/a&gt;,
&lt;a href=&quot;https://developer.apple.com/documentation/swift/comparable&quot;&gt;Swift&lt;/a&gt;, …):&lt;/p&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Comparable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bool&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bool&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… and an IEEE754-conformant comparison implementation for floating point values,
i. e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-0.0 &amp;lt; +0.0&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float.NaN &amp;lt; Float.PositiveInfinity&lt;/code&gt; are both false.&lt;/p&gt;

&lt;p&gt;As it becomes obvious, such an implementation of &lt;em&gt;partial order&lt;/em&gt; can be used to &lt;em&gt;compare&lt;/em&gt; values,
but cannot be used to correctly &lt;em&gt;sort&lt;/em&gt; values (&lt;em&gt;total order&lt;/em&gt;).&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The reason is that the implementation of &lt;em&gt;comparison operations&lt;/em&gt; for floating point values (a partial order, IEEE754 §5.11)
cannot be used as a stand-in for &lt;em&gt;sorting&lt;/em&gt; operations on floating point values.&lt;/p&gt;

&lt;p&gt;Conveniently, IEEE754 standardizes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;totalOrder&lt;/code&gt; relation in §5.10, defining how floating point numbers are sorted.
The only requirement language-wise is to introduce a distinct trait&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; which represents &lt;em&gt;total ordering&lt;/em&gt;,
enabling a clean separation of &lt;em&gt;comparison operations&lt;/em&gt; from &lt;em&gt;sorting operations&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Sortable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sortsBefore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bool&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sortsAfter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bool&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This enables the use of each individual trait for its specific purpose, without conflating different concerns:&lt;/p&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;example&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comparing&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Comparable&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;compareReversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Comparable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;example&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sorting&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Sortable&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Sortable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sortsBefore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;See also &lt;a href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4367.html#Floating&quot;&gt;Comparison in C++&lt;/a&gt;. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Rust is a good example of a language suffering from the problems caused by intermingling &lt;a href=&quot;https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html&quot;&gt;&lt;em&gt;partial order&lt;/em&gt;&lt;/a&gt; with &lt;a href=&quot;https://doc.rust-lang.org/std/cmp/trait.Ord.html&quot;&gt;&lt;em&gt;total order&lt;/em&gt;&lt;/a&gt;. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 31 Oct 2018 00:00:00 +0000</pubDate>
        <link>/languages/comparing-and-sorting.html</link>
        <guid isPermaLink="true">/languages/comparing-and-sorting.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Equality &amp; Identity – Part 4: Fixing Haskell</title>
        <description>&lt;p&gt;Basic goals, as mentioned in the previous parts:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You should not lose values inside a data structure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is the simple example again, demonstrating the issue:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;elem (0.0/0.0) [0.0/0.0] -- False
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To be clear, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elem&lt;/code&gt; is picked as the simplest example possible.&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h4 id=&quot;status-quo&quot;&gt;Status Quo&lt;/h4&gt;

&lt;p&gt;Why is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt; not doing its job, or rather – what is its job description in the first place?
According to &lt;a href=&quot;https://hackage.haskell.org/package/base-4.16.1.0/docs/Data-Eq.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Data.Eq&lt;/code&gt;&lt;/a&gt;, not much:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The Haskell Report defines no laws for Eq. However, instances are encouraged to follow these properties: […]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why does &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt; provide no laws, compared to many other typeclasses that state them strongly and explicitly?&lt;/p&gt;

&lt;p&gt;The reason becomes obvious if one scrolls though the list of typeclass instances.
If the “encouraged properties” were upgraded to “laws”,
Haskell would have law-breaking typeclass instances in one of its most central modules.&lt;/p&gt;

&lt;p&gt;The fault of Haskell’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt; is that it lives in a world in which there is only a single definition of equality per type, which is incorrect in general. Case in point: floating point numbers, which have multiple definitions (see IEE754 §5.10 and §5.11).&lt;/p&gt;

&lt;p&gt;There can be multiple useful definitions of equality per type, and – depending on the use-case – having only one to pick is not sufficient.
Even simple functions like list’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elem&lt;/code&gt; might require both equality and identity operations to work correctly,
which means the frequently suggested newtype hack to swap one implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt; for another one is insufficient.&lt;/p&gt;

&lt;h4 id=&quot;available-options&quot;&gt;Available Options&lt;/h4&gt;

&lt;p&gt;The key point is that only two of the three properties can be satisfied:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;correct data structures&lt;/li&gt;
  &lt;li&gt;abstraction/polymorphism&lt;/li&gt;
  &lt;li&gt;a single “universal” equality function&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The status quo is discarding property &lt;em&gt;1.&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Data structures which lose values, example: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elem (0.0/0.0) [0.0/0.0]&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Polymorphic data structures like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&lt;/code&gt;s and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vector&lt;/code&gt;s.&lt;/li&gt;
  &lt;li&gt;A single equality function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Discarding property &lt;em&gt;2.&lt;/em&gt; would give you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;(Some) correctly working data structures, example: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elem (0.0/0.0) someFloatList&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Specialized data structures like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FloatList&lt;/code&gt;s or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DoubleVector&lt;/code&gt;s (likely in addition to polymorphic variants), which implement functions like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elem&lt;/code&gt; using both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; and functions specific to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float&lt;/code&gt;s or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Double&lt;/code&gt;s. Semantics would differ between polymorphic and specialized variants.&lt;/li&gt;
  &lt;li&gt;A single equality function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt;, and type-specific functions in specialized data structures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Discarding property &lt;em&gt;3.&lt;/em&gt; would give you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Correctly working data structures, example: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elem (0.0/0.0) [0.0/0.0]&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Polymorphic data structures like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;List&lt;/code&gt;s and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vector&lt;/code&gt;s.&lt;/li&gt;
  &lt;li&gt;An identity function (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;===&lt;/code&gt;), in addition to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt;s existing equality function (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;Here is how the last approach can be implemented:&lt;/p&gt;

&lt;h4 id=&quot;a-solution&quot;&gt;A Solution&lt;/h4&gt;

&lt;p&gt;The simplest fix (instead of introducing a new typeclass for identity) is to extend &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt; as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class  Eq a  where
  (==), (/=), (===), (/==) :: a -&amp;gt; a -&amp;gt; Bool

  x ==  y              = not (x /= y)
  x /=  y              = not (x == y)
  x === y              = x == y         -- new
  x /== y              = not (x === y)  -- new
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nothing would change for 99% of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt;’s instances, but the typeclass instances for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Double&lt;/code&gt;, … would now be defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;instance Eq Float where
  (==)  = eqFloat
  (===) = Numeric.IEEE.identicalIEEE  -- new
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then change the documentation replacing the “expected properties” of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/=&lt;/code&gt; with “laws” of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;===&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/==&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As a last exercise, adjust usages of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x == y&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x == y || x === y&lt;/code&gt; where appropriate (e. g. list’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elem&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;And there you have it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;strong assurances instead of “it would be nice”&lt;/li&gt;
  &lt;li&gt;lawful instances where there were none before&lt;/li&gt;
  &lt;li&gt;more reliable behavior of data structures&lt;/li&gt;
  &lt;li&gt;no need to spin new types for things which should work out-of-the-box, because deriving &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt; &lt;em&gt;just works&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Even arguing that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt; is the correct result of the code example does not detract from the points being made, as there are plenty of other examples. Taking &lt;a href=&quot;/languages/comparing-and-sorting.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ord&lt;/code&gt;’s issues&lt;/a&gt; into account, which are very similar, would add even more examples. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 14 Mar 2019 00:00:00 +0000</pubDate>
        <link>/languages/equality-and-identity-fixing-haskell.html</link>
        <guid isPermaLink="true">/languages/equality-and-identity-fixing-haskell.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Binary Operators are Overused</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Use methods.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Many languages provide binary operators, usually for operations on numbers (addition, multiplication),
bits (shifts) and boolean values. In general, this language facility has been overused, forcing users
to learn and recall precedence and associativity of dozens of operators.&lt;/p&gt;

&lt;p&gt;Additionally, some popular operators have additional problems:&lt;/p&gt;

&lt;h3 id=&quot;the-problem-with-&quot;&gt;The problem with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Many older language that were influenced by C also inherited its &lt;a href=&quot;https://ericlippert.com/2020/02/27/hundred-year-mistakes/&quot;&gt;incorrect operator precedence&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Newer languages like Go or Swift avoided copying this mistake.&lt;/p&gt;

&lt;h3 id=&quot;the-problem-with---&quot;&gt;The problem with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;lt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Languages (like Java or JavaScript) that decided against providing both signed and unsigned number types often offer
two operators for shifting bits to the right: one that preserves the sign bit and one that doesn’t.&lt;/p&gt;

&lt;p&gt;The operators in question – &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; – don’t indicate their respective semantics, forcing users
to remember the rules.&lt;/p&gt;

&lt;h3 id=&quot;the-problem-with--1&quot;&gt;The problem with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;&lt;/h3&gt;

&lt;h4 id=&quot;in-most-languages-the--operator-implements-a-remainder-operation-not-a-modulo-operation&quot;&gt;In most languages the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt; operator implements a remainder operation, not a modulo operation&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;remainder&lt;/em&gt;: has the same sign as the dividend&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;modulo&lt;/em&gt;: has the same sign as the divisor&lt;/li&gt;
&lt;/ul&gt;

&lt;table class=&quot;table-medium table-width-small&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt; &lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;remainder&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;modulo&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+4 % +3&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;-4 % +3&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;+4 % -3&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;-4 % -3&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;there-are-multiple-possible-implementations-of-remainder-and-modulo-with-no-clear-winner&quot;&gt;There are multiple possible implementations of remainder and modulo, with no clear winner&lt;/h4&gt;

&lt;p&gt;At least five approaches are known&lt;sup id=&quot;fnref:leijen&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:leijen&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:boute&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:boute&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Remainder of truncated division&lt;/li&gt;
  &lt;li&gt;Remainder of floored division&lt;/li&gt;
  &lt;li&gt;Remainder of ceiling division&lt;/li&gt;
  &lt;li&gt;Remainder of euclidean division&lt;/li&gt;
  &lt;li&gt;Remainder of rounded division&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;a-sensible-small-set-of-operators&quot;&gt;A sensible, small set of operators&lt;/h3&gt;

&lt;table class=&quot;table-medium table-layout-auto&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Precedence level&lt;/th&gt;
      &lt;th&gt;Operator&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Assignment&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;2&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;&amp;#124;&amp;#124;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Boolean Or&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Boolean And&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;4&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!=&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;=&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;=&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;===&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!==&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Comparisons&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;5&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;, &lt;code&gt;&amp;#124;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Addition, Subtraction, Bitwise Or, Bitwise Xor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;6&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Multiplication, Division, Bitwise And&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:leijen&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf&quot;&gt;Division and Modulus for Computer Scientists&lt;/a&gt; &lt;a href=&quot;#fnref:leijen&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:boute&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://dl.acm.org/doi/pdf/10.1145/128861.128862&quot;&gt;The Euclidean Definition of the Functions div and mod&lt;/a&gt; &lt;a href=&quot;#fnref:boute&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 21 Sep 2019 00:00:00 +0000</pubDate>
        <link>/languages/binary-operators-are-overused.html</link>
        <guid isPermaLink="true">/languages/binary-operators-are-overused.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Unary Operators are Unnecessary</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Unary operators are a waste of a language’s complexity budget. Replace them with methods.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Many languages provide unary prefix operators – symbols placed in front of the value they apply to – such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;: Logical complement (on booleans)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt;: Bitwise complement (on numbers)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;: Numeric complement (on numbers)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;: useless (on numbers)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;Except for reasons of tradition and familiarity, their privileged position in many languages is unnecessary.&lt;br /&gt;
They provide rather limited benefits – while adding complexity to the core language.&lt;/p&gt;

&lt;p&gt;An alternative is to define methods on the respective types, dropping unary operators altogether:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not&lt;/code&gt; replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; on booleans: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;someBool.not&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!someBool&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;not&lt;/code&gt; replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; on integers: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.not&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;negate&lt;/code&gt; replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt; on numbers: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.negate&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;There are three benefits to replace unary prefix operators with methods:&lt;/p&gt;

&lt;h5 id=&quot;it-moves-the-negation-closer-to-the-thing-being-negated&quot;&gt;It moves the negation closer to the thing being negated&lt;/h5&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if language.users.map(_.lastName).contains(&quot;Smith&quot;).not then ... else ...&lt;/code&gt; can be read from the left to the right, while
   the more traditional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if !language.users.map(_.lastName).contains(&quot;Smith&quot;) then ... else ...&lt;/code&gt;
   requires users to read the negation first, then read the condition to the end of the line to figure out what is being negated.&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h5 id=&quot;it-allows-the-use-of-more-elaborate-result-types&quot;&gt;It allows the use of more elaborate result types&lt;/h5&gt;

&lt;p&gt;While a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;negate&lt;/code&gt; operation may always succeed on arbitrary-precision numbers (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BigInt&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BigDec&lt;/code&gt;, …),
the same operation on the more common fixed-size types (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Long&lt;/code&gt;, …) could benefit from returning an optional
result to indicate that a negative value may lack a positive counterpart.&lt;/p&gt;

&lt;h5 id=&quot;it-is-completely-unambiguous&quot;&gt;It is completely unambiguous&lt;/h5&gt;

&lt;p&gt;Code mixing unary prefix operators with other operations can be confusing to readers,
for instance whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-1.abs&lt;/code&gt; evaluates to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-1&lt;/code&gt;, and if the precedence only
applies to literals or also code like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let x = 1; -x.abs&lt;/code&gt;.&lt;br /&gt;
With methods, the code is unambiguous: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.negate.abs&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;appendix&quot;&gt;Appendix&lt;/h4&gt;

&lt;p&gt;Incomplete list of languages and their interpretation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-1.abs&lt;/code&gt;:&lt;/p&gt;

&lt;table class=&quot;table-medium table-width-small&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt; &lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;-1.abs&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;let x = 1; -x.abs&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;C#&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Core&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;D&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Dart&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Fantom&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Groovy&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Kitten&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;n.a.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;JavaScript&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Nim&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Raku&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Ruby&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Rust&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Scala&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;Smalltalk&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;n.a.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The Rust community had a similar &lt;a href=&quot;https://internals.rust-lang.org/t/the-is-not-empty-method-as-more-clearly-alternative-for-is-empty/&quot;&gt;discussion&lt;/a&gt; about this topic. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 21 Sep 2019 00:00:00 +0000</pubDate>
        <link>/languages/unary-operators-are-unnecessary.html</link>
        <guid isPermaLink="true">/languages/unary-operators-are-unnecessary.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Unified Condition Expressions – Implementation</title>
        <description>&lt;p&gt;As a first approximation – especially if an existing language shall be adapted –
it makes sense to build a feature-reduced version of unified condition expressions
using a different keyword, in parallel to existing syntax.&lt;/p&gt;

&lt;p&gt;After unified condition expressions have gained sufficient maturity and functionality,
they can then be switched over to the “real” keyword, old implementations of ternary operators,
switch-cases or if-expressions can be removed and their uses migrated to unified condition expressions.&lt;/p&gt;

&lt;h5 id=&quot;level-1-basics&quot;&gt;Level 1: Basics&lt;/h5&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;individual&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;condition&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragment&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;john&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jane&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From a semantic point of view, the crucial requirement is that the common
fragment is only evaluated once during execution.&lt;/p&gt;

&lt;p&gt;This means that during typechecking, the combined expression of the common
fragment with each individual branch has to be taken into account, but the
common fragment has to be retained until code-generation.&lt;/p&gt;

&lt;h5 id=&quot;level-2-pattern-matching&quot;&gt;Level 2: Pattern Matching&lt;/h5&gt;

&lt;p&gt;The core insight is that pattern matching occurs either always (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt;&amp;amp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt;&amp;amp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt;) or never
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;&amp;amp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt;&amp;amp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;&amp;amp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;) with “legacy” approaches.&lt;/p&gt;

&lt;p&gt;With unified condition expressions, this choice can be made for each branch individually, using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is&lt;/code&gt; keyword:&lt;/p&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;john&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;_,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;paternn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;no&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;match&lt;/span&gt; 
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;level-3-bindings&quot;&gt;Level 3: Bindings&lt;/h5&gt;

&lt;p&gt;The main design task is picking a convention/rule that decides whether an identifier inside a pattern match introduces a
new binding with that name, or refers to an existing binding of that name in scope.&lt;/p&gt;

&lt;p&gt;Possible design options include …&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;… using a keyword or symbol (for instance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt;) to introduce bindings in patterns:&lt;/p&gt;

    &lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refers&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`age`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defined&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;earlier&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;john&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;     &lt;span class=&quot;s2&quot;&gt;&quot;miller&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;introduces&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jane&apos;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jane&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;… using a keyword or symbol (for instance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;) to reference existing bindings in scope:&lt;/p&gt;

    &lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`$`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refers&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`age`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defined&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;earlier&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;john&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;miller&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;$age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;introduces&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jane&apos;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jane&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;… using casing rules to distinguish bindings from references:&lt;/p&gt;

    &lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Age&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uppercase&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;refers&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`Age`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defined&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;earlier&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;john&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;miller&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lowercase&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;introduce&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binding&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jane&apos;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; 
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jane&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&quot;optional-partial-conditions&quot;&gt;Optional: Partial Conditions&lt;/h5&gt;

&lt;p&gt;The notion of the condition’s common fragment can be made more flexible:&lt;/p&gt;

&lt;p&gt;The common fragment can be partial; i. e. the common fragment may not be a valid expression on its own:&lt;/p&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;common&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;condition&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragment&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;john&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jane&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The challenge here is how such code can be expressed best in the AST.&lt;/p&gt;

&lt;h5 id=&quot;optional-indentation-based-syntax&quot;&gt;Optional: Indentation-based syntax&lt;/h5&gt;

&lt;p&gt;Introducing an indentation-based syntax allows dropping &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...&lt;/code&gt; from the unified condition syntax
without introducing problems in other places.&lt;/p&gt;

&lt;p&gt;Similarly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt; could be replaced with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;then&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;no&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;needed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicate&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;common&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;condition&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragment&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;john&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;`&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;jane&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 21 Sep 2019 00:00:00 +0000</pubDate>
        <link>/languages/unified-condition-expressions-implementation.html</link>
        <guid isPermaLink="true">/languages/unified-condition-expressions-implementation.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Modern and Minimal</title>
        <description>&lt;ol&gt;
  &lt;li&gt;A smaller language, not a bigger one
    &lt;ul&gt;
      &lt;li&gt;namespaces: types, terms, &lt;del&gt;packages&lt;/del&gt;, &lt;del&gt;fields&lt;/del&gt;, &lt;del&gt;methods&lt;/del&gt;, &lt;del&gt;labels&lt;/del&gt;&lt;/li&gt;
      &lt;li&gt;modifiers: &lt;del&gt;keywords&lt;/del&gt;, &lt;a href=&quot;annotations-obsolete-modifiers&quot;&gt;annotations&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;nesting: &lt;del&gt;packages&lt;/del&gt;, modules, &lt;del&gt;static&lt;/del&gt;&lt;/li&gt;
      &lt;li&gt;members: &lt;a href=&quot;fields-methods-properties-pick-two&quot;&gt;fields, methods, &lt;del&gt;properties&lt;/del&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;control flow: &lt;a href=&quot;unified-condition-expressions&quot;&gt;if-then-else&lt;/a&gt;, return, while, &lt;del&gt;break&lt;/del&gt;, &lt;del&gt;continue&lt;/del&gt;, &lt;del&gt;loop&lt;/del&gt;, &lt;del&gt;exceptions&lt;/del&gt;, &lt;del&gt;throw&lt;/del&gt;, &lt;del&gt;catch&lt;/del&gt;&lt;/li&gt;
      &lt;li&gt;constructors: primary, &lt;del&gt;secondary&lt;/del&gt;&lt;/li&gt;
      &lt;li&gt;literals: &lt;del&gt;octal number literals&lt;/del&gt;, &lt;del&gt;class literals&lt;/del&gt;, …&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Correctness
    &lt;ul&gt;
      &lt;li&gt;separate types for &lt;a href=&quot;equality-and-identity-part1&quot;&gt;identity/equality&lt;/a&gt;, &lt;a href=&quot;comparing-and-sorting&quot;&gt;ordering/comparing&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Fewer special-cases, not more
    &lt;ul&gt;
      &lt;li&gt;operators: &lt;a href=&quot;unary-operators-are-unnecessary&quot;&gt;&lt;del&gt;unary operators&lt;/del&gt;&lt;/a&gt;, &lt;a href=&quot;binary-operators-are-overused&quot;&gt;fewer binary operators&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;del&gt;magic methods on all types&lt;/del&gt;&lt;/li&gt;
      &lt;li&gt;&lt;del&gt;collection literals&lt;/del&gt;, &lt;del&gt;array syntax&lt;/del&gt;&lt;/li&gt;
      &lt;li&gt;&lt;del&gt;instance-of-syntax&lt;/del&gt;, &lt;del&gt;cast-syntax&lt;/del&gt;&lt;/li&gt;
      &lt;li&gt;types have &lt;a href=&quot;against-mixed-cased-type-names&quot;&gt;consistent casing&lt;/a&gt; (uppercase)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Simplicity, not familiarity
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;stop-using-angle-brackets-for-generics&quot;&gt;&lt;del&gt;generics with &amp;lt;&amp;gt;&lt;/del&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;member definition syntax differs only by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fun&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Higher Standards
    &lt;ul&gt;
      &lt;li&gt;simple to specify&lt;/li&gt;
      &lt;li&gt;simple to implement&lt;/li&gt;
      &lt;li&gt;simple to understand&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Tue, 05 Nov 2019 00:00:00 +0000</pubDate>
        <link>/languages/modern-minimal.html</link>
        <guid isPermaLink="true">/languages/modern-minimal.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Stop Using `&lt;&gt;` for Generics</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Use&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; &lt;em&gt;instead of&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; &lt;em&gt;for generics. It will save you a lot of avoidable trouble down the road.&lt;/em&gt;&lt;/p&gt;

&lt;h4 id=&quot;1--is-hard-to-read-for-humans&quot;&gt;1. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; is hard to read for humans&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; are usually already used as comparison and bitshift operators, which (as binary operators)
conform to a completely different grammatical structure compared to their use as brackets.&lt;br /&gt;
This, often in combination with other design mistakes – like the use of both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; for function calls,
or literal syntax to construct lists, sets and maps – leads to a confusing and inconsistent use of brackets in many languages.&lt;/p&gt;

&lt;p&gt;On top of that, imagine a programming font that in which the height of parentheses (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;), curly braces (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt;) or
square brackets (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt;) were capped to the height of a lower-case letter.&lt;br /&gt;
This is of course ridiculous – but exactly what happens with the (ab)use of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; symbols for brackets.&lt;/p&gt;

&lt;h4 id=&quot;2--is-hard-to-parse-for-compilers&quot;&gt;2. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; is hard to parse for compilers&lt;/h4&gt;

&lt;p&gt;Many languages that were created without generics in mind had trouble adding generics later on,
as all pairs of brackets – &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;}&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt; – were already put to use.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;, used in binary operators for comparisons and bitshifts, were usually the only symbols left in the
grammar that are practical to overload with a new, different meaning.&lt;/p&gt;

&lt;p&gt;That’s pretty much the only reason why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; started to be used as generics in the first place.&lt;/p&gt;

&lt;p&gt;Unfortunately, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; for generics caused parsing problems in every language that tried
use them for this purpose, forcing language designers to indulge in various ugly workarounds:&lt;sup id=&quot;fnref:related&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:related&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Java&lt;/em&gt; approached these issues by making the syntax less consistent (before function return types, but after class names)
and limiting where generics can be used (for instance not with statically imported methods).&lt;sup id=&quot;fnref:java&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:java&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;C#&lt;/em&gt; and &lt;em&gt;Kotlin&lt;/em&gt; tried to retain a more consistent syntax by introducing unlimited look-ahead:
Their parsers keep reading input after the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; until a decision can be made.&lt;sup id=&quot;fnref:csharp&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:csharp&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;C++&lt;/em&gt; suffers from a plethora of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt;-related issues.&lt;sup id=&quot;fnref:cpp1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:cpp1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;
The only issue addressed by the C++ committee after decades was the requirement to add spaces to
nested closing generics to allow the compiler to distinguish between the right-shift operator &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&lt;/code&gt;
and the end of a nested generic type definition.&lt;sup id=&quot;fnref:cpp2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:cpp2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; All other issues appear to be unfixable.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Rust&lt;/em&gt; is forced to use the hideous “turbofish” operator &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::&amp;lt;&amp;gt;&lt;/code&gt; to distinguish between the left side of a
comparison and the start of a generic type, introducing syntactic inconsistency between generics in
a type context and generics in a term context:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;cm&quot;&gt;/*or*/&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;cm&quot;&gt;/*or*/&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;a-better-design&quot;&gt;A better design&lt;/h4&gt;

&lt;p&gt;Instead of repeating the mistakes of the past, imagine each bracket has a clearly-defined use:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; &lt;em&gt;encloses&lt;/em&gt; type parameters or type arguments&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; &lt;em&gt;groups&lt;/em&gt; expressions, parameter/argument lists or tuples&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt; &lt;em&gt;sequences&lt;/em&gt; statements or definitions&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt; is only used as a comparison operator, and not misused as a makeshift bracket.&lt;/p&gt;

&lt;p&gt;This substantially simplifies the mental model beginners need to adopt before writing their first program
(&lt;em&gt;”&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; is for values, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; is for types”&lt;/em&gt;), and encourages the elimination of syntactic special cases like collection literals …&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Array(1, 2, 3)         /* instead of */   [ 1, 2, 3 ]
Set(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)     /* instead of */   { &quot;a&quot;, &quot;b&quot;, &quot;c&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… and array indexing in favor of standard function call syntax&lt;sup id=&quot;fnref:nim&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:nim&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;someList.get(0)        /* instead of */   someList[0]
array.set(0, 23.42)    /* instead of */   array[0] = 23.42
map.set(&quot;name&quot;, &quot;Joe&quot;) /* instead of */   map[&quot;name&quot;] = &quot;Joe&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A &lt;a href=&quot;useful-syntax-sugar&quot;&gt;small amount of syntax sugar&lt;/a&gt; can be considered, leading to the following code:&lt;sup id=&quot;fnref:pythonscala&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:pythonscala&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;someList(0)            /* instead of */   someList[0]
array(0) = 23.42       /* instead of */   array[0] = 23.42
map(&quot;name&quot;) = &quot;Joe&quot;    /* instead of */   map[&quot;name&quot;] = &quot;Joe&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;coda&quot;&gt;Coda&lt;/h4&gt;

&lt;p&gt;Thankfully, the number of languages using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; for generics seems to increase lately –
with Scala, Python, and Nim joining Eiffel, which was pretty much the sole user of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; for decades.&lt;/p&gt;

&lt;p&gt;&lt;del&gt;It remains to be seen whether this turns into tidal change similar to the widespread
&lt;a href=&quot;https://soc.me/languages/type-annotations&quot;&gt;adoption of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ident: Type&lt;/code&gt; over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Type ident&lt;/code&gt;&lt;/a&gt; in modern languages.&lt;/del&gt;
&lt;em&gt;With the recent adoption of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; for generics by Go and Carbon this seems to be the likely outcome.&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:related&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://keleshev.com/parsing-ambiguity-type-argument-v-less-than&quot;&gt;Parsing Ambiguity: Type Argument vs. Less Than&lt;/a&gt; is a similar article focusing on some of these issues in more depth. &lt;a href=&quot;#fnref:related&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:java&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Java: The syntax inconsistency is due to the difficulty a compiler would have to tell whether some token stream of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instance&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; is the left side of a comparison (with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; being the “less-than” operator) or the start of a generic type argument within a method call. &lt;a href=&quot;#fnref:java&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:csharp&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;C#: See &lt;a href=&quot;https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf&quot;&gt;ECMA-334, 4th Edition, §9.2.3 – Grammar Ambiguities&lt;/a&gt; &lt;a href=&quot;#fnref:csharp&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:cpp1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;C++: See &lt;a href=&quot;https://stackoverflow.com/questions/7304699/what-are-all-the-syntax-problems-introduced-by-the-usage-of-angle-brackets-in-c&quot;&gt;What are all the syntax problems introduced by the usage of angle brackets in C++ templates?&lt;/a&gt; &lt;a href=&quot;#fnref:cpp1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:cpp2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;C++: See &lt;a href=&quot;https://en.wikipedia.org/wiki/C%2B%2B11#Right_angle_bracket&quot;&gt;Wikipedia – C++11 right angle bracket&lt;/a&gt; &lt;a href=&quot;#fnref:cpp2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:nim&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Nim uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; for generics, but employs &lt;a href=&quot;https://nim-lang.org/docs/manual.html#procedures-method-call-syntax&quot;&gt;a hack to &lt;em&gt;also&lt;/em&gt; use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; for lookup&lt;/a&gt;. &lt;a href=&quot;#fnref:nim&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:pythonscala&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://docs.python.org/3/reference/datamodel.html#object.__getitem__&quot;&gt;Pyt&lt;/a&gt;&lt;a href=&quot;https://docs.python.org/3/reference/datamodel.html#object.__setitem__&quot;&gt;hon&lt;/a&gt; and &lt;a href=&quot;https://otfried.org/scala/apply.html&quot;&gt;Scala&lt;/a&gt; demonstrate that this approach works incredibly well. &lt;a href=&quot;#fnref:pythonscala&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 04 Apr 2020 00:00:00 +0000</pubDate>
        <link>/languages/stop-using-angle-brackets-for-generics.html</link>
        <guid isPermaLink="true">/languages/stop-using-angle-brackets-for-generics.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Popular, but Wrong</title>
        <description>&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; members&lt;/li&gt;
  &lt;li&gt;properties (&lt;a href=&quot;fields-methods-properties-pick-two&quot;&gt;see&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; for generics (&lt;a href=&quot;stop-using-angle-brackets-for-generics&quot;&gt;see&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; for arrays (&lt;a href=&quot;stop-using-angle-brackets-for-generics&quot;&gt;see&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Type ident&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ident: Type&lt;/code&gt; (&lt;a href=&quot;type-annotations&quot;&gt;see&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;having if-then-else &lt;em&gt;and&lt;/em&gt; switch/case &lt;em&gt;and&lt;/em&gt; a ternary operator (&lt;a href=&quot;unified-condition-expressions&quot;&gt;see&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;having both modifiers and annotations (&lt;a href=&quot;annotations-obsolete-modifiers&quot;&gt;see&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;async&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;separate namespaces for methods and fields&lt;/li&gt;
  &lt;li&gt;method overloading&lt;/li&gt;
  &lt;li&gt;namespace declarations doubling as imports&lt;/li&gt;
  &lt;li&gt;special syntax for casting&lt;/li&gt;
  &lt;li&gt;using cast syntax for things that are not casts&lt;/li&gt;
  &lt;li&gt;requiring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; for methods without parameters&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Tue, 20 Oct 2020 00:00:00 +0000</pubDate>
        <link>/languages/popular-but-wrong.html</link>
        <guid isPermaLink="true">/languages/popular-but-wrong.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Four Kinds of Unions</title>
        <description>&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;

&lt;table class=&quot;table-medium table-layout-auto&quot;&gt;
  &lt;tr&gt;
    &lt;th&gt;&lt;/th&gt;
    &lt;th&gt;Syntactic Wrapping&lt;/th&gt;
    &lt;th&gt;No Syntactic Wrapping&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;No Runtime Tags&lt;/th&gt;
    &lt;td&gt;untagged union&lt;br /&gt;(C &lt;i&gt;union&lt;/i&gt;, C++ &lt;i&gt;union&lt;/i&gt;, Rust &lt;i&gt;union&lt;/i&gt;)&lt;/td&gt;
    &lt;td&gt;union type&lt;br /&gt;(TypeScript &lt;i&gt;union type&lt;/i&gt;)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;Runtime Tags&lt;/th&gt;
    &lt;td&gt;discriminated union/tagged union&lt;br /&gt;(Rust &lt;i&gt;enum&lt;/i&gt;, F# &lt;i&gt;discriminated union&lt;/i&gt;)&lt;/td&gt;
    &lt;td&gt;?&lt;br /&gt;(Algol &lt;i&gt;united mode&lt;/i&gt;, Core &lt;i&gt;union&lt;/i&gt;, C# &lt;i&gt;nominal type union&lt;/i&gt;)&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;upper-left-untagged-unions&quot;&gt;Upper Left: Untagged Unions&lt;/h3&gt;

&lt;p&gt;Some languages like C, C++ or Rust provide untagged unions, where the chosen variant has to be specified on creation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;union Pet {
  cat: Cat,
  dog: Dog
}
let pet = Pet { cat: Cat(&quot;Molly&quot;, 9) }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Values of untagged unions do not contain metadata (runtime tags) to distinguish variants
(though such information can be manually included as an additional field).&lt;/p&gt;

&lt;p&gt;This approach usually requires that the expected variant is assumed/asserted when accessing it from the union value.&lt;/p&gt;

&lt;h3 id=&quot;upper-right-union-types&quot;&gt;Upper Right: Union Types&lt;/h3&gt;

&lt;p&gt;Other languages provide union types where the definition of the union type (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pet&lt;/code&gt;)
refers to existing types in scope for its variants (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt;).&lt;sup id=&quot;fnref:union-types&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:union-types&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;type Pet = Cat | Dog
let pet: Pet = Cat(&quot;Molly&quot;, 9)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A value of such a union does not contain metadata (runtime tags) to tell its variants apart.&lt;/p&gt;

&lt;h3 id=&quot;lower-left-discriminated-unions&quot;&gt;Lower Left: Discriminated Unions&lt;/h3&gt;

&lt;p&gt;A “traditional” discriminated union definition as it exists in various languages defines both the enum itself
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pet&lt;/code&gt;), as well as its variants (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt;).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;enum Pet {
  Cat(name: String, lives: Int),
  Dog(name: String, age: Int)
}
let pet: Pet = Cat(&quot;Molly&quot;, 9)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A discriminated union value contains a tag to allow telling its variants apart – even in cases where the types are them same (such as in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result[String, String]&lt;/code&gt;).&lt;/p&gt;

&lt;h3 id=&quot;lower-right-&quot;&gt;Lower Right: ?&lt;/h3&gt;

&lt;p&gt;The combination of unions with runtime tag but without syntactic wrapping has existed in various languages,
though no common, language-spanning name has been established for this concept.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/ALGOL_68#struct,_union_&amp;amp;_[:]:_Structures,_unions_and_arrays&quot;&gt;“United modes”&lt;/a&gt; in Algol 68:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;STRUCT Cat (STRING name, INT lives);
STRUCT Dog (STRING name, INT years);
MODE Pet = UNION (Cat, Dog);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://core-lang.dev/overview.html#language-21&quot;&gt;Unions&lt;/a&gt; in &lt;a href=&quot;https://core-lang.dev/&quot;&gt;core&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Cat(name: String, lives: Int)
class Dog(name: String, years: Int)
union Pet of Cat, Dog
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/dotnet/csharplang/issues/9662&quot;&gt;“Nominal union types”&lt;/a&gt; as proposed for C# 15:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public record Cat(string Name, long lives);
public record Dog(string Name, long years);
public union Pet(Cat, Dog);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All these define a union &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pet&lt;/code&gt; that refers to &lt;em&gt;existing types&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cat&lt;/code&gt; can be directly assigned to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pet&lt;/code&gt; (of union type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pet&lt;/code&gt;) – without syntactic wrapping:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// core
let pet: Pet = Cat(&quot;Molly&quot;, 9)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Intuitively, this works similarly to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permits&lt;/code&gt; clauses of &lt;a href=&quot;https://docs.oracle.com/en/java/javase/17/language/sealed-classes-and-interfaces.html&quot;&gt;&lt;em&gt;sealed interfaces&lt;/em&gt; in Java&lt;/a&gt; in the sense that&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sealed interface Pet permits Cat, Dog { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;does not define &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cat&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt;, but refers to existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt; types in scope.&lt;sup id=&quot;fnref:sealed&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:sealed&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h4 id=&quot;benefits-of-such-unions&quot;&gt;Benefits of such unions&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Union variants have types, because they have a “real” class/struct/… declaration.&lt;br /&gt;
(This fixes a mistake that some languages like Rust or Haskell made with their enum/data types.&lt;sup id=&quot;fnref:enum-variants-1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:enum-variants-1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:enum-variants-2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:enum-variants-2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;)&lt;/li&gt;
  &lt;li&gt;Variants can be reference types or value types (as they refer to “real” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; definitions).&lt;/li&gt;
  &lt;li&gt;No “stutter”, where variant names have to be invented to wrap existing types. (Rust has this issue.)&lt;/li&gt;
  &lt;li&gt;Union values can be passed/created more easily, as no syntactic wrapping is required.&lt;/li&gt;
  &lt;li&gt;Variants can be re-used in different unions.&lt;/li&gt;
  &lt;li&gt;The ability to build ad-hoc unions out of existing types obviates the need for a separate type alias feature.&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h5 id=&quot;example-for-1-2-3&quot;&gt;Example for 1., 2., 3.&lt;/h5&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;enum Option[T] { Some(value: T), None }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… would receive little benefit from being written as …&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;union Option[T] of Some[T], None
value Some[T](value: T)
module None
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…, but even trivial types like a JSON representation would benefit.&lt;/p&gt;

&lt;p&gt;Instead of …&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;enum JsonValue {
  JsonObject(Map[String, JsonValue])
  JsonArray (Array[JsonValue]),
  JsonString(String),
  JsonNumber(Float64),
  JsonBool  (Bool),
  JsonNull,
  ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… one would write (with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Float64&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt; being existing types in the language):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;union JsonValue of
  Map[String, JsonValue]
  Array[JsonValue],
  String,
  Float64
  Bool,
  JsonNull,
  ...

module JsonNull
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;example-for-4&quot;&gt;Example for 4.&lt;/h5&gt;

&lt;p&gt;No wrapping required when passing arguments (unlike “traditional” enum approaches):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fun someValue(value: JsonValue) = ...
someValue(JsonString(&quot;test&quot;)) // &quot;traditional&quot; approach
someValue(&quot;test&quot;)             // proposed union design
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;example-for-5&quot;&gt;Example for 5.&lt;/h5&gt;

&lt;p&gt;Consider this class definition:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Name(name: String)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the proposed union design, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Name&lt;/code&gt; can be used multiple times – in different unions (and elsewhere):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;union PersonIdentifier of
  Name,
  ... // other identifiers like TaxId, Description, PhoneNumber etc.

union DogTag of
  Name,
  ... // other identifiers like RegId, ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;This kind of union design reduce indirection at use-sites and can be used in more scenarios (compared to more “traditional” enums),
while not changing their runtime costs or representation.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:union-types&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type Num = Int | Int&lt;/code&gt; does not allow detecting whether an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt; instance is the first or the second variant; the definition is equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type Num = Int&lt;/code&gt; &lt;a href=&quot;#fnref:union-types&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:sealed&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Unlike sealed interfaces in Java though, in the proposed union design &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dog&lt;/code&gt; are not subtypes of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pet&lt;/code&gt;. &lt;a href=&quot;#fnref:sealed&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:enum-variants-1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/1450&quot;&gt;Types for enum variants&lt;/a&gt; &lt;a href=&quot;#fnref:enum-variants-1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:enum-variants-2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/rust-lang/rfcs/pull/2593&quot;&gt;Enum variant types&lt;/a&gt; &lt;a href=&quot;#fnref:enum-variants-2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 26 Aug 2021 00:00:00 +0000</pubDate>
        <link>/languages/unions.html</link>
        <guid isPermaLink="true">/languages/unions.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Annotations Obsolete Modifiers</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; If your language has annotations&lt;sup id=&quot;fnref:attributes&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:attributes&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, it doesn’t need modifiers. Drop modifiers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Modifiers&lt;/em&gt; (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abstract&lt;/code&gt;) were traditionally built into languages;
as keywords, they were part of the core language syntax.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Annotations&lt;/em&gt; (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@deprecated&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@test&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@derive&lt;/code&gt;) are usually defined in libraries; similar to a class or interface,
there exists a source file that defines each annotation.&lt;/p&gt;

&lt;h4 id=&quot;motivating-example&quot;&gt;Motivating Example&lt;/h4&gt;

&lt;p&gt;Consider this code example containing a variety of annotations – some of which would have been modifiers in older languages:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@open&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@deprecatedOpen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stop extending this class!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.2&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@derive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Stringable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// a person can be converted to a string&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int32&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@final&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isAdult&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@deprecated&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;use `!isAdult` instead&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isKid&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@inline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ALWAYS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;$firstName $lastName&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;benefits&quot;&gt;Benefits&lt;/h4&gt;

&lt;h5 id=&quot;increased-language-hygiene&quot;&gt;Increased language hygiene&lt;/h5&gt;

&lt;p&gt;Dropping modifiers and only using annotations avoids having two language constructs (modifiers and annotations) that
serve largely the same purpose: refining the semantics of language building blocks like type or function definitions.&lt;/p&gt;

&lt;p&gt;This also obviates having to think which behaviors deserve (or need) to be modifiers and which can exist as an annotation “only”.&lt;/p&gt;

&lt;h5 id=&quot;improved-compatibility-through-namespacing&quot;&gt;Improved compatibility through namespacing&lt;/h5&gt;

&lt;p&gt;As annotations are defined as code in regular source files, they are namespaced.&lt;/p&gt;

&lt;p&gt;This means that – unlike keywords that exist “globally”&lt;sup id=&quot;fnref:contextual&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:contextual&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; – introducing a new annotation does not break existing code.&lt;/p&gt;

&lt;h5 id=&quot;more-accessible-documentation&quot;&gt;More accessible documentation&lt;/h5&gt;

&lt;p&gt;Annotations are defined in source code and live as regular source files of the language, which makes them much easier
for authors to document:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/** a class marked with this annotation allows inheritance, such that ... **/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;annotation&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;open&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Annotation documentation is also much easier for users to discovers, as regular IDE actions like “jump to definition”
or “show documentation” just work due to a presence of a source file.&lt;/p&gt;

&lt;h5 id=&quot;paths-for-language-evolution--migration&quot;&gt;Paths for language evolution &amp;amp; migration&lt;/h5&gt;

&lt;p&gt;Annotations are easier to evolve than modifiers. Example: the implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@private&lt;/code&gt; visibility had a bug?
Fix it, then add a default parameter to the annotation, such that developers can opt into the old behavior:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;-- annotation private
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;++ annotation private(check = Strict) // Strict fixes bug
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;
...
&lt;span class=&quot;gd&quot;&gt;-- @private
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;++ @private(Lenient) // fix this later
&lt;/span&gt;   fun foo ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For larger changes, it is also possible to leverage the namespaced nature of annotations:&lt;/p&gt;

&lt;p&gt;An older language version may import its annotations from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lang.v1&lt;/code&gt; namespace, while a newer language version might
use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lang.v2&lt;/code&gt; namespace in which the behavior of some annotations has changed.&lt;/p&gt;

&lt;p&gt;This preserves the semantics of existing compiled artifacts and allow mixing new and old artifacts.&lt;/p&gt;

&lt;h5 id=&quot;language-future-proofing&quot;&gt;Language future-proofing&lt;/h5&gt;

&lt;p&gt;Even if the language compiler/runtime makes a distinction between “language-powered” annotations (that originated as
modifiers) and user-supplied annotations, putting modifiers and annotations on equal footing syntactically allows
extension of their capabilities later on, for instance by carefully exposing compiler APIs for annotations to hook into.&lt;/p&gt;

&lt;h4 id=&quot;drawbacks&quot;&gt;Drawbacks&lt;/h4&gt;

&lt;h5 id=&quot;harder-bootstrapping&quot;&gt;Harder bootstrapping&lt;/h5&gt;

&lt;p&gt;Bootstrapping the language and the compiler requires more attention:&lt;/p&gt;

&lt;p&gt;As annotations crucial to language semantics have an immediate effect on the interpretation of source code
(such as “static”-ness, or the visibility of types and members), handling annotations as early as possible in the
compilation pipeline is important.&lt;/p&gt;

&lt;p&gt;Introducing a keyword to define annotations (e. g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;annotation&lt;/code&gt;, similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; for classes or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trait&lt;/code&gt; for traits)
is strongly recommended.&lt;sup id=&quot;fnref:scala-annotations&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:scala-annotations&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h5 id=&quot;high-syntax-requirements&quot;&gt;High syntax requirements&lt;/h5&gt;

&lt;p&gt;Lightweight use-site syntax (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt;) is required, as even moderate syntax costs (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[...]&lt;/code&gt; in Rust) may feel “too much” for
its intended use as a replacement for modifier syntax.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:attributes&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Some languages like C, C++, C# and Rust use the name “attribute” for annotations. &lt;a href=&quot;#fnref:attributes&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:contextual&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Except “contextual” keywords, that are only considered keywords in certain contexts (and identifiers in all other places). &lt;a href=&quot;#fnref:contextual&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:scala-annotations&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;As a cautionary tale, annotations in Scala were classes that implemented &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala.annotation.Annotation&lt;/code&gt;, forcing the compiler to traverse and resolve the parent types of a type definition to determine whether some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class&lt;/code&gt; was actually an annotation. &lt;a href=&quot;#fnref:scala-annotations&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 15 Dec 2021 00:00:00 +0000</pubDate>
        <link>/languages/annotations-obsolete-modifiers.html</link>
        <guid isPermaLink="true">/languages/annotations-obsolete-modifiers.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Annotations Obsolete Modifiers – Failed Attempts</title>
        <description>&lt;h4 id=&quot;kotlin&quot;&gt;Kotlin&lt;/h4&gt;

&lt;p&gt;Kotlin &lt;a href=&quot;https://blog.jetbrains.com/kotlin/2015/08/modifiers-vs-annotations/&quot;&gt;gave up on it&lt;/a&gt;, as they couldn’t figure out
how to recognize annotation usages as early in the compiler pipeline as modifiers previously.&lt;/p&gt;

&lt;p&gt;This lead to the determination that modifiers (without the prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt;) had to stay, but annotations would not always be
able to omit the prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt;, leading to inconsistencies.&lt;/p&gt;

&lt;h4 id=&quot;ceylon&quot;&gt;Ceylon&lt;/h4&gt;

&lt;p&gt;Ceylon tried the route in which &lt;a href=&quot;https://ceylon-lang.org/documentation/1.3/reference/structure/annotation/&quot;&gt;everything is an annotation, but looks like a modifier (i. e. without prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt;)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This made it hard to distinguish between important keywords, and less important annotations.&lt;/p&gt;
</description>
        <pubDate>Wed, 15 Dec 2021 12:00:00 +0000</pubDate>
        <link>/languages/annotations-obsolete-modifiers-attempts.html</link>
        <guid isPermaLink="true">/languages/annotations-obsolete-modifiers-attempts.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Against Mixed-cased Type Names</title>
        <description>&lt;p&gt;There is no good reason¹ why some type names need to start with a lower-case letter (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;float&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;str&lt;/code&gt;, …)
and others with an upper-case letter (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BigInt&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt;, …).&lt;/p&gt;

&lt;p&gt;Instead: Pick one naming rule, and stick to it while building your language.&lt;/p&gt;

&lt;hr /&gt;

&lt;h4 id=&quot;stupid-reasons&quot;&gt;¹Stupid Reasons&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;familiarity&quot;&gt;fAmiLiAriTy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;But types with lower-cased names are “primitives”!!1!&lt;/li&gt;
  &lt;li&gt;Akkkchually, they aren’t lower-cased type names, they are keywords for types!&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Sun, 05 Jun 2022 10:00:00 +0000</pubDate>
        <link>/languages/against-mixed-cased-type-names.html</link>
        <guid isPermaLink="true">/languages/against-mixed-cased-type-names.html</guid>
        
        
      </item>
    
      <item>
        <title>Library Design: Naming Conventions – Part 4: Lookup</title>
        <description>&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 18%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th style=&quot;width: 34%&quot;&gt;Code Example&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;–&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(12.3, 45.6)(0)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Some(12.3)&lt;/span&gt;
Map(&quot;key&quot;, &quot;val&quot;)(&quot;key&quot;)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Some(&quot;val&quot;)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;retrieves the value at the given index/key&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;at(idx)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Array(12.3, 45.6).at(1)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Some(Ref(arr, 1))&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;returns a reference to the given position in the array&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;contains(val)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1.0, -0.0, NaN).contains(0.0)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; true&lt;/span&gt;
List(1.0, -0.0, NaN).contains(NaN)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; true&lt;/span&gt;
Map(&quot;key&quot;, &quot;val&quot;).contains(&quot;key&quot;)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; true&lt;/span&gt;
&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;checks whether container contains a value, as determined by either equality (&lt;code&gt;==&lt;/code&gt;) or identity (&lt;code&gt;===&lt;/code&gt;)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;includes(val)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1.0, -0.0, NaN).includes(0.0)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; true&lt;/span&gt;
List(1.0, -0.0, NaN).includes(NaN)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; false&lt;/span&gt;
Map(&quot;key&quot;, &quot;val&quot;).includes(&quot;key&quot;)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; true&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;checks whether container includes a value, as determined by equality (&lt;code&gt;==&lt;/code&gt;)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;has(val)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1.0, -0.0, NaN).has(0.0)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; false&lt;/span&gt;
List(1.0, -0.0, NaN).has(NaN)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; true&lt;/span&gt;
Map(&quot;key&quot;, &quot;val&quot;).includes(&quot;key&quot;)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; true&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;checks whether container has a value, as determined by identity (&lt;code&gt;===&lt;/code&gt;)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;findFirst(pred)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(3, 1, 2, 3).findFirst(_ &amp;lt; 3)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Some(1)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;find first value in container that satisfies the provided predicate&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;findLast(pred)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(3, 1, 2, 3).findLast(_ &amp;lt; 3)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Some(2)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        &lt;ul&gt;
          &lt;li&gt;find last value in container that satisfies the provided predicate&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Tue, 07 Jun 2022 00:00:00 +0000</pubDate>
        <link>/languages/naming-conventions-lookup.html</link>
        <guid isPermaLink="true">/languages/naming-conventions-lookup.html</guid>
        
        
      </item>
    
      <item>
        <title>Library Design: Naming Conventions – Part 5: Streaming</title>
        <description>&lt;h4 id=&quot;projections&quot;&gt;Projections&lt;/h4&gt;

&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 20%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th style=&quot;width: 34%&quot;&gt;Code Example&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;map(&amp;lt;fun&amp;gt;)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3).map(_ + 1)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(2, 3, 4)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream in which &lt;code&gt;fun&lt;/code&gt; is applied to each element.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;mapMany(&amp;lt;fun&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;mapMulti&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;flatMap&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;mapFlat&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;mapAndFlatten&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2).mapMany(x -&amp;gt; List(x, x))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(1, 1, 2, 2)&lt;/span&gt;

List(1, 2).mapMany(x -&amp;gt; Some(x))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(1, 2)&lt;/span&gt;
List(1, 2).mapMany(x -&amp;gt; None)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List()&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream in which &lt;code&gt;fun&lt;/code&gt; is applied to each element, producing a sequence of elements that is subsequently flattened.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;filters&quot;&gt;Filters&lt;/h4&gt;

&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 20%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th style=&quot;width: 34%&quot;&gt;Code Example&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;first&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3).first
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Option(1)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns the first element of the stream.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;last&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3).last
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Option(3)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns the last element of the stream.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;retainFirst(&amp;lt;num&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;take&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;keep&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;pick&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3, 4).retainFirst(2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(1, 2)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream that produces the first &lt;code&gt;num&lt;/code&gt; elements of the input stream.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;retain(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;accept&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;select&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;filter&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3, 1).retain(_ &amp;lt; 2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(1, 2, 1)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        Returns a stream that produces only elements for which &lt;code&gt;pred&lt;/code&gt; evaluates to &lt;code&gt;true&lt;/code&gt;.&lt;br /&gt;
        Alternatives considered:
        &lt;ul&gt;
          &lt;li&gt;&lt;code&gt;filter&lt;/code&gt; is a poor name as it&apos;s unclear (especially for non-native speakers) whether &quot;filtered elements&quot; are those retained, or those &quot;filtered out&quot;.&lt;/li&gt;
          &lt;li&gt;&lt;code&gt;accept&lt;/code&gt; is not ideal, as the visitor pattern also makes use of this name.&lt;/li&gt;
          &lt;li&gt;&lt;code&gt;select&lt;/code&gt; is even less ideal, as SQL uses the name for a completely different purpose.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;retainIndex(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;).retainIndex(_ % 2 == 0)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(&quot;a&quot;, &quot;c&quot;)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream that produces only elements for which &lt;code&gt;pred&lt;/code&gt; evaluates to &lt;code&gt;true&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;retainWhile(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;takeWhile&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;keepWhile&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;pickWhile&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3, 1).retainWhile(_ &amp;lt; 3)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(1, 2)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream that produces elements of the input stream until the &lt;code&gt;pred&lt;/code&gt; evaluates to &lt;code&gt;false&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;retainUntil(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;takeUntil&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;keepUntil&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;pickUntil&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(4, 3, 2, 4).retainUntil(_ &amp;lt; 3)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(4, 3)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        Returns a stream that produces elements of the input stream until the &lt;code&gt;pred&lt;/code&gt; evaluates to &lt;code&gt;true&lt;/code&gt;.
        &lt;ul&gt;
          &lt;li&gt;Redundant, equivalent to &lt;code&gt;retainWhile(pred.not)&lt;/code&gt;.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;rejectFirst(&amp;lt;num&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;skip&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;drop&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3, 4).rejectFirst(1)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(2, 3, 4)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream without the first &lt;code&gt;num&lt;/code&gt; elements of the input stream.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;reject(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;filterNot&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3, 1).reject(_ &amp;lt; 2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(3)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        Returns a stream that produces only elements for which &lt;code&gt;pred&lt;/code&gt; evaluates to &lt;code&gt;false&lt;/code&gt;.&lt;br /&gt;
        Alternatives considered:
        &lt;ul&gt;
          &lt;li&gt;&lt;code&gt;filterNot&lt;/code&gt; is a poor name as it&apos;s unclear (especially for non-native speakers) whether &quot;filtered elements&quot; are those retained, or those &quot;filtered out&quot;.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;rejectIndex(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;).rejectIndex(_ % 2 == 0)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(&quot;b&quot;)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream that produces only elements for which &lt;code&gt;pred&lt;/code&gt; evaluates to &lt;code&gt;false&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;rejectWhile(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;skipWhile&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;dropWhile&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(2, 3, 4, 1).rejectWhile(_ &amp;lt; 2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(3, 4, 1)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream that skips elements of the input stream until &lt;code&gt;pred&lt;/code&gt; evaluates to &lt;code&gt;false&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;rejectUntil(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;skipUntil&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;dropUntil&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(3, 2, 1, 4).rejectUntil(_ &amp;lt; 2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(1, 4)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;
        Returns a stream that skips elements of the input stream until &lt;code&gt;pred&lt;/code&gt; evaluates to &lt;code&gt;true&lt;/code&gt;.&lt;br /&gt;
        Alternatives considered:
        &lt;ul&gt; 
          &lt;li&gt;Redundant, equivalent to &lt;code&gt;rejectWhile(pred.not)&lt;/code&gt;.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;distinct&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1, 2, 3, 1).distinct
&lt;span class=&quot;result&quot;&gt;--&amp;gt; List(1, 2, 3)&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream that produces only the first occurrence of elements occurring multiple times.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;folds&quot;&gt;Folds&lt;/h4&gt;

&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 20%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th style=&quot;width: 34%&quot;&gt;Code Example&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;fold(&amp;lt;num&amp;gt;, &amp;lt;start&amp;gt;)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;reduce(&amp;lt;fun&amp;gt;)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;combine[Monoid]&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;sum[Numeric]&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1.0, 2.0, 3.0, 4.0).sum
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 10.0&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Computes the sum of the list of numbers.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;product[Numeric]&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1.0, 2.0, 3.0, 4.0).product
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 24.0&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Computes the product of the list of numbers.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;average[Numeric]&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;List(1.0, 2.0, 3.0, 4.0).average
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 2.5&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;Computes the average of the list of numbers.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;all(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;forAll&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;Returns &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;pred&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt; for all elements.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;any(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;forAny&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;Returns &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;pred&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt; for any element.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;p&gt;&lt;code&gt;none(&amp;lt;pred&amp;gt;)&lt;/code&gt;&lt;/p&gt;&lt;p class=&quot;obsolete&quot;&gt;&lt;s&gt;&lt;code&gt;forNone&lt;/code&gt;&lt;/s&gt;&lt;/p&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;Returns &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;pred&lt;/code&gt; returns &lt;code&gt;false&lt;/code&gt; for all elements.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;injects&quot;&gt;Injects&lt;/h4&gt;

&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 20%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th style=&quot;width: 34%&quot;&gt;Code Example&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;joinInner[Record]&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;joinLeft[Record]&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;joinRight[Record]&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;joinFull[Record]&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;groupBy(&amp;lt;fun&amp;gt;)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;partitionBy(&amp;lt;fun&amp;gt;)&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;fan-ins&quot;&gt;Fan-Ins&lt;/h4&gt;

&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 20%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th style=&quot;width: 34%&quot;&gt;Code Example&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;concat&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream that produces the values from the first stream and then the values of the second stream.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;interleave&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;
        Returns a stream that produces a value, alternating between the first and second stream.
        &lt;ul&gt;
          &lt;li&gt;Likely requires multiple method variants that handle streams of different lengths in different ways.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;zip&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;
        Returns a stream that produces a tuple value, where the first element is from the first stream and the second element is from the second stream.
        &lt;ul&gt;
          &lt;li&gt;Likely requires multiple method variants that handle streams of different lengths in different ways.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;zipWithIndex&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;&lt;/td&gt;
      &lt;td&gt;Returns a stream that produces a tuple value, where the first element is from the stream and the second element is the index at which the value was produced.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Wed, 08 Jun 2022 00:00:00 +0000</pubDate>
        <link>/languages/naming-conventions-streaming.html</link>
        <guid isPermaLink="true">/languages/naming-conventions-streaming.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Equality &amp; Identity – Part 6: Fixing Rust</title>
        <description>&lt;p&gt;Rust designers recognized the issues with Haskell’s approach, but were not able to address the issues with Rust’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PartialEq&lt;/code&gt; traits.&lt;/p&gt;

&lt;p&gt;The main cause of this failure is the sub-typing relationship between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PartialEq&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;It requires that an implementation of partial order is consistent with an implementation of total order.&lt;/p&gt;

&lt;p&gt;This works for many types, but not for floating point types, for which the IEEE754 standard specifies a partial order as
well as a total order.&lt;/p&gt;

&lt;p&gt;The easiest solution for Rust would have been to not introduce the sub-typing relationship between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PartialEq&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt;
(as well as between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PartialOrd&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ord&lt;/code&gt;).&lt;/p&gt;
</description>
        <pubDate>Thu, 09 Jun 2022 00:00:00 +0000</pubDate>
        <link>/languages/equality-and-identity-fixing-rust.html</link>
        <guid isPermaLink="true">/languages/equality-and-identity-fixing-rust.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Familiarity – Familiarity is a tie-breaker, not a self-sufficient argument</title>
        <description>&lt;p&gt;In the past, many languages did not pick up easily adoptable language design improvements and opted
for familiarity instead, often in a misguided attempt to keep perceived language complexity down.&lt;/p&gt;

&lt;p&gt;Examples include&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;C’s broken operator precedence&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; spread to many other languages, most of whom have little in common with C.&lt;/li&gt;
  &lt;li&gt;C++’s use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; for generics, which was adopted by languages that – unlike C++ – had better options available.&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;C#’s design of properties, picked up by languages that did not suffer from C#’s legacy of fields and methods.&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;
The benefits of familiarity (“it is easy, because I have seen it before”) are limited to those who
“have seen it before”, while the benefits of simplicity (“it is easy, because it was designed this way”)
apply to everyone, regardless of experience, schooling or development history.&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Therefore, it’s best to treat familiarity as a tie-breaker: to be used sparingly, only when the
pros and cons of different design options have been fully explored, and it has been determined that
no design has an edge above the other.&lt;/p&gt;

&lt;p&gt;But if one design has arguments for it, and another design has only familiarity on its side,
language designers of the future are implored to pick the former to stop propagating the same
language design mistakes further and further into the future.&lt;sup id=&quot;fnref:6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;see also &lt;a href=&quot;popular-but-wrong&quot;&gt;Popular, but Wrong&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;see &lt;a href=&quot;https://ericlippert.com/2020/02/27/hundred-year-mistakes/&quot;&gt;Hundred year mistakes&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;see &lt;a href=&quot;stop-using-angle-brackets-for-generics&quot;&gt;Stop Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt; for Generics&lt;/a&gt; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;see &lt;a href=&quot;fields-methods-properties-pick-two&quot;&gt;Fields &amp;amp; Methods &amp;amp; Properties? – Pick Two!&lt;/a&gt; &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;confusing them is an easy, but dangerous mistake to make, &lt;a href=&quot;https://steveklabnik.com/writing/the-language-strangeness-budget&quot;&gt;example&lt;/a&gt; &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The target audience of this footnote probably hasn’t made it this far before losing their mind, but to clarify: Nobody is planning on making you code in GIMP, all I’m saying is that some language decisions made in the 1970ies (with little thought on design) could &lt;em&gt;perhaps&lt;/em&gt; benefit from some scrutiny before copying them into new languages verbatim. &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 10 Jun 2022 00:00:00 +0000</pubDate>
        <link>/languages/familiarity.html</link>
        <guid isPermaLink="true">/languages/familiarity.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Fields &amp; Methods &amp; Properties? – Pick Two!</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Properties are a hack employed to retrofit “nice” syntax into languages that already shipped with fields and methods. Instead, design the language to deliver the same (or more) benefits with fields!&lt;/em&gt;&lt;/p&gt;

&lt;h4 id=&quot;why-do-properties-exist&quot;&gt;Why do properties exist?&lt;/h4&gt;

&lt;p&gt;The core feature of properties, in rough terms, is that (unlike getters and setters) property invocations look like field access,
but retain the possibility to add logic that is executed on access at a later date (unlike fields).&lt;/p&gt;

&lt;h4 id=&quot;examples-of-languages-with-properties&quot;&gt;Examples of Languages with properties&lt;/h4&gt;

&lt;h5 id=&quot;c&quot;&gt;C#&lt;/h5&gt;

&lt;p&gt;C# popularized properties when it shipped them in version 1, and extended their feature set in subsequent versions
(&lt;em&gt;auto-implemented properties&lt;/em&gt; in C# 3, &lt;em&gt;initializers&lt;/em&gt; in C# 6, &lt;em&gt;expression-bodied members&lt;/em&gt; in C# 7).&lt;/p&gt;

&lt;div class=&quot;language-c# highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This means that – instead of e. g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;person.getFirstName()&lt;/code&gt; – users can write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;person.firstName&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In C#, this is not perfect: changing a field to a property is source compatible, but not binary compatible;
and changing a getter/setter pair to a property is neither.&lt;/p&gt;

&lt;h5 id=&quot;kotlin&quot;&gt;Kotlin&lt;/h5&gt;

&lt;p&gt;TODO: fields vs. properties vs. methods&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;poorly copied from C#&lt;/li&gt;
  &lt;li&gt;large regression from Scala&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;swift&quot;&gt;Swift&lt;/h5&gt;

&lt;p&gt;TODO: stored properties vs. computed properties vs. methods&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;slightly better syntax than C#&lt;/li&gt;
  &lt;li&gt;still a large language complexity footprint&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;the-problem-with-properties&quot;&gt;The problem with properties&lt;/h4&gt;

&lt;p&gt;Conceptually, it’s a bit icky that languages feature three constructs to define members that fundamentally only express
two categories: members that store (“fields”) and members that compute (“methods”).&lt;/p&gt;

&lt;p&gt;All three (fields, methods, properties) compete for the same syntactic sweet-spot and pollute the mental model –
as they can be thin wrappers around their storage (“auto-implemented properties” in C#, “stored properties” in Swift),
or contain complex custom logic (non-“auto-implemented properties” in C#, “computed properties” in Swift).&lt;/p&gt;

&lt;h4 id=&quot;which-desirable-characteristics-should-fieldsmethodsproperties-language-provide&quot;&gt;Which desirable characteristics should fields/methods/properties language provide?&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;“Nice” syntax at use- and declaration-site.&lt;/li&gt;
  &lt;li&gt;Evolving access should be source- and binary-compatible.&lt;/li&gt;
  &lt;li&gt;Users should be able to see whether they are accessing a value directly, or whether computation will occur during access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;how-to-deliver-these-characteristics-without-needing-fields-methods-and-properties&quot;&gt;How to deliver these characteristics without needing fields, methods &lt;em&gt;and&lt;/em&gt; properties?&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Use keyword-based syntax to distinguish between fields and methods.
    &lt;ul&gt;
      &lt;li&gt;This means that methods without parameters do not need to require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; to distinguish them from fields.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Define that members live in the same namespace.
    &lt;ul&gt;
      &lt;li&gt;This prohibits a type containing a field and a method with the same name.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Implement late(-enough) binding of member invocations.
    &lt;ul&gt;
      &lt;li&gt;This avoids encoding field/method invocation differences into call sites.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Expose the difference between a field and a method invocation through the use of colors in the IDE.
    &lt;ul&gt;
      &lt;li&gt;This preserves important information (compared to properties or explicit getter/setter calls).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;how-to-replace-property-getters-with-fields-and-methods&quot;&gt;How to replace property getters with fields and methods?&lt;/h4&gt;

&lt;p&gt;Consider a class definition with one field (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt;) and two methods (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firstName&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastName&lt;/code&gt;) …&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Person(let name: String)
  fun firstName: String = this.name.split(&quot; &quot;).get(0)
  fun lastName:  String = this.name.split(&quot; &quot;).get(1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… and its usage:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let person = Person(&quot;Jane Doe&quot;)
person.name       // &quot;Jane Doe&quot;
person.firstName  // &quot;Jane&quot;
person.lastName   // &quot;Doe&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As a mental model, a desugared encoding of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt; value could look like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Person(name: String)
  @private
  let _name: String = name
  fun name: String = self._name
  ... /* other methods, as in the last example */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt; class definition was now changed to contain two fields and one method …&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Person(let firstName: String, let lastName: String)
  fun name: String = this.firstName + &quot; &quot; + this.lastName
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… code using the class should not require changes, except adjusting the constructor call:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let person = Person(&quot;Jane&quot;, &quot;Doe&quot;)
person.name       // &quot;Jane Doe&quot;
person.firstName  // &quot;Jane&quot;
person.lastName   // &quot;Doe&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Still, users of the class can see what’s happening when they access &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Person&lt;/code&gt;’s members,
because the IDE can use different colors to mark fields (keyword &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let&lt;/code&gt;) and methods (keyword &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fun&lt;/code&gt;).&lt;/p&gt;

&lt;h4 id=&quot;how-to-replace-property-setters-with-fields-and-methods&quot;&gt;How to replace property setters with fields and methods?&lt;/h4&gt;

&lt;p&gt;While mutability is on its way out, and the benefits of this approach are less pronounced for property setters,
let’s review an example that demonstrates how property setters can also be replaced with fields and functions:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Wine(let name: String, var rating: In64)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As a mental model, a desugared encoding of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Wine&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rating&lt;/code&gt; variable could look like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Wine(let name: String, rating: Int64)
  @private
  var _rating: Int64 = rating
  fun rating: Int64 = self._rating
  fun setRating(newRating: Int64) = self._rating = newRating
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Instead of a special property syntax like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set;&lt;/code&gt; or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@setter(&quot;rating&quot;)&lt;/code&gt; annotation,
it’s possible to define some slight syntactic sugar for methods starting with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.setY(z)&lt;/code&gt; can be written as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.y = z&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is very similar to the desugaring rules used for &lt;a href=&quot;stop-using-angle-brackets-for-generics#3-it-allows--to-be-abused-for-syntax-conveniences&quot;&gt;indexing operations&lt;/a&gt;
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.get(y)&lt;/code&gt; can be written as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x(y)&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.set(y, z)&lt;/code&gt; can be written as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x(y) = z&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;It is used like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let wine = Wine(&quot;Schatoh-la Fid&quot;, 96)
wine.rating       // 96
wine.rating = 97  /* same as `wine.setRating(97)` */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To add additional checks when setting a new value (which is a popular use-case for property setters),
we explicitly define a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRating&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Wine(let name: String, var rating: Int64)
  fun setRating(newRating: Int64) =
    require(newRating &amp;gt;= 0 &amp;amp;&amp;amp; newRating &amp;lt;= 100, s&quot;rating must be between 0 and 100, but was $newRating&quot;)
    self.rating = newRating
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is used like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let wine = Wine(&quot;Schatoh-la Fid&quot;, 96)
wine.rating       // 96
wine.rating = 97
wine.rating = -1  /* fails */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But now we realize, that – to protect our new invariant – we also want to run this check on construction,
so we refactor:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Wine(let name: String, var rating: Int64)
  checkRating(rating)

  @override
  fun setRating(newRating: Int64) =
    checkRating(newRating)
    this.rating = newRating

  fun checkRating(newRating: Int64) =
    require(newRating &amp;gt;= 0 &amp;amp;&amp;amp; newRating &amp;lt;= 100, s&quot;rating must be between 0 and 100, but was $newRating&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At this point, the use of (property) setters becomes questionable, as more mutable members mean more
checks that we need to be called at all the right places. Instead, consider this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;value Rating(let value: Int64)
  require(value &amp;gt;= 0 &amp;amp;&amp;amp; value &amp;lt;= 100, s&quot;rating must be between 0 and 100, but was $value&quot;)

class Wine(let name: String, var rating: Rating)

let wine = Wine(&quot;Schatoh-la Fid&quot;, Rating(96))
wine.rating               // Rating(96)
wine.rating = Rating(97)
wine.rating = Rating(-1)  /* fails */
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This preserves the simplicity of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Wine&lt;/code&gt; class definition, and moves the verification of the rating
to its own type, making it easier to ensure all invariants are preserved.&lt;/p&gt;

&lt;h4 id=&quot;what-about-method-references&quot;&gt;What about method references?&lt;/h4&gt;

&lt;p&gt;Allowing method definitions/invocation without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; poses the question of “how to handle method references?”.&lt;/p&gt;

&lt;p&gt;There are three options:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Type inference&lt;/p&gt;

    &lt;p&gt;The meaning of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;person.firstName&lt;/code&gt; depends on the expected type, i. e.&lt;/p&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; fun foo(s: String) = ...
 foo(person.firstName)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;evaluates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;person.firstName&lt;/code&gt;, while&lt;/p&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; fun bar(f: () =&amp;gt; String) = ...
 bar(person.firstName)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;passes a method reference to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar&lt;/code&gt;.
 This approach likely requires picking one choice as a default if there is no expected type,
 as well as type annotations if the type is ambiguous.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Explicit lambda syntax&lt;/p&gt;

    &lt;p&gt;Instead of dealing with type inference and ambiguity, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;person.firstName&lt;/code&gt; could be specified to always evaluate,
 requiring the use of a lambda for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar&lt;/code&gt;.&lt;/p&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; fun bar(f: () =&amp;gt; String) = ...
 bar(() =&amp;gt; person.firstName)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Reference syntax&lt;/p&gt;

    &lt;p&gt;Special syntax could be introduced to create references from methods:&lt;/p&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; fun bar(f: () =&amp;gt; String) = ...
 bar(person::firstName)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;This approach is especially interesting if the language has other program elements for which a “reference” syntax
 could also be beneficial, as it could replace special constructs like Java’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String.class&lt;/code&gt; or C#’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;typeof(String)&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;coda&quot;&gt;Coda&lt;/h4&gt;

&lt;p&gt;With this design, we have accomplished more than languages with properties,
while also avoiding the complexity of having fields &lt;em&gt;and&lt;/em&gt; methods &lt;em&gt;and&lt;/em&gt; properties.&lt;/p&gt;
</description>
        <pubDate>Thu, 07 Jul 2022 00:00:00 +0000</pubDate>
        <link>/languages/fields-methods-properties-pick-two.html</link>
        <guid isPermaLink="true">/languages/fields-methods-properties-pick-two.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: The Cost of Everything</title>
        <description>&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Merit Points&lt;/th&gt;
      &lt;th&gt;Item&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-100&lt;/td&gt;
      &lt;td&gt;Adding a language feature to do something that can already be done&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-90&lt;/td&gt;
      &lt;td&gt;Adding a language feature to do something that can be implemented in a library&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-80&lt;/td&gt;
      &lt;td&gt;Adding a language feature to do something that can be achieved by fixing a compiler bug&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-70&lt;/td&gt;
      &lt;td&gt;Adding a new element to the global namespace&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-60&lt;/td&gt;
      &lt;td&gt;Adding a new element to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;util&lt;/code&gt; namespace&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;-20&lt;/td&gt;
      &lt;td&gt;Adding a new element to the standard library&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Thu, 07 Jul 2022 11:00:00 +0000</pubDate>
        <link>/languages/the-cost-of-everything.html</link>
        <guid isPermaLink="true">/languages/the-cost-of-everything.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Useful Syntax Sugar</title>
        <description>&lt;h4 id=&quot;get-sugar&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt; sugar&lt;/h4&gt;

&lt;h5 id=&quot;rule&quot;&gt;Rule&lt;/h5&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.get(y)&lt;/code&gt; can be written as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x(y)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5 id=&quot;explanation&quot;&gt;Explanation&lt;/h5&gt;

&lt;p&gt;Instead of special-purpose syntax that is used for indexing operations (reading) in many languages, like&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;someArray&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;one can write&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let firstValue = someArray(0)
/* same as */
let firstValue = someArray.get(0)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;assuming a definition like&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Array[T]
  fun get(idx: Int64): T = ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;In combination with varargs, it can also replace special-purpose syntax used to construct various data structures.&lt;/p&gt;

&lt;p&gt;Instead of e. g.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;someArray&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;one can write&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let someArray = Array(1, 2, 3)
/* same as */
let someArray = Array.get(1, 2, 3)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;assuming a definition like&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module Array
  fun get[T](vals: T*): Array[T] = ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;Of course &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt; is just one example; this rule applies to other data structures and use-cases equally:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let countriesAndCapitals =
  Map(&quot;France&quot; -&amp;gt; &quot;Paris&quot;, &quot;Germany&quot; -&amp;gt; &quot;Berlin&quot;, ...)
countriesAndCapitals(&quot;France&quot;) // &quot;Paris&quot;

let baroqueComposers = Set(&quot;Bach&quot;, &quot;Händel&quot;, &quot;Vivaldi&quot;, ...)
baroqueComposers(&quot;Rammstein&quot;)  // false 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;set-sugar&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt; sugar&lt;/h4&gt;

&lt;h5 id=&quot;rule-1&quot;&gt;Rule&lt;/h5&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.set(y, z)&lt;/code&gt; can be written as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x(y) = z&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5 id=&quot;explanation-1&quot;&gt;Explanation&lt;/h5&gt;

&lt;p&gt;Instead of special-purpose syntax that is used for indexing operations (writing) in many languages, like&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;someArray&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;one can write&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;someArray(0) = 23
/* same as */
someArray.set(0, 23)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;assuming a definition like&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Array[T]
  fun set(idx: Int64, val: T): Unit = ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;Of course &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt; is just one example; this rule applies to other data structures and use-cases equally:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let countriesAndCapitals =
  Map(&quot;France&quot; -&amp;gt; &quot;Paris&quot;, &quot;Germany&quot; -&amp;gt; &quot;Berlin&quot;, ...)
countriesAndCapitals(&quot;England&quot;) = &quot;London&quot; // new entry added

let baroqueComposers = Set(&quot;Bach&quot;, &quot;Händel&quot;, &quot;Vivaldi&quot;, ...)
baroqueComposers(&quot;Monteverdi&quot;) = true      // new entry added
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;set-sugar-1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set...&lt;/code&gt; sugar&lt;/h4&gt;

&lt;h5 id=&quot;rule-2&quot;&gt;Rule&lt;/h5&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.setY(z)&lt;/code&gt; can be written as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x.y = z&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h5 id=&quot;explanation-2&quot;&gt;Explanation&lt;/h5&gt;

&lt;p&gt;Instead of special-purpose syntax for properties and their setters, like&lt;/p&gt;

&lt;div class=&quot;language-c# highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rating&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;someRating&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;97&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;one can keep writing&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;someRating.value = 97
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;assuming a definition like&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct Rating(var value: Int32)
  fun setValue(val: Int32) = ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;but does not have to pay the complexity cost of adding properties to the language.&lt;/p&gt;
</description>
        <pubDate>Sun, 10 Jul 2022 00:00:00 +0000</pubDate>
        <link>/languages/useful-syntax-sugar.html</link>
        <guid isPermaLink="true">/languages/useful-syntax-sugar.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Schemas as Source Code</title>
        <description>&lt;p&gt;TLD;DR: Your compiler should treat schema definitions as a valid (alternate) source syntax of your programming language.&lt;/p&gt;

&lt;h2 id=&quot;whats-the-goal&quot;&gt;What’s the goal&lt;/h2&gt;

&lt;h2 id=&quot;failed-alternatives&quot;&gt;Failed Alternatives&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;poorly integrated source generation&lt;/li&gt;
  &lt;li&gt;compiler plugins&lt;/li&gt;
  &lt;li&gt;macros/type providers&lt;/li&gt;
  &lt;li&gt;annotating program texts&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 06 Aug 2022 00:00:00 +0000</pubDate>
        <link>/languages/schema-as-source-code.html</link>
        <guid isPermaLink="true">/languages/schema-as-source-code.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Typing Terminology</title>
        <description>&lt;blockquote&gt;
  &lt;p&gt;Most people think only in terms of the dichotomy between Nominal-Manifest-Static-Strong and  Structural-Inferred-Dynamic-Weak
in any given discussion of programming language type system design. And it is exhausting.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(from &lt;a href=&quot;https://old.reddit.com/r/ProgrammingLanguages/comments/weywuw/what_does_strong_and_weak_typing_mean_to_you/&quot;&gt;what does strong and weak typing mean to you&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Most individual distinction are a scale, not a strict yes/no checkbox. (&lt;a href=&quot;https://old.reddit.com/r/ProgrammingLanguages/comments/weywuw/what_does_strong_and_weak_typing_mean_to_you/iir8ns5/&quot;&gt;inspiration&lt;/a&gt;)&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;typed--untyped-typing-modalitypresence&quot;&gt;Typed ⟷ Untyped (Typing Modality/Presence)&lt;/h3&gt;

&lt;p&gt;A typed language allows analysis of the program text and rejection of certain programs, without executing them.
Untyped (sometimes also called “dynamic”) programming languages lack this facility.&lt;/p&gt;

&lt;p&gt;More Static: Haskell, CommonLisp&lt;br /&gt;
More Untyped: SmallTalk, Scheme, JavaScript&lt;/p&gt;

&lt;h3 id=&quot;manifest--inferred-typing-apparency&quot;&gt;Manifest ⟷ Inferred (Typing Apparency)&lt;/h3&gt;

&lt;p&gt;It describes the degree to which types need to mentioned in the program text.&lt;/p&gt;

&lt;p&gt;More Manifest: Java, C&lt;br /&gt;
More Inferred: OCaml, Haskell.&lt;/p&gt;

&lt;h3 id=&quot;nominal--structural-typing-morphology&quot;&gt;Nominal ⟷ Structural (Typing Morphology)&lt;/h3&gt;

&lt;p&gt;It pertains to how types are described and referred to and when they are judged equal.&lt;/p&gt;

&lt;p&gt;More Nominal: Rust, D&lt;br /&gt;
More Structural: Ruby, OCaml.&lt;/p&gt;

&lt;p&gt;→ Mention Java SAM types.&lt;/p&gt;

&lt;h3 id=&quot;reified--erased-typing-preservation&quot;&gt;Reified ⟷ Erased (Typing Preservation)&lt;/h3&gt;

&lt;p&gt;A reified type system means that type information is preserved during compilation and available at run-time.&lt;/p&gt;

&lt;p&gt;This enables runtimes to execute code more effectively and/or allows user-provided code to query type information as
part of the program code.&lt;/p&gt;

&lt;p&gt;Java: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.lang.reflect&lt;/code&gt; package, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object#getClass()&lt;/code&gt;&lt;br /&gt;
C#: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object#GetType()&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;compile-time-vs-run-time-reflection&quot;&gt;Compile-time vs. Run-time Reflection?&lt;/h4&gt;

&lt;p&gt;~~ compile-time: required info is stored at call-site vs. run-time: required info is stored at declaration-site&lt;/p&gt;

&lt;p&gt;Not directly typing related, but typing preservation choices have a direct impact on what’s possible.
(Maybe as sub-point of reified vs. erased?)&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;vv-draft-space-vv&quot;&gt;vv Draft Space vv&lt;/h3&gt;

&lt;h4 id=&quot;untyped-languages&quot;&gt;Untyped Languages&lt;/h4&gt;

&lt;h4 id=&quot;tagged--untagged&quot;&gt;Tagged ⟷ Untagged&lt;/h4&gt;

&lt;hr /&gt;

&lt;p&gt;→ cite Benjamin Pierce
→ cite Bob Harper: https://existentialtype.wordpress.com/2011/03/19/dynamic-languages-are-static-languages/&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Not really typing:&lt;/p&gt;

&lt;h3 id=&quot;strong--weak-typing-disciplinevalue-convertibility&quot;&gt;Strong ⟷ Weak (Typing Discipline/Value Convertibility)&lt;/h3&gt;

&lt;p&gt;which I think should be called Typing discipline because it pertains to the number of type errors you get (compile time or runtime, doesn’t matter.) Stronger: SML, Python, Weaker: JavaScript, C.&lt;/p&gt;
</description>
        <pubDate>Sat, 06 Aug 2022 00:00:00 +0000</pubDate>
        <link>/languages/typing-terminology.html</link>
        <guid isPermaLink="true">/languages/typing-terminology.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: `Result` naming</title>
        <description>&lt;p&gt;I was never too happy with the existing naming approaches for the Result type:&lt;/p&gt;

&lt;h4 id=&quot;successfailure&quot;&gt;Success/Failure&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;pro: both names have the same length, like Option’s Some/None&lt;/li&gt;
  &lt;li&gt;con: quite long, concern that people may use Option over Result&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;okerr&quot;&gt;Ok/Err&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;pro: short&lt;/li&gt;
  &lt;li&gt;con: names don’t have the same length, leading to inconsistent indentation when pattern matching&lt;/li&gt;
  &lt;li&gt;con: Err is not a word&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;The new naming ticks all the boxes:&lt;/p&gt;

&lt;h4 id=&quot;passfail&quot;&gt;Pass/Fail&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;pro: both names have the same length&lt;/li&gt;
  &lt;li&gt;pro: same length as Some/None&lt;/li&gt;
  &lt;li&gt;pro: real words&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a minor thing, but it’s nice to have found a good design even where it doesn’t matter that much!&lt;/p&gt;

&lt;p&gt;The only concern I have is that I might find a type in a testing-related context where Pass/Fail would fit even better!&lt;/p&gt;
</description>
        <pubDate>Mon, 31 Oct 2022 00:00:00 +0000</pubDate>
        <link>/languages/result-naming.html</link>
        <guid isPermaLink="true">/languages/result-naming.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Unified Condition Expressions – Comparison with Rust</title>
        <description>&lt;h5 id=&quot;simple-if-expression&quot;&gt;simple if expression&lt;/h5&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This translates straight-forward to Rust:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;z&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;multiple-cases-equality-relation&quot;&gt;multiple cases, equality relation&lt;/h5&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In Rust, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt; is idiomatic:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;   &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;z&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;multiple-cases-any-other-relation&quot;&gt;multiple cases, any other relation&lt;/h5&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rust requires the use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt; with guards (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt; on its own only supports equality relations), or an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; expression:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;                           &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;                 &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;z&quot;&lt;/span&gt;                             &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;             &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;z&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;multiple-cases-method-calls&quot;&gt;multiple cases, method calls&lt;/h5&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isInfinite&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isNaN&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;z&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In Rust one would use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;match&lt;/code&gt; with guards, or an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; expression:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_infinite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt;          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_infinite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_nan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt;               &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.is_nan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;z&quot;&lt;/span&gt;                             &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;               &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;z&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;if-let-statement&quot;&gt;“if-let”, statement&lt;sup id=&quot;fnref:rust-if-let&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:rust-if-let&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:swift-if-let&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:swift-if-let&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/h5&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt_number&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;`i`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rust requires a special construct to pattern match or introduce bindings:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt_number&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* use `i` */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;if-let-expression&quot;&gt;“if-let”, expression&lt;sup id=&quot;fnref:rust-if-let:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:rust-if-let&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:swift-if-let:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:swift-if-let&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/h5&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt_number&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rust uses the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let-equals-if-let-equals&lt;/code&gt; pattern:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt_number&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;if-let-chains&quot;&gt;“if-let” chains&lt;sup id=&quot;fnref:rust-if-let-chains&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:rust-if-let-chains&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/h5&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;opt_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rust proposes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if-let&lt;/code&gt; chains syntax:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt_number&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;let-else&quot;&gt;“let-else”&lt;sup id=&quot;fnref:rust-let-else&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:rust-let-else&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;sup id=&quot;fnref:swift-guard-let&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:swift-guard-let&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/h5&gt;

&lt;div class=&quot;language-ml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt_number&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;       &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rust’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let-else&lt;/code&gt; allows binding a fallible pattern without introducing nesting:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opt_number&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:rust-if-let&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Rust &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if-let&lt;/code&gt; – https://doc.rust-lang.org/book/second-edition/ch06-03-if-let.html &lt;a href=&quot;#fnref:rust-if-let&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:rust-if-let:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:swift-if-let&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Swift &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if-let&lt;/code&gt; – https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html &lt;a href=&quot;#fnref:swift-if-let&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:swift-if-let:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:rust-if-let-chains&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Rust &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if-let&lt;/code&gt; chains – https://github.com/rust-lang/rust/issues/53667 &lt;a href=&quot;#fnref:rust-if-let-chains&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:rust-let-else&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Rust &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;let-else&lt;/code&gt; – https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#let-else-statements &lt;a href=&quot;#fnref:rust-let-else&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:swift-guard-let&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Swift &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;guard-let&lt;/code&gt; – https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html &lt;a href=&quot;#fnref:swift-guard-let&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 07 Nov 2022 00:00:00 +0000</pubDate>
        <link>/languages/unified-condition-expressions-comparison.html</link>
        <guid isPermaLink="true">/languages/unified-condition-expressions-comparison.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Drop `break` and `continue`</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Optimize for the common case, not the exotic ones.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First of all: The argument is &lt;em&gt;not&lt;/em&gt; that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt; in loops aren’t …&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;useful&lt;/li&gt;
  &lt;li&gt;convenient&lt;/li&gt;
  &lt;li&gt;sometimes the best option&lt;/li&gt;
  &lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s not the argument being made. The argument that &lt;em&gt;is&lt;/em&gt; being made is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt; are …&lt;/p&gt;

&lt;h4 id=&quot;-optimizing-for-an-infrequent-special-case-&quot;&gt;… optimizing for an infrequent special case …&lt;/h4&gt;

&lt;p&gt;Consider a codebase that contains 1000 loops.&lt;/p&gt;

&lt;p&gt;Out of those 1000, 900 loops aren’t using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Of the remaining 100 loops, perhaps 90 loops use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt;, and 10 loops use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Of those 90 loops with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt;s, 80 are easily convertible to equivalent code not using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Of the 10 loops with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt;s maybe 5 are easily convertible.&lt;/p&gt;

&lt;pre class=&quot;diagram&quot;&gt;
.------------------------------------------------.
| all loops                                      |
|                                                |
|                                            +---+
|                                            |   |
|                        loops with break---&amp;gt;|   |
|                                            +---+
|                     loops with continue---&amp;gt;|   |
&apos;--------------------------------------------+---&apos;
&lt;/pre&gt;

&lt;p&gt;This means that out of 1000 loops, supporting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt; focuses on making 1.5% of the loops more convenient,
to the detriment of the other 98.5% of the loops.&lt;/p&gt;

&lt;h4 id=&quot;-while-worsening-the-general-case&quot;&gt;… while worsening the general case!&lt;/h4&gt;

&lt;p&gt;What’s the detriment? The loss of the ability to read the head of the loop and know what’s going on
(e. g. when the loop terminates), as the body of every loop could contain a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;while true { // is it really an endless loop? only way to find out is reading the whole loop body!
  ...
  if shouldBreak() {
    break;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This inability is so ingrained in people, that they cannot fathom the mental load that gets removed
when they do not have to keep “this loop may contain a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt;” in the back of their head:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let continue = true
while continue { // loop head shows immediately when the loop terminates
  ...
  continue = shouldBreak().not
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Dropping &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;continue&lt;/code&gt; removes mental load from 98.5% of the loops that don’t use them,
with the disadvantage that a few loops are now more painful to write.&lt;/p&gt;

&lt;p&gt;That’s a good trade-off.&lt;/p&gt;
</description>
        <pubDate>Sat, 10 Dec 2022 00:00:00 +0000</pubDate>
        <link>/languages/drop-break-and-continue.html</link>
        <guid isPermaLink="true">/languages/drop-break-and-continue.html</guid>
        
        
      </item>
    
      <item>
        <title>Time to wind down Rust feature development</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Regardless on where you stand on the “Rust 2.0”, Rust’s current approach to language evolution is not sustainable.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Whenever a language considers adding a feature, the cost of having to remove the feature (for any reasons)
should be factored in from the start.&lt;/p&gt;

&lt;p&gt;In Rust case, where fixing pretty much any anything after release is close to impossible –
that cost function goes toward infinity.&lt;/p&gt;

&lt;p&gt;Looking at the last few years of feature additions I have issues coming up with a feature whose
benefits are larger than its costs.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;async/await: too early to tell whether it was actually worth it&lt;/li&gt;
  &lt;li&gt;if let: growing extensions proposals at an impressive rate&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 16 Dec 2022 00:00:00 +0000</pubDate>
        <link>/languages/winding-down-rust-feature-development.html</link>
        <guid isPermaLink="true">/languages/winding-down-rust-feature-development.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Rust&apos;s Struct Initializer Syntax Was a Mistake</title>
        <description>&lt;p&gt;Rust has distinct syntactic facilities for …&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;invoking functions&lt;/li&gt;
  &lt;li&gt;initializing structs and enums&lt;/li&gt;
  &lt;li&gt;initializing tupled structs and enums&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;… that provide different affordances and features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;method arguments are positional and cannot be named&lt;/li&gt;
  &lt;li&gt;initializer arguments are named, and what looks like positional arguments is a special shorthand notation&lt;/li&gt;
  &lt;li&gt;initializer arguments for tuple structs and enums look like method arguments, but are initializer arguments without shorthand notation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following example shows all three:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sign_in_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// tuple struct&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;sign_in_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Jane Example&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;jane@example.com&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;the-problems&quot;&gt;The Problems&lt;/h3&gt;

&lt;p&gt;Some of the issues caused by Rust implementing “most features, half the time”:&lt;/p&gt;

&lt;h4 id=&quot;diverging-code-styles-and-best-practices&quot;&gt;Diverging Code Styles and Best Practices&lt;/h4&gt;

&lt;p&gt;The unwieldiness of struct initialization combined with the
&lt;a href=&quot;https://github.com/samsieber/rubber-duck/blob/master/REVIEW.md&quot;&gt;lack of named/default parameters&lt;/a&gt; has lead to diverging
code styles and best practices – like &lt;a href=&quot;https://rust-unofficial.github.io/patterns/idioms/ctor.html&quot;&gt;constructor pattern&lt;/a&gt;,
&lt;a href=&quot;https://www.greyblake.com/blog/builder-pattern-in-rust&quot;&gt;builders&lt;/a&gt;,
&lt;a href=&quot;https://xaeroxe.github.io/init-struct-pattern/&quot;&gt;option structs&lt;/a&gt;,
&lt;a href=&quot;https://github.com/rust-unofficial/patterns/discussions/237&quot;&gt;default hacks&lt;/a&gt;)
– for dealing with issues like “this thing has grown and is taking way too many parameters now”.&lt;/p&gt;

&lt;p&gt;Every future language improvement/addition will change the scale slightly, causing churn due to another technique
becoming the next “best practice”.
(And most likely only apply to either struct/enum initializers &lt;em&gt;or&lt;/em&gt; method calls, but not both.)&lt;/p&gt;

&lt;h4 id=&quot;needless-ambiguity&quot;&gt;Needless Ambiguity&lt;/h4&gt;

&lt;p&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt; for struct initialization also means that something as trivial as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if foo {&lt;/code&gt; appears to be syntactically ambiguous.&lt;/p&gt;

&lt;p&gt;(In Rust such code is always treated as a condition body, a struct initialization in this position would need to be enclosed in parentheses.)&lt;/p&gt;

&lt;h4 id=&quot;lack-of-consistent-rules-for-type-ascriptions&quot;&gt;Lack of Consistent Rules for Type Ascriptions&lt;/h4&gt;

&lt;p&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; for struct initialization means that it’s not possible to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;: Foo&lt;/code&gt; as a type ascription.
Languages from the 70ies managed to get this right, Rust somehow regressed on that, failing to ship
&lt;a href=&quot;https://rust-lang.github.io/rfcs/0803-type-ascription.html&quot;&gt;type ascriptions&lt;/a&gt; and
&lt;a href=&quot;https://rust-lang.github.io/rfcs/3307-de-rfc-type-ascription.html&quot;&gt;giving up on it after 8 years&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;a-solution&quot;&gt;A Solution&lt;/h3&gt;

&lt;p&gt;What Rust should have done instead is to decide upon &lt;em&gt;one&lt;/em&gt; ruleset that all those invocation follow, such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Function calls and struct/enum initializers use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;, not a mix of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; for passing actual values as named arguments, such that everything “just works” if default parameters were added in the future.
(See the &lt;a href=&quot;#appendix-a-detailed-look-at-the-role-of-&quot;&gt;Appendix&lt;/a&gt; for an evaluation of available options.)&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; only for type ascriptions.&lt;/li&gt;
  &lt;li&gt;Shorthand notation or positional arguments? Pick one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adapting the example code from above, the code would look like this:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sign_in_count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;u64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// default parameter value&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// named parameter&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Jane Example&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;jane@example.com&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;appendix-a-detailed-look-at-the-role-of-&quot;&gt;Appendix: A Detailed Look at the Role of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;&lt;/h3&gt;

&lt;h4 id=&quot;how-to-distinguish-between-a-variable-assigment-and-a-named-parameter-use-inside-a-function-invocation&quot;&gt;How to distinguish between a variable assigment and a named parameter use inside a function invocation?&lt;/h4&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;k&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;i64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// what does this mean?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Two points have to be considered here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Reducing chances of mix-ups:
    &lt;ul&gt;
      &lt;li&gt;Frequency: Are variable assignments within function calls or function calls with named parameters projected to be used more often?&lt;/li&gt;
      &lt;li&gt;Intuitivity: How can the syntax be distributed to those two use-cases such that the choice makes intuitively sense from a user point-of-view?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Reducing the harm from mix-ups:
    &lt;ul&gt;
      &lt;li&gt;Can code change meaning unexpectedly, e. g. when function parameters are renamed?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&quot;option-1-try-to-use-the-same-syntax-for-both-variable-assigments-and-named-parameters&quot;&gt;Option 1: Try to use the same syntax for both variable assigments and named parameters&lt;/h5&gt;

&lt;p&gt;This means that named parameters simply act like another scope in which identifiers are looked up.&lt;/p&gt;

&lt;p&gt;The danger with this approach is that changing the name of a named parameter can silently change the meaning of callsites if a variable with the previously used parameter name happens to be in scope.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// named parameter, but if someFunction&apos;s parameter name changes,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// without the callsite being updated, it silently becomes an&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// assignment instead of a compilation failure:&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It also means that variables with the same name as a parameter name cannot be assigned within a function call.&lt;/p&gt;

&lt;h5 id=&quot;option-2-let-variable-assignments-use-the-good-syntax-and-give-named-parameters-some-workaround-syntax&quot;&gt;Option 2: Let variable assignments use the “good” syntax and give named parameters some “workaround” syntax&lt;/h5&gt;

&lt;p&gt;In this example, the workaround syntax for named parameters is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;, prefixed to the parameter name.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// variable assigment inside a function argument list,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// only works if assignment returns the assigned value&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// (which is generally a bad idea):&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// named parameter, and if someFunction&apos;s parameter name changes,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// without the callsite being updated, it becomes a compilation failure:&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;.a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;option-3-let-named-parameters-use-the-good-syntax-and-give-variable-assignments-some-workaround-syntax&quot;&gt;Option 3: Let named parameters use the “good” syntax and give variable assignments some “workaround” syntax&lt;/h5&gt;

&lt;p&gt;Inside a functions argument list, the first level of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; use is always a named parameter and never a
variable assignment, even if some variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; would be in scope.&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// named parameter, and if someFunction&apos;s parameter name changes,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// without the callsite being updated, it becomes a compilation failure:&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// variable assigment inside a function argument list,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// only works if assignment returns the assigned value&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// (which is generally a bad idea):&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 20 Sep 2023 00:00:00 +0000</pubDate>
        <link>/languages/rust-struct-initializer-mistake.html</link>
        <guid isPermaLink="true">/languages/rust-struct-initializer-mistake.html</guid>
        
        
      </item>
    
      <item>
        <title>Library Design: Naming Conventions – Part 3: Option &amp; Result</title>
        <description>&lt;p&gt;Many languages’ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt; types suffer from an organically-grown and therefore inconsistently named set of functions.&lt;/p&gt;

&lt;p&gt;To avoid this, a simple naming scheme can be used to derive a full set of useful methods with predictable names for these types.&lt;/p&gt;

&lt;p&gt;The examples below use variant names &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Some&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option&lt;/code&gt;, and variant names &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pass&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fail&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt;.&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;h4 id=&quot;naming-scheme&quot;&gt;Naming Scheme&lt;/h4&gt;

&lt;p&gt;Given a function operating on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option[T]&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result[T, E]&lt;/code&gt; …&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get...&lt;/code&gt; indicates a result type of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt;,&lt;br /&gt;
its lack indicates a result type of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option[T]&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result[T, E]&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...Else&lt;/code&gt; indicates a closure argument,&lt;br /&gt;
its lack indicates an eagerly evaluated value&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...Panic&lt;/code&gt; indicates a possibly panicking function,&lt;br /&gt;
its lack indicates a total function&lt;/li&gt;
  &lt;li&gt;additional combinator function names are adopted from &lt;a href=&quot;naming-conventions-streaming&quot;&gt;Naming Conventions – Streaming&lt;/a&gt; as appropriate&lt;br /&gt;
where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...None&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...Fail&lt;/code&gt; variants indicate working on the error value instead of on the success value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;table class=&quot;table-medium&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;width: 18%&quot;&gt;Function Name&lt;/th&gt;
      &lt;th&gt;Code Example&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;or&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Some(1).or(Some(2))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Some(1)&lt;/span&gt;
None.or(Some(2))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Some(2)&lt;/span&gt;
Pass(1).or(Pass(2))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Pass(1)&lt;/span&gt;
Fail(1).or(Pass(2))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Pass(2)&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;orElse&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Some(1).orElse(() -&amp;gt; Some(2))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Some(1)&lt;/span&gt;
None.orElse(() -&amp;gt; Some(2))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Some(2)&lt;/span&gt;
None.orElse(() -&amp;gt; None)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; None&lt;/span&gt;
Pass(1).orElse(() -&amp;gt; Pass(2))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Pass(1)&lt;/span&gt;
Fail(1).orElse(() -&amp;gt; Pass(2))
&lt;span class=&quot;result&quot;&gt;--&amp;gt; Pass(2)&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;getOr&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Some(1).getOr(2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 1&lt;/span&gt;
None.getOr(2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 2&lt;/span&gt;
Pass(1).getOr(2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 1&lt;/span&gt;
Fail(1).getOr(2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 2&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;getOrElse&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Some(1).getOrElse(() -&amp;gt; 2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 1&lt;/span&gt;
None.getOrElse(() -&amp;gt; 2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 2&lt;/span&gt;
Pass(1).getOrElse(() -&amp;gt; 2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 1&lt;/span&gt;
Fail(1).getOrElse(() -&amp;gt; 2)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 2&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;getOrPanic&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Some(1).getOrPanic()
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 1&lt;/span&gt;
None.getOrPanic()
&lt;span class=&quot;result&quot;&gt;# program aborts&lt;/span&gt;
Pass(1).getOrPanic()
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 1&lt;/span&gt;
Fail(1).getOrPanic()
&lt;span class=&quot;result&quot;&gt;# program aborts&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;getOrPanicWith&lt;/code&gt;&lt;/td&gt;
      &lt;td class=&quot;code&quot;&gt;Some(1).getOrPanicWith(&quot;expected some&quot;)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 1&lt;/span&gt;
None.getOrPanicWith(&quot;expected some&quot;)
&lt;span class=&quot;result&quot;&gt;# program aborts with message &quot;expected some&quot;&lt;/span&gt;
Pass(1).getOrPanicWith(&quot;expected some&quot;)
&lt;span class=&quot;result&quot;&gt;--&amp;gt; 1&lt;/span&gt;
Fail(1).getOrPanicWith(&quot;expected pass&quot;)
&lt;span class=&quot;result&quot;&gt;# program aborts with message &quot;expected pass&quot;&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Having variant names with the same length avoids pointless debates and diverging code style decisions on whether
  the arms of matches should be lined up or not. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 05 Jul 2024 00:00:00 +0000</pubDate>
        <link>/languages/naming-conventions-option-and-result.html</link>
        <guid isPermaLink="true">/languages/naming-conventions-option-and-result.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Rust&apos;s Almost-Rules</title>
        <description>&lt;p&gt;(Inspired by &lt;a href=&quot;https://matklad.github.io/2022/07/10/almost-rules.html&quot;&gt;Almost Rules&lt;/a&gt;.)&lt;/p&gt;

&lt;h3 id=&quot;syntax&quot;&gt;Syntax&lt;/h3&gt;

&lt;h5 id=&quot;-is-followed-by-a-type&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt; is followed by a type&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;except inside struct initializers, where it is followed by a value&lt;/li&gt;
  &lt;li&gt;except function result types, which are preceded by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;generics-use-&quot;&gt;generics use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&amp;gt;&lt;/code&gt;&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;except in expression contexts, which uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::&amp;lt;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;invocations-use-&quot;&gt;invocations use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;except where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; is used, because “they convey important information”
    &lt;ul&gt;
      &lt;li&gt;except for macro invocations, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[]&lt;/code&gt; are equivalent and interchangeable&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;t--initializes-a-struct&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T {}&lt;/code&gt; initializes a struct&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;except inside an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt; starts a branch (see &lt;a href=&quot;rust-struct-initializer-mistake&quot;&gt;Rust’s Struct Initializer Syntax Was a Mistake&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;types-are-uppercase&quot;&gt;types are uppercase&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;except “primitive” types
    &lt;ul&gt;
      &lt;li&gt;except the primitive types array, slice, tuple and unit&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;rust-has-no-varargs&quot;&gt;Rust has no varargs&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;except for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extern&lt;/code&gt; functions&lt;/li&gt;
  &lt;li&gt;except for macros&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;patterns-introduce-bindings&quot;&gt;patterns introduce bindings&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;except in macro pattern matching, where the same syntax matches identifiers verbatim&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;semantics&quot;&gt;Semantics&lt;/h3&gt;

&lt;h5 id=&quot;types-with-a-total-order-implement-eq-and-ord&quot;&gt;types with a total order implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Eq&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ord&lt;/code&gt;&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;except &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f64&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f32&lt;/code&gt;, which do not&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;struct-initializers-use-temporary-lifetime-extension&quot;&gt;struct initializers use temporary lifetime extension&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;except tuple structs
    &lt;ul&gt;
      &lt;li&gt;except when using curly braces to initialize tuple structs&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 05 Aug 2024 00:00:00 +0000</pubDate>
        <link>/languages/rust-almost-rules.html</link>
        <guid isPermaLink="true">/languages/rust-almost-rules.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Equality &amp; Identity – Part 5: Fixing Java</title>
        <description>&lt;p&gt;The recent development of Java is an interesting case, as it faces these questions more acutely with the introduction
of value types in &lt;a href=&quot;https://en.wikipedia.org/wiki/Project_Valhalla_(Java_language)&quot;&gt;Project Valhalla&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;recap&quot;&gt;Recap&lt;/h4&gt;

&lt;p&gt;Java-before-value-types worked like this:&lt;/p&gt;

&lt;table class=&quot;table-medium table-layout-auto&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;==&lt;/th&gt;
      &lt;th&gt;Object#equals&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;primitive types (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;float&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;byte&lt;/code&gt;, …)&lt;/td&gt;
      &lt;td&gt;primitive equality&lt;/td&gt;
      &lt;td&gt;not available&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;reference types (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.lang.Integer&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.lang.Float&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.lang.Byte&lt;/code&gt;, …)&lt;/td&gt;
      &lt;td&gt;reference equality&lt;/td&gt;
      &lt;td&gt;value equality&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;br /&gt;
Note that every primitive type has a reference-based “wrapper type” to which it can be converted.&lt;br /&gt;
When the compiler injects this conversion implicitly, it is called “auto-boxing”.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;// primitive value&lt;/span&gt;
&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;                &lt;span class=&quot;c1&quot;&gt;// primitive equality → true&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;// auto-boxing the primitive value into its wrapper type&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;D&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;// reference equality, same reference → true&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;D&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;// reference equality, different reference → false&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// value equality → true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Primitive equality of primitives behaves largely the same as the value equality of its wrappers,
except for floating point values, where behavior differs for zero and not-a-number values:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;                               &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// false&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NaN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NaN&lt;/span&gt;                               &lt;span class=&quot;c1&quot;&gt;// false&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NaN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NaN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A (side-)effect of this is that a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashMap&amp;lt;Double&amp;gt;&lt;/code&gt; can reliably find entries, including ones with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NaN&lt;/code&gt; key.&lt;/p&gt;

&lt;h4 id=&quot;whats-new&quot;&gt;What’s new&lt;/h4&gt;

&lt;p&gt;With Valhalla, Java …&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;allows programmers to define their own value types,&lt;/li&gt;
  &lt;li&gt;migrates primitive wrapper types into value types, and&lt;/li&gt;
  &lt;li&gt;defines &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;==&lt;/code&gt; on value types to be a member-wise check for “sameness”.&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;
This means that comparison between two wrapper values with the same wrapped value now always return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;, including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NaN&lt;/code&gt; values:&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;table class=&quot;table-medium table-layout-auto&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;before Valhalla&lt;/th&gt;
      &lt;th&gt;after Valhalla&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new Double(Double.NaN) == new Double(Double.NaN)&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;false&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new Double(Double.NaN).equals(new Double(Double.NaN))&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
      &lt;td&gt;true&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;br /&gt;
This allows a more efficient representation of previously boxed wrapper types, without introducing breaking changes.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“Two value objects are the same if they are instances of the same class and the values of their instance fields are the same.”
(&lt;a href=&quot;https://cr.openjdk.org/~dlsmith/jep401/jep401-20250409/specs/value-objects-jls.html#jls-4.3.1&quot;&gt;draft spec&lt;/a&gt;) &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; are variables storing the results of any two boxing conversions of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p&lt;/code&gt;, then it is always the case that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a.equals(b)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a == b&lt;/code&gt;.”
(&lt;a href=&quot;https://cr.openjdk.org/~dlsmith/jep401/jep401-20250118/specs/value-objects-jls.html#jls-5.1.7&quot;&gt;draft spec&lt;/a&gt;) &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 07 Mar 2025 00:00:00 +0000</pubDate>
        <link>/languages/equality-and-identity-fixing-java.html</link>
        <guid isPermaLink="true">/languages/equality-and-identity-fixing-java.html</guid>
        
        
      </item>
    
      <item>
        <title>Language Design: Multi-Color Number Literals</title>
        <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; Use multiple colors to make the various components of your number literals easily distinguishable.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Different colors for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;base prefix&lt;/li&gt;
  &lt;li&gt;type suffix&lt;/li&gt;
  &lt;li&gt;float exponent&lt;/li&gt;
  &lt;li&gt;digits value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;image-before&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Do:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;&quot; alt=&quot;image-after&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Sun, 08 Jun 2025 00:00:00 +0000</pubDate>
        <link>/languages/multicolor-number-literals.html</link>
        <guid isPermaLink="true">/languages/multicolor-number-literals.html</guid>
        
        
      </item>
    
  </channel>
</rss>
