<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">

  <channel>
    <title>Alexandru Nedelcu - Blog</title>
    <description>Feed of blog articles, published at alexn.org/blog/</description>
    <link>https://alexn.org/</link>
    <atom:link href="https://alexn.org/feeds/blog.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 06 Mar 2026 09:40:05 +0000</pubDate>
    <lastBuildDate>Fri, 06 Mar 2026 09:40:05 +0000</lastBuildDate>
    <language>en</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <generator>Jekyll v4.4.1</generator>
    

<item>
  <title>Copyright is Dead</title>
  <description>If copyrighted works can be whitewashed / reimplemented via AI, then copyright is dead. And now we have a case in public view, the reimplementation of chardet, relicensed from LGPL to MIT, causing upheaval.</description>
  <content:encoded>&lt;img referrerpolicy=&quot;no-referrer-when-downgrade&quot; src=&quot;https://ly.alexn.org/m.php?idsite=1&amp;rec=1&amp;action_name=RSS+Feed&amp;url=https%3A%2F%2Falexn.org%2Ffeeds%2Fblog.xml&amp;pk_campaign=rss&amp;pk_kwd=open&quot; width=&quot;1&quot; height=&quot;1&quot; style=&quot;position: fixed !important; bottom: -1px !important; right: -1px !important; border:none !important; margin:0px !important;&quot; alt=&quot;&quot;&gt;
  
  
    &lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2026/03/06/copyright-is-dead/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2026-thomas-trying-to-fit.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1536&quot; height=&quot;1024&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Thomas, my tomcat, trying to fit into a box of tissues, visibly distressed that he can&apos;t fit. This is a metaphor, not sure if it&apos;s working 😛
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
If copyrighted works can be whitewashed / reimplemented via AI, then copyright is dead. And now we have a case in public view, the &lt;a href=&quot;https://github.com/chardet/chardet/issues/327#issuecomment-4005195078&quot;&gt;reimplementation of chardet&lt;/a&gt;, relicensed from LGPL to MIT, causing upheaval.
&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
This is a yet another opinion piece on AI, sorry, I’m taking a 40-days break from social media, which prompts me to write more on my blog. At least I get to be less superficial about it.
&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;chardet&lt;/code&gt; reimplementation was created by pointing the AI at the project’s test suite that works as the specification. However, if the project’s source code was in the LLM’s training data, then one can argue that this wasn’t a &lt;em&gt;“clean room”&lt;/em&gt; reimplementation. You don’t necessarily need to copy/paste code from the original project in order to create a derivative work — people that get exposed to original source code can’t really make the claim that they could execute a clean room reimplementation, which is why the guidelines for contributing to reverse engineering efforts (like the Wine or Mono projects) contained warnings against viewing Microsoft’s proprietary code.&lt;/p&gt;

&lt;p&gt;And many people are now worried that if this is legal, then &lt;a href=&quot;https://en.wikipedia.org/wiki/Copyleft&quot;&gt;copyleft&lt;/a&gt; is dead. And they should be worried, but it’s not just copyleft fans that should be worried, but rather all creative industries that depend on copyright. Because if this passes, then &lt;em&gt;copyright is as good as dead&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Well, I for one don’t think this is all that bad. Sure, it can potentially leave us without a job, but copyright has always been … &lt;em&gt;fake&lt;/em&gt;. Copyright violations are not really &lt;em&gt;theft&lt;/em&gt;, because copyright is not like actual private property — because if you’re infringing on someone’s copyright, you aren’t depriving the owner of their possesion. Copyright can only work because it’s a government-granted monopoly. And globally, it can only work because the US and Europe could use their economic strength to impose it via treaties.&lt;/p&gt;

&lt;p&gt;One can make the case that it deprives the owner of future revenue and recognition, which is the case made by the likes of RIAA and MPAA, which is also why we ended up with &lt;a href=&quot;https://en.wikipedia.org/wiki/Digital_rights_management&quot;&gt;DRM&lt;/a&gt;, i.e., software &lt;a href=&quot;https://en.wikipedia.org/wiki/Defective_by_Design&quot;&gt;defective by design&lt;/a&gt; and by law. Are we really siding with the RIAA, MPAA and Disney now? That should make us, Open Source fans, question our beliefs, despite the many benefits that copyright also bestowed on us.&lt;/p&gt;

&lt;p&gt;And “copyleft” happened as a counter-reaction of hackers that used the law to turn copyright on its head. &lt;a href=&quot;https://www.fsf.org/blogs/community/201cthe-printer-story201d-redux-a-testimonial-about-the-injustice-of-proprietary-firmware&quot;&gt;The story goes&lt;/a&gt; that Richard Stallman, the guy behind the GPL license and the FSF, wanted to improve his printer’s driver and he couldn’t do that, because printer drivers started being proprietary, with no available source-code. If the guy had the possibility of reimplementing a printer driver for cheap, we probably wouldn’t have a copyleft movement.&lt;/p&gt;

&lt;p&gt;Copyleft hasn’t been suitable for protecting many of authors’ wishes and interests for some time. An early example of this was &lt;a href=&quot;https://en.wikipedia.org/wiki/Tivoization&quot;&gt;tivoization&lt;/a&gt;, with GPL being patched in GPLv3. But then there was Linus Torvalds that came out against it, in &lt;a href=&quot;https://web.archive.org/web/20060813200643/https://www.forbes.com/technology/2006/03/09/torvalds-linux-licensing-cz_dl_0309torvalds1.html/&quot;&gt;an interview&lt;/a&gt;, saying:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“To me, the GPL really boils down to “I give out code, I want you to do the same.” The thing that makes me not want to use the GPLv3 in its current form is that it really tries to move more toward the “software freedom” goals. For example, the GPLv2 in no way limits your use of the software. If you’re a mad scientist, you can use GPLv2’d software for your evil plans to take over the world (“Sharks with lasers on their heads!!”), and the GPLv2 just says that you have to give source code back. And that’s OK by me. I like sharks with lasers. I just want the mad scientists of the world to pay me back in kind. I made source code available to them, they have to make their changes to it available to me. After that, they can fry me with their shark-mounted lasers all they want.”&lt;/em&gt; — Linus Torvalds, 2006&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another example was the proliferation of “source available” licenses that are not &lt;a href=&quot;https://opensource.org/definition-annotated&quot;&gt;Open Source&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Free_software&quot;&gt;Free software&lt;/a&gt;. The first instance I remember is Microsoft’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Shared_Source_Initiative&quot;&gt;Shared Source Initiative&lt;/a&gt;, back when Microsoft was treating Linux as “cancer”. And such initiatives are now back in full force, because the era of interest-free money may be over, companies building Open Source struggling to survive and flipping, e.g., MongoDB, Elasticsearch, Akka. Their reasoning for doing so may be legitimate — copyleft doesn’t work given the &lt;em&gt;“SaaS loophole”&lt;/em&gt;, and if you try selling your Open Source product as SaaS, Amazon may be able to do it better and cheaper.&lt;/p&gt;

&lt;p&gt;In fairness, they didn’t &lt;a href=&quot;https://www.joelonsoftware.com/2002/06/12/strategy-letter-v/&quot;&gt;get the memo&lt;/a&gt; — Open Source, in the context of a business, can only work as a complementary to a proprietary product, as a way to bring costs down, or as a strategy to get rid of your competition.&lt;/p&gt;

&lt;p&gt;But wait, in a world in which the cost of cloning stuff is going down, even if proprietary, or in a world in which laymen can just solve their own, simpler problems, without buying into a whole SaaS deal, avoiding to get stuck with everything but the kitchen sink … &lt;em&gt;SaaS is probably dead, too.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And yet another example are all the people concerned that their software ends up being used in a way they disagree with (e.g., by the military, or for surveillance). Famously, a license like &lt;a href=&quot;https://en.wikipedia.org/wiki/Douglas_Crockford#Software_license_for_%22Good,_not_Evil%22&quot;&gt;the Software shall be used for good, not evil&lt;/a&gt; is not compatible with Open Source / Free Software, like all restrictions on usage. Although, to be frank, you may try banning the military from using and abusing your software, but that’s a bit naive, because the state, by design, has a monopoly on violence, copyright is only possible due to this social construct, and you can’t expect the military to show restraint when it comes to copyright infringements, especially during war or “special operations”.&lt;/p&gt;

&lt;p&gt;I mentioned that it’s not all doom and gloom because …&lt;/p&gt;

&lt;p&gt;If you’re an anarchist loving the ideas behind Open Source, you should like some of these developments, because yes, you may now be able to fix your printer driver. And this ability may not be restricted just to software developers, but to laymen as well. &lt;em&gt;“Democratizing”&lt;/em&gt; this or that should have happened for software development, and instead, the world moved to protected, defective by design, consumption-only devices, in order for industry to protect copyright, the world converging to a handful of monopolies built on copyright and patents.&lt;/p&gt;

&lt;p&gt;Well, I may worry about my future, but my anarchist heart is glad to see the days of copyright numbered.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2026/03/06/copyright-is-dead/?pk_campaign=rss&quot;&gt;Copyright is Dead&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 06 Mar 2026 07:10:02 +0000</pubDate>
  <dc:modified>Fri, 06 Mar 2026 09:39:22 +0000</dc:modified>
  <atom:modified>Fri, 06 Mar 2026 09:39:22 +0000</atom:modified>
  <link>https://alexn.org/blog/2026/03/06/copyright-is-dead/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2026/03/06/copyright-is-dead/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>AI</category>
  <category>Open Source</category>
  <category>Opinion</category>
  </item>


<item>
  <title>Boring Tech May Become Irrelevant Tech</title>
  <description>You may have read the “Boring” Tech Stack in 2015, a view with which I’ve wholeheartedly agreed. And if you didn’t agree with this view, the corporation you’re working for surely agreed. It’s why companies like Google have had a list of “approved” languages, for example. But is this view relevant in 2026? I think not.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2026/03/05/boring-tech-irrelevant/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2026-thomas-worried.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;2000&quot; height=&quot;1500&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Thomas, self-employed tomcat, worried about the evolution of the software industry.
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
You may have read the &lt;a href=&quot;https://mcfunley.com/choose-boring-technology&quot;&gt;“Boring” Tech Stack&lt;/a&gt; in 2015, a view with which I’ve wholeheartedly agreed. And if you didn’t agree with this view, the corporation you’re working for surely agreed. It’s why companies like Google have had a list of “approved” languages, for example. But is this view relevant in 2026? I think not.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
This is a continuation of &lt;a href=&quot;https://alexn.org/blog/2025/11/16/programming-languages-in-the-age-of-ai-agents/&quot;&gt;Programming Languages in the Age of AI Agents&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;Companies pick “boring” tech because boring is reliable, it does the job, and most importantly, it minimizes risk. Companies don’t want to be locked into tech stacks that are obsolete, because:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Hiring developers becomes more challenging, and historically, it’s been good to pick tooling that optimizes for “horizontal scalability” of development — i.e., optimize for head count — which makes sense in a growing industry, given there are more beginners than seniors, beginner-friendly tech wins, and popular tech is beginner-friendly, due to it being old, popular and targeting simple apps.&lt;/li&gt;
  &lt;li&gt;Projects get stuck on obsolete tech, companies being forced to support that tech stack on their own. Project rewrites are super risky, the industry being filled with stories of failed rewrites. As such, we now have it ingrained that a project rewrite is something &lt;a href=&quot;https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/&quot;&gt;we should never do&lt;/a&gt;. So, companies want tech stacks that get supported for decades.&lt;/li&gt;
  &lt;li&gt;A special mention here goes for maintenance — older tech tends to be more stable, whereas newer tech tends to break compatibility more often, and the upgrade treadmill sucks.&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/You_aren&apos;t_gonna_need_it&quot;&gt;YAGNI&lt;/a&gt; mentality is most often good, our industry’s history being filled with stories of projects preparing for “big data” with data that could easily fit in RAM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in 2026 we are facing the reality of AI/LLMs. I’ll use the example of less popular programming languages, such as Rust, Scala, OCaml, F#, Haskell, and others. Here’s why:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The cost of refactoring for switching tech stacks, programming languages included, is going to zero.&lt;/li&gt;
  &lt;li&gt;The cost of training new people on your tech stack also converges to zero — if your project has the right skills promoted and the guardrails, does it matter if novices aren’t “functional programming” wizards from day 1?&lt;/li&gt;
  &lt;li&gt;The cost of dependency upgrades goes to zero, becoming an automated process, even when it involves API breakage.&lt;/li&gt;
  &lt;li&gt;Frontier models are good, but they still do dumb shit all the time, so having better tech, like a potent compiler to watch your back, matters.&lt;/li&gt;
  &lt;li&gt;The feedback loop matters, and static, expressive type systems provide the most bang for the buck (optimal token usage).&lt;/li&gt;
  &lt;li&gt;Top programming languages have the advantage of a large corpus available for training, however, that’s also a liability, as the common denominator of all code seen in the wild is not very good (which is why by simply telling the LLM to use FP, it will generate better code for the simple fact that FP code seen in the wild tends to be higher quality).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;People are already talking about programming languages designed for LLMs, not humans. I think that’s nonsense; we’ll use languages designed for LLMs &lt;em&gt;and&lt;/em&gt; humans, because even if you are an AI maximalist, you still need to communicate with the AI system efficiently, and to have the ability to review what it did. And what will such a language look like?&lt;/p&gt;

&lt;p&gt;Well, IMO (YMMV), such a language will be high-level, but it will also be very precise, very static, very expressive, in order to optimize the feedback loop, to optimize tokens, to minimize mistakes, to force LLMs and humans alike to apply mathematical reasoning. It’s hard to picture us settling on natural languages (English); that boat sailed in the ~16th century when symbolic notation was adopted for math. And it’s hard for me to see very popular languages like Java, Python or C++ surviving either, due to all their inherent unsafety.&lt;/p&gt;

&lt;p&gt;Anyway, more to the point — given the costs of software maintenance, refactoring or adoption are significantly going down, converging to zero, then old lessons no longer make sense, and companies are already on outdated best practices regarding the adoption of tech stacks.&lt;/p&gt;

&lt;p&gt;The next time you’re in a meeting with stakeholders, they probably have LLMs/AI in their KPIs 😉, so now you have the words to fight back against Java, Spring, Hibernate and Oracle DB 😈&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2026/03/05/boring-tech-irrelevant/?pk_campaign=rss&quot;&gt;Boring Tech May Become Irrelevant Tech&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 05 Mar 2026 16:12:06 +0000</pubDate>
  <dc:modified>Fri, 06 Mar 2026 04:49:20 +0000</dc:modified>
  <atom:modified>Fri, 06 Mar 2026 04:49:20 +0000</atom:modified>
  <link>https://alexn.org/blog/2026/03/05/boring-tech-irrelevant/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2026/03/05/boring-tech-irrelevant/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>AI</category>
  <category>FP</category>
  <category>Opinion</category>
  <category>Programming</category>
  <category>Languages</category>
  </item>


<item>
  <title>Tapir Server with Cats-Effect and Pekko HTTP (snippet)</title>
  <description>Simple snippet for using Tapir, with business logic driven by Cats-Effect, using Akka/Pekko HTTP as a backend.</description>
  <content:encoded>&lt;p&gt;At work, we have been using &lt;a href=&quot;https://pekko.apache.org/docs/pekko-http/current/&quot;&gt;Akka/Pekko HTTP&lt;/a&gt; for some servers, but one of the foundations is &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats-Effect&lt;/a&gt;, and I wanted to use &lt;a href=&quot;https://tapir.softwaremill.com/&quot;&gt;Tapir&lt;/a&gt; for refactoring one of our microservices.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
As you may have noticed, I sometimes use this blog as a replacement for GitHub Gist.
&lt;/p&gt;

&lt;p&gt;Here’s a simple snippet for using Tapir, with business logic driven by Cats-Effect, using Akka/Pekko HTTP as a backend:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;#!/usr/bin/env -S scala shebang

//&gt; using scala &quot;3.8.2&quot;
//&gt; using dep com.softwaremill.sttp.tapir::tapir-core:1.13.10
//&gt; using dep com.softwaremill.sttp.tapir::tapir-pekko-http-server:1.13.10
//&gt; using dep org.typelevel::cats-effect:3.6.3
//&gt; using dep org.apache.pekko::pekko-http:1.3.0
//&gt; using dep org.apache.pekko::pekko-actor-typed:1.4.0

import cats.effect.*
import cats.effect.std.Dispatcher
import org.apache.pekko.actor.typed.ActorSystem
import org.apache.pekko.actor.typed.scaladsl.Behaviors
import org.apache.pekko.http.scaladsl.Http
import org.apache.pekko.http.scaladsl.server.Route
import scala.concurrent.ExecutionContext
import sttp.tapir.*
import sttp.tapir.server.pekkohttp.PekkoHttpServerInterpreter

object Main extends IOApp.Simple {

  // Endpoint definition (pure tapir, no effect type yet)
  val helloWorldEndpoint =
    endpoint.get
      .in(&quot;hello&quot; / &quot;world&quot;)
      .in(query[String](&quot;name&quot;))
      .out(stringBody)
      .errorOut(stringBody)

  // Business logic described via Cats Effect IO functions
  def greetLogic(name: String): IO[Either[String, String]] =
    IO.println(s&quot;Saying hello to: $name&quot;)
      .as(Right(s&quot;Hello, $name!&quot;))

  // Bridge: IO logic → Future, as required by the Pekko HTTP interpreter
  def helloWorldRoute(using Dispatcher[IO], ExecutionContext): Route =
    PekkoHttpServerInterpreter().toRoute(
      helloWorldEndpoint.serverLogic(name =&gt; 
        summon[Dispatcher[IO]].unsafeToFuture(greetLogic(name))
      )
    )

  override def run: IO[Unit] = {
    val res =
      for {
        given Dispatcher[IO] &lt;- Dispatcher.parallel[IO]
        given ExecutionContext &lt;- Resource.eval(IO.executionContext)
        given ActorSystem[Nothing] &lt;- Resource(IO {
          val system = ActorSystem(Behaviors.empty, &quot;tapir-pekko-sample&quot;)
          val cancel = IO.fromFuture(IO {
            val f = system.whenTerminated
            system.terminate()
            f
          })
          (system, cancel.void)
        })
        _ &lt;- Resource(IO {
          // Starts server
          val bound = Http().newServerAt(&quot;localhost&quot;, 8383)
            .bind(helloWorldRoute)
          val cancel =
            IO.fromFuture(IO {
              bound.flatMap(_.unbind())
            });
          (bound, cancel.void)
        })
      } yield ()

    res.use { _ =&gt;
      for {
        _ &lt;- IO.println(
          &quot;Server running at http://localhost:8383 — press ENTER to stop&quot;
        )
        _ &lt;- IO.readLine.void
      } yield ()
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2026/03/05/tapir-server-with-cats-effect-and-pekko-http-snippet/?pk_campaign=rss&quot;&gt;Tapir Server with Cats-Effect and Pekko HTTP (snippet)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 05 Mar 2026 12:27:35 +0000</pubDate>
  <dc:modified>Thu, 05 Mar 2026 12:37:35 +0000</dc:modified>
  <atom:modified>Thu, 05 Mar 2026 12:37:35 +0000</atom:modified>
  <link>https://alexn.org/blog/2026/03/05/tapir-server-with-cats-effect-and-pekko-http-snippet/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2026/03/05/tapir-server-with-cats-effect-and-pekko-http-snippet/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Akka</category>
  <category>Cats Effect</category>
  <category>Pekko</category>
  <category>Programming</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Hybrid IO-driven Promise (Scala snippet)</title>
  <description>Alternative to Scala’s Promise and Cats-Effect’s Deferred, exposing a hybrid API, useful for interoperability between imperative libraries (e.g., Akka/Pekko) and Cats-Effect.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
Alternative to &lt;a href=&quot;https://www.scala-lang.org/api/current/scala/concurrent/Promise.html&quot;&gt;Scala’s Promise&lt;/a&gt; and &lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/deferred&quot;&gt;Cats-Effect’s Deferred&lt;/a&gt;, exposing a hybrid API, useful for interoperability between imperative libraries (e.g., Akka/Pekko) and Cats-Effect.
&lt;/p&gt;

&lt;p&gt;Compared with &lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/deferred&quot;&gt;Deferred&lt;/a&gt;, this &lt;code&gt;IOPromise&lt;/code&gt; allows for completing the promise via &lt;code&gt;unsafeTryComplete&lt;/code&gt;, which can be used in an imperative (non-&lt;code&gt;IO&lt;/code&gt;) context, but it still exposes an &lt;code&gt;IO&lt;/code&gt;-driven API.&lt;/p&gt;

&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The advantage of using this, instead of just wrapping &lt;code&gt;scala.concurrent.{ Promise, Future }&lt;/code&gt; references in &lt;code&gt;cats.effect.IO&lt;/code&gt; is that the &lt;code&gt;IO&lt;/code&gt; value returned by &lt;code&gt;awaitOrGet&lt;/code&gt; doesn’t leak memory (being able to unregister its callback on cancellation).&lt;/li&gt;
  &lt;li&gt;The advantage of using this, over &lt;code&gt;cats.effect.Deferred&lt;/code&gt;, is that it allows for completing the promise in an imperative context, without needing to instantiate a &lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/dispatcher&quot;&gt;Dispatcher&lt;/a&gt; or having to import &lt;a href=&quot;https://typelevel.org/cats-effect/api/3.x/cats/effect/unsafe/IORuntime$.html#global:cats.effect.unsafe.IORuntime&quot;&gt;cats.effect.unsafe.global&lt;/a&gt;, thus being safer, more efficient and with a lighter API.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//&gt; using dep &quot;org.typelevel::cats-effect:3.6.3&quot;
//&gt; using scala &quot;3.3.7&quot;

import cats.effect.IO
import java.util.concurrent.atomic.AtomicReference
import scala.annotation.tailrec
import scala.collection.immutable.Queue
import scala.concurrent.ExecutionContext
import scala.concurrent.Future

/** This is a replacement for `scala.concurrent.Promise` and
  * `cats.effect.Deferred`, exposing a hybrid API, useful in 
  * interop scenarios.
  *
  * All methods exposed have both pure/safe and impure/unsafe variants:
  *   - [[tryComplete]] and [[unsafeTryComplete]]
  *   - [[awaitOrGet]] and [[unsafeAwaitOrGet]]
  */
final class IOPromise[A] private (ref: AtomicReference[IOPromise.State[A]]) {
  import IOPromise.*

  /** Attempts to complete the promise with the given result.
    *
    * It&apos;s UNSAFE, in the sense that it&apos;s side-effecting. This can be a feature,
    * as it can be used in a non-`IO` context.
    *
    * @return
    *   `true` if the promise was successfully completed with the given result,
    *   `false` if the promise was already completed by another
    *   thread/actor/fiber.
    */
  @tailrec
  def unsafeTryComplete(result: Either[Throwable, A]): Boolean = {
    val state = ref.get()
    state.tryComplete(result) match {
      case None =&gt; false
      case Some((task, newState)) =&gt;
        if (ref.compareAndSet(state, newState)) {
          task.run()
          true
        } else {
          // Retry...
          unsafeTryComplete(result)
        }
    }
  }

  /** Variant of [[unsafeTryComplete]]. */
  def unsafeTrySuccess(value: A): Boolean =
    unsafeTryComplete(Right(value))

  /** Variant of [[unsafeTryComplete]]. */
  def unsafeTryFailure(ex: Throwable): Boolean =
    unsafeTryComplete(Left(ex))

  /** Safe (IO-driven) version of [[unsafeTryComplete]]. */
  def tryComplete(result: Either[Throwable, A]): IO[Boolean] =
    IO(unsafeTryComplete(result))

  /** Safe (IO-driven) version of [[unsafeTrySuccess]]. */
  def trySuccess(value: A): IO[Boolean] =
    tryComplete(Right(value))

  /** Safe (IO-driven) version of [[unsafeTryFailure]]. */
  def tryFailure(ex: Throwable): IO[Boolean] =
    tryComplete(Left(ex))

  /** Returns an `IO` that completes when the promise is completed.
    *
    * @see
    *   [[unsafeAwaitOrGet]] for the side-effecting version of this method.
    */
  def awaitOrGet: IO[A] = {
    def cancel(cb: Callback[A]): IO[Unit] =
      IO.defer {
        val current = ref.get()
        current.unregister(cb) match {
          case Some(update) if !ref.compareAndSet(current, update) =&gt;
            cancel(cb) // retry
          case _ =&gt;
            IO.unit
        }
      }

    @tailrec
    def tryCompleteOrEnqueue(cb: Callback[A]): Option[IO[Unit]] = {
      val state = ref.get()
      state.getResult(cb) match {
        case Right(newState) =&gt;
          if (ref.compareAndSet(state, newState)) {
            Some(cancel(cb))
          } else {
            tryCompleteOrEnqueue(cb)
          }
        case Left(task) =&gt;
          task.run()
          None
      }
    }

    IO.executionContext.flatMap { ec =&gt;
      IO.async { cb =&gt;
        IO(tryCompleteOrEnqueue((ec, cb)))
      }
    }
  }

  /** Awaits the completion of the promise, producing a result.
    *
    * It&apos;s UNSAFE because it&apos;s side-effecting, and `Future` itself has its own
    * warts.
    *
    * @see
    *   [[awaitOrGet]] for the safe (IO-driven) version of this method.
    * @return
    *   a `Future` that completes when the promise is completed.
    */
  def unsafeAwaitOrGet(using ec: ExecutionContext): Future[A] = {
    @tailrec
    def tryCompleteOrEnqueue(cb: Callback[A]): Unit = {
      val state = ref.get()
      state.getResult(cb) match {
        case Right(newState) =&gt;
          if (!ref.compareAndSet(state, newState)) {
            tryCompleteOrEnqueue(cb)
          }
        case Left(task) =&gt;
          task.run()
      }
    }

    val promise = scala.concurrent.Promise[A]()
    tryCompleteOrEnqueue((ec, r =&gt; promise.complete(r.toTry)))
    promise.future
  }
}

object IOPromise {
  /** Creates a new `IOPromise`.
    *
    * @see
    *   [[unsafe]] for the side-effecting version of this method.
    */
  def apply[A](): IO[IOPromise[A]] =
    IO(unsafe())

  /** Creates a new `IOPromise` in a side-effectful way.
    *
    * UNSAFE, because it&apos;s side-effecting, meaning that it allocates mutable
    * state.
    *
    * @see
    *   [[apply]] for the safe (IO-driven) version of this method.
    */
  def unsafe[A](): IOPromise[A] =
    new IOPromise(new AtomicReference(State.Pending(Queue.empty)))

  private type Callback[A] = (ExecutionContext, Either[Throwable, A] =&gt; Unit)

  sealed private trait State[A] extends Product with Serializable {
    /** @return
      *   either `Some((task, newState))`, in case the state was `Pending`, and
      *   we have to call all the registered callbacks. Or `None`, in case the
      *   state was already `Completed`, and the caller has nothing left to do.
      */
    def tryComplete(result: Either[Throwable, A]): Option[(Runnable, State[A])] =
      this match {
        case State.Pending(callbacks) =&gt;
          val task: Runnable = () =&gt;
            for ((ec, notify) &lt;- callbacks)
              ec.execute(() =&gt; notify(result))
          Some((task, State.Completed(result)))
        case State.Completed(_) =&gt;
          None
      }

    /** Attempts to register the given callback, if the state is still
      * `Pending`, returning the new state with the callback registered.
      *
      * If the state is already completed, then the callback isn&apos;t registered,
      * the caller returning a task that should be executed. Note that this
      * method is supposed to be pure, which is why we are not calling the
      * callback directly.
      */
    def getResult(cb: Callback[A]): Either[Runnable, State[A]] =
      this match {
        case State.Pending(callbacks) =&gt;
          Right(State.Pending(callbacks.enqueue(cb)))
        case State.Completed(result) =&gt;
          Left { () =&gt;
            val (ec, notify) = cb
            ec.execute(() =&gt; notify(result))
          }
      }

    /** Removes a callback from the queue, used for cancellation. */
    def unregister(cb: Callback[A]): Option[State[A]] =
      this match {
        case State.Pending(callbacks) =&gt;
          val filtered = callbacks.filterNot(_ == cb)
          Some(State.Pending(filtered))
        case State.Completed(_) =&gt;
          None
      }
  }

  private object State {
    /** Represents a promise that is still pending, and has a queue of callbacks
      * waiting on completion.
      */
    final case class Pending[A](callbacks: Queue[Callback[A]]) extends State[A]

    /** Represents a promise that is already completed, with the result
      * memoized.
      */
    final case class Completed[A](result: Either[Throwable, A]) extends State[A]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As a usage example, here’s a &lt;a href=&quot;https://pekko.apache.org/japi/pekko/snapshot/org/apache/pekko/stream/KillSwitch.html&quot;&gt;KillSwitch&lt;/a&gt; implementation on which we can await the shutdown via &lt;code&gt;cats.effect.IO&lt;/code&gt;, very useful for &lt;a href=&quot;https://alexn.org/blog/2023/04/17/integrating-akka-with-cats-effect-3/&quot;&gt;Akka/Pekko+Cats-Effect interop&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//&gt; using dep &quot;org.apache.pekko::pekko-stream-typed:1.4.0&quot;

import cats.effect.kernel.Resource
import cats.effect.IO
import org.apache.pekko.stream.FlowShape
import org.apache.pekko.stream.Graph
import org.apache.pekko.stream.KillSwitch
import org.apache.pekko.stream.KillSwitches
import org.slf4j.LoggerFactory

/** Replacement for Akka/Pekko `SharedKillSwitch`.
  *
  * It&apos;s primary innovation is the [[awaitShutdown]] method.
  *
  * NOTE: the use of `SharedKillSwitch` in this project is now banned ;-)
  */
trait BetterKillSwitch extends KillSwitch {
  def flow[T]: Graph[FlowShape[T, T], BetterKillSwitch]
  def awaitShutdown: IO[KillSwitchOutcome]
}

object BetterKillSwitch {
  def unsafe(name: String): BetterKillSwitch = {
    val underlying = KillSwitches.shared(name)
    val promise = IOPromise.unsafe[KillSwitchOutcome]()
    new BetterKillSwitchEfficient(underlying, promise)
  }

  def apply(name: String): IO[BetterKillSwitch] =
    IO(unsafe(name))

  def resource(name: String): Resource[IO, BetterKillSwitch] =
    Resource(apply(name).map { ks =&gt;
      (ks, IO(ks.shutdown()))
    })
}

final private class BetterKillSwitchEfficient(
  underlying: org.apache.pekko.stream.SharedKillSwitch,
  promise: IOPromise[KillSwitchOutcome]
) extends BetterKillSwitch {
  override def awaitShutdown: IO[KillSwitchOutcome] =
    promise.awaitOrGet

  override def shutdown(): Unit =
    try
      underlying.shutdown()
    finally {
      val _ = promise.unsafeTrySuccess(KillSwitchOutcome.Completed)
    }

  override def abort(ex: Throwable): Unit =
    try
      underlying.abort(ex)
    finally
      if (!promise.unsafeTrySuccess(KillSwitchOutcome.Errored(ex)))
        LoggerFactory.getLogger(getClass).error(
          &quot;Kill switch was already shutdown when aborting with error&quot;,
          ex
        )

  override def flow[T]: Graph[FlowShape[T, T], BetterKillSwitch] =
    underlying.flow[T].mapMaterializedValue { it =&gt;
      if (it == underlying) BetterKillSwitchEfficient.this
      else new BetterKillSwitchEfficient(it, promise)
    }
}

/** Kill-switches can be shutdown gracefully (i.e., by completing the stream),
  * or via an error.
  *
  * The effect on the downstream is not the same, as `onError` short-circuits
  * the stream, while `shutdown` allows the in-process messages to complete.
  *
  * This type is used to signal to shut down listener whenever the kill-switch
  * is shutdown gracefully or aborted via an error.
  */
enum KillSwitchOutcome {
  case Completed
  case Errored(e: Throwable)

  def toEither: Either[Throwable, Unit] =
    this match {
      case Completed =&gt; Right(())
      case Errored(e) =&gt; Left(e)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that when using a &lt;a href=&quot;https://pekko.apache.org/japi/pekko/1.4/org/apache/pekko/stream/SharedKillSwitch.html&quot;&gt;SharedKillSwitch&lt;/a&gt; (the standard implementation provided by Akka/Pekko), we could already do something like the following, by leveraging Akka/Pekko streams, but it’s definitely heavier, API-wise as well (notice the &lt;code&gt;Materializer&lt;/code&gt; requirement):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.syntax.*
import org.apache.pekko.stream.Materializer
import org.apache.pekko.stream.SharedKillSwitch
import org.apache.pekko.stream.scaladsl.Source

def awaitShutdown(
  ref: SharedKillSwitch
)(using Materializer): IO[Either[Throwable, Unit]] = {
  val start = IO {
    val done = Source.never[Unit]
      .via(ref.flow)
      .run()
    (done, IO.unit)
  }
  IO.fromFutureCancelable(start)
    .void.attempt
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2026/02/17/hybrid-io-driven-promise-in-scala-snippet/?pk_campaign=rss&quot;&gt;Hybrid IO-driven Promise (Scala snippet)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 17 Feb 2026 12:03:04 +0000</pubDate>
  <dc:modified>Tue, 17 Feb 2026 13:46:11 +0000</dc:modified>
  <atom:modified>Tue, 17 Feb 2026 13:46:11 +0000</atom:modified>
  <link>https://alexn.org/blog/2026/02/17/hybrid-io-driven-promise-in-scala-snippet/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2026/02/17/hybrid-io-driven-promise-in-scala-snippet/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Akka</category>
  <category>Cats Effect</category>
  <category>Concurrency</category>
  <category>FP</category>
  <category>Pekko</category>
  <category>Programming</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>New Year, Old Me</title>
  <description>Reflections on finding happiness through gratitude, purpose, and disengaging from what’s unimportant.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2026/01/08/new-year-old-me/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2026-me-and-my-wife.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1900&quot; height=&quot;1187&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Me and my wife on our winter retreat, somewhere in Brașov, Romania.
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
In 2025, I was happy. Like, really happy. I wasn&apos;t miserable before, far from it, but this past year was strange, as I&apos;ve been having repeated episodes when I felt my heart was bursting with happiness. It&apos;s been going on for months now, and it&apos;s not subsiding, the feeling and frequency are only intensifying.
&lt;/p&gt;

&lt;p&gt;The relationship I have with my wife is great. We started dating in 2001, got married in 2007, so that’s almost 19 years of marriage, and 25 years of loving each other, and I love her even more. The relationship I have with my son is great. He’s 15, now a freshman in high school, and I feel a lot of accomplishment from teaching him math, computer science, or my values; plus I’m really proud of him, having bittersweet moments as I witness the man he’s growing into. Work is good. I’m a “Chapter Lead”, which is a fancy way of saying that I’m a cross-team manager while still having individual contributions. I still have a lot of passion for programming. And my winter break is now over, I’ve spent it with family and friends, and I’ve also read 5 fiction books in 2 weeks (yay!).&lt;/p&gt;

&lt;p&gt;This is noteworthy for me because I’m usually grumpy and a pessimist. I was never diagnosed with depression, but I went through at least two burnouts; and the pandemic, with the subsequent war at our borders, hit me hard. I’ve always joked that having a family to take care of wouldn’t allow me to reach the bottom. And I do have a tendency for doom-and-gloom, which is why I’m lucky to have married an optimist.&lt;/p&gt;

&lt;p&gt;I think that what changed is that I’ve started being more grateful. Getting older, you start realizing some obvious truths, such as the fact that life is actually good as long as you have your health, and your basic needs met, like food and shelter. And having fun, in the modern sense (e.g., travel, parties), is actually optional. Recharging batteries is important, but I’ve come to realize that what actually brings happiness is living with purpose and gratitude, which is hard work.&lt;/p&gt;

&lt;p&gt;I’m now afraid it won’t last, nothing lasts, but right now each day for me is a gift, and I’m glad that I came to this realization before falling seriously ill, or some other tragedy that’s waiting around the corner. Being raised as an Orthodox Christian (non-practicing, and I was mostly agnostic in the past), I’ve never learned the true power of prayer — instilling gratitude by thanking God daily for the gifts I’ve received. This is similar to meditation sessions, focusing on breathing, to remind you that you’re still here and alive, but I find such meditation to be more shallow, as feeling alive doesn’t lead me to gratitude, unless I’m faced with serious life problems.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://alexn.org/blog/2025/10/13/outsourced-voices-outsourced-minds/&quot;&gt;Disconnecting from web slop&lt;/a&gt; (like world news) certainly helped. I’ve come to realize that all online social media platforms are toxic, including Mastodon or Bluesky. To tell you the truth, these aren’t any less toxic than 𝕏/Twitter, their only redeeming quality being the ability to avoid the algorithmic feed, and thus curation works slightly better (but only slightly). The Web is dying due to AI slop, bots and negative people, but we can still find communities that are islands, tuned to our values and interests. And being too-online is bad for our mental health.&lt;/p&gt;

&lt;p&gt;I maintain a social media presence strictly for learning programming, honing my craft, and for finding out more about interesting hobbies, or books recommendations. You know, the good stuff. I’ve had occasional doom-scrolling episodes, or political posts that I then deleted within 10 minutes. Someone is always wrong or an asshole on the Internet, some tragedy is always happening in other parts of the world, but growing older, I care less and less. I’m still not able to care only about what I can influence, but this Stoic philosophy of life is certainly my ideal.&lt;/p&gt;

&lt;p&gt;Back in 2024, I had &lt;a href=&quot;https://alexn.org/blog/2024/01/01/new-year-resolutions/&quot;&gt;New Year’s resolutions&lt;/a&gt; that had to do with habits. What a waste. New Year’s should be a time for reflection, not for TODO lists. My 2026 New Year’s resolution is to keep doing what I’ve been doing — to be grateful, to strive to be a good person, to live with purpose, to maintain curiosity, to perfect my craft, to strive to be the best husband, father, colleague, and friend that I can be. I don’t have recipes for these, and I’ll fail a lot, but this path is what brings me joy.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2026/01/08/new-year-old-me/?pk_campaign=rss&quot;&gt;New Year, Old Me&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 08 Jan 2026 10:10:32 +0000</pubDate>
  <dc:modified>Thu, 08 Jan 2026 10:22:30 +0000</dc:modified>
  <atom:modified>Thu, 08 Jan 2026 10:22:30 +0000</atom:modified>
  <link>https://alexn.org/blog/2026/01/08/new-year-old-me/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2026/01/08/new-year-old-me/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Opinion</category>
  <category>Personal</category>
  <category>Politics</category>
  </item>


<item>
  <title>How To Become a DevOps Engineer</title>
  <description>The TLDR: Eat your own dogfood by practicing DevOps on your own infrastructure, change mentality to one oriented towards automation, and grow your hard engineering skills, such as learning to do programming, because it’s in the job description.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
The TLDR: &lt;em&gt;Eat your own dogfood&lt;/em&gt; by practicing DevOps on your own infrastructure, change mentality to one oriented towards automation, and grow your hard engineering skills, such as learning to do programming, because it’s in the job description.
&lt;/p&gt;

&lt;p&gt;While working in this industry, at some point it becomes clear that good DevOps engineers may be more rare than good developers. Senior people end up interviewing for engineering roles, and as an interviewer, I started being happy to see people knowing what &lt;code&gt;$?&lt;/code&gt; is for.&lt;/p&gt;

&lt;p&gt;I may even understand why that happens. Depending on the organization, the job of a DevOps is less about engineering per se, and more about dealing with manual investigations and paperwork. Few devs have the stomach to become DevOps, so the normal pipeline for creating DevOps engineers goes through Support departments. DevOps was coined to highlight that Operations teams need to invest in automation and fast problem detection mechanisms, which requires software development. But in many projects it becomes clear that the “dev” in DevOps may be missing entirely.&lt;/p&gt;

&lt;p&gt;Be as it may, if you want to grow as a DevOps engineer, you need to grow your inner “dev”. Knowing how to use your Windows laptop and browser isn’t enough of a hard skill to get by. So here’s what you need to do:&lt;/p&gt;

&lt;h3 id=&quot;1-use-the-linux-command-line-every-day&quot;&gt;1) Use the Linux command line every day&lt;/h3&gt;

&lt;p&gt;First, Linux dominates on the server-side. If you’re administering Windows servers, the days of your job are numbered, even if you’re a believer in Microsoft’s tech.&lt;/p&gt;

&lt;p&gt;I can’t stress this enough. It’s embarrassing to notice people not being able to do basic tasks, such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Navigate the file system, find files, view file contents, edit files.&lt;/li&gt;
  &lt;li&gt;Handle &lt;code&gt;tar.gz&lt;/code&gt; archives.&lt;/li&gt;
  &lt;li&gt;Finding out if a package is installed and what version.&lt;/li&gt;
  &lt;li&gt;Finding if a certain process is running.&lt;/li&gt;
  &lt;li&gt;Getting the logs of a process.&lt;/li&gt;
  &lt;li&gt;Filter errors from those logs. Read those errors.&lt;/li&gt;
  &lt;li&gt;Kill that process.&lt;/li&gt;
  &lt;li&gt;Investigate CPU, RAM or disk usage.&lt;/li&gt;
  &lt;li&gt;Check that a server is up and running.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The easiest way to do that is to install Linux on your laptop. If you can’t do that on your work laptop, maybe because your organization has rigid ideas about security and support, go for Apple’s macOS, or try &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/wsl/about&quot;&gt;WSL&lt;/a&gt;, or at the very least, install Linux on your personal laptop.&lt;/p&gt;

&lt;p&gt;Then force yourself to use Unix/Linux command line tools, every day. Given the advent of LLM tools, it’s easier than ever to get answers.&lt;/p&gt;

&lt;p&gt;If you’re Romanian, check out &lt;a href=&quot;https://github.com/systems-cs-pub-ro/carte-uso/releases/tag/uso-ed1-2021&quot;&gt;“Utilizarea sistemelor de operare”&lt;/a&gt;. This is a book used as support for a course at University Politehnica of Bucharest, however, it’s also used by 15-year-olds participating in the &lt;a href=&quot;https://concurs.acadnet.eu/&quot;&gt;AcadNet&lt;/a&gt; competition. I think that professional DevOps engineers should have more knowledge than high-schoolers participating in local competitions 🧑‍🎓&lt;/p&gt;

&lt;h3 id=&quot;2-have-your-own-virtual-private-server-vps-and-self-host-stuff&quot;&gt;2) Have your own Virtual Private Server (VPS) and self-host stuff&lt;/h3&gt;

&lt;p&gt;There are cheap VPS providers around, like &lt;a href=&quot;https://www.hetzner.com/&quot;&gt;Hetzner&lt;/a&gt; or &lt;a href=&quot;https://www.netcup.com/&quot;&gt;Netcup&lt;/a&gt;. Get your own VPS. Then work your way to self-hosting your own services like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Static websites, served by Nginx (easiest)&lt;/li&gt;
  &lt;li&gt;VPN (WireGuard)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wordpress.org/&quot;&gt;WordPress&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://isso-comments.de/&quot;&gt;Isso commenting widget&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://matomo.org/&quot;&gt;Matomo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://linkding.link/&quot;&gt;Linkding&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/dani-garcia/vaultwarden&quot;&gt;Vaultwarden&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://freshrss.org/&quot;&gt;FreshRSS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.joinmastodon.org/user/run-your-own/&quot;&gt;Mastodon&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nextcloud.com/&quot;&gt;NextCloud&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many services you might want to host, depending on what you fancy (not email, don’t do that). Providing your family with online services might be good motivation. In the process you may learn how to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Keep backups, after you lose everything, which will happen at least once, &lt;a href=&quot;https://alexn.org/blog/2022/12/02/personal-server-backups/&quot;&gt;multiple kinds of backups&lt;/a&gt;, actually.&lt;/li&gt;
  &lt;li&gt;Harden your Linux server, after you leave a Redis port open on the Internet, and your server gets infected by malware mining for Bitcoin (true story).&lt;/li&gt;
  &lt;li&gt;Do automated upgrades and cleanups, because you don’t have the time or the attention span to keep it up to date, or to intervene when that server crashes due to low disk space.&lt;/li&gt;
  &lt;li&gt;Simplify hosting by using Docker containers, because you want easy installations, and a predictable environment that can be replicated.&lt;/li&gt;
  &lt;li&gt;Reinstall that Linux server from scratch, every once in a while, by switching VPS providers or taking advantage of lowering prices.&lt;/li&gt;
  &lt;li&gt;Write portable scripts for automated provisioning of new Linux servers, because remembering stuff just won’t cut it.&lt;/li&gt;
  &lt;li&gt;Keep those scripts in a Git repository, alongside other configuration or documentation you need; you need the ability to rebuild that server from scratch in a couple of hours, tops.&lt;/li&gt;
  &lt;li&gt;Find ways for continuous monitoring, to make your server as resilient as possible, because your personal brand or your family depends on it.&lt;/li&gt;
  &lt;li&gt;Find ways to block AI bots that can consume your bandwidth, or DDoS attacks; or optimize the server to withstand traffic sent due to your links trending on social media.&lt;/li&gt;
&lt;/ol&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; Pain is good! Embrace it, witness it, but don’t normalize it. It tells you when you need to find better solutions. Have the guts to say &lt;em&gt;“this sucks, I can do better!”&lt;/em&gt; Pain-driven development, as I like calling it 😄
&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
&lt;strong&gt;WARN:&lt;/strong&gt; You can also do home-automation, which can be a great motivation, but unless a Linux server is involved, a server that you administer, and that’s exposed to danger, it doesn’t count. Home automation stuff can be very user friendly and you won’t learn much.
&lt;/p&gt;

&lt;h3 id=&quot;3-learn-programming&quot;&gt;3) Learn Programming&lt;/h3&gt;

&lt;p&gt;The job of a DevOps includes “dev”. It’s in the job description. You mustn’t be just a user.&lt;/p&gt;

&lt;p&gt;The mentality of a DevOps engineer should be &lt;em&gt;“automate and monitor all the things”&lt;/em&gt;, with everything else being just red tape and drudgery getting in the way, also ripe for automation. So of course you need programming.&lt;/p&gt;

&lt;p&gt;As programming languages, at the very least, you need Bash and Python. Bash sucks, everyone hates it, but it’s everywhere and works for very simple scripts. You’ll need more than Bash, though.&lt;/p&gt;

&lt;p&gt;But don’t stop at just superficial knowledge about syntax. Learn basic algorithms and data structures, because you need to get into the right mindset. If you need motivation, consider that you need the knowledge of a 15-year-old in their freshman year at a high-school with a computer-science curriculum (from Romania, at least, I don’t know what high-schools teach in other countries). And don’t fool yourself about the existence of LLMs (AKA “AI”), because at the very least you need to know what to ask for, or to &lt;a href=&quot;https://alexn.org/blog/2025/11/16/programming-languages-in-the-age-of-ai-agents/&quot;&gt;review the generated code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The good news is that it’s easier than ever to learn, the Internet being filled with (often free) books or video tutorials, and you can also use ChatGPT for learning (when used in the right way, it can be useful). You can also join like-minded communities and seek help from others. Teach others, too, as becoming a teacher is the best way to go deep.&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
&lt;strong&gt;WARN:&lt;/strong&gt; you may expect your employer or your government to invest in your training, and that surely would be nice and wise, but it’s not really how the free market works. If you stagnate, or if you find yourself unable to get new jobs, it’s not your past or present employers’ responsibility, it’s not your government’s responsibility, it’s mostly yours. Sorry, I don’t make the rules.
&lt;/p&gt;

&lt;h3 id=&quot;4-be-a-cat-owner&quot;&gt;4) Be a Cat owner&lt;/h3&gt;

&lt;p&gt;You’re not a true DevOps if you don’t have a cat occasionally sitting on your keyboard, wreaking havoc.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/2025-cat-on-macbook.jpeg&quot; width=&quot;2000&quot; height=&quot;1500&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;p&gt;Cat sitting on Macbook keyboard (&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Cat_on_a_macbook.JPG&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Now go forth, self-host stuff, do programming, have fun, pet your cat, and learn some hard engineering skills 💪&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/11/26/how-to-become-a-good-devops-engineer/?pk_campaign=rss&quot;&gt;How To Become a DevOps Engineer&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 26 Nov 2025 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2025/11/26/how-to-become-a-good-devops-engineer/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/11/26/how-to-become-a-good-devops-engineer/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>DevOps</category>
  <category>Teaching</category>
  <category>Self Hosting</category>
  </item>


<item>
  <title>Programming Languages in the Age of AI Agents</title>
  <description>In the age of “AI” Agents generating the code, is your programming language choice still relevant? Or will we just converge on using the top 5 programming languages, because that’s what the “AI” has been trained on? You can also ask the same question for any other piece of tech from your stack.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
In the age of “AI” Agents generating the code, &lt;strong&gt;is your programming language choice still relevant?&lt;/strong&gt; Or will we just converge on using the top 5 programming languages, because that’s what the “AI” has been trained on? You can also ask the same question for any other piece of tech from your stack.
&lt;/p&gt;

&lt;p&gt;At work, I’ve built several Python scripts doing various boring chores. GitHub’s Copilot, powered by GPT or Claude Sonnet, does a reasonably good job at writing Python scripts. Furthermore, I’ve seen Python scripts developed by rookies that are worse than what these agents can generate. A programming language’s popularity is a feedback loop. These days, because Python is popular, having available a huge training corpus, “AI” agents can be successful at generating Python scripts that work, making Python even more popular.&lt;/p&gt;

&lt;p&gt;For programming language aficionados, for people loving their craft, while there is reason to worry that “AI” Agents can kill the long tail, I also think there are reasons to celebrate the dawn of “AI”. Here’s why:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) Having a compiler with an expressive static type system helps the “AI” Agent converge on a solution with a much shorter feedback loop.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“If it compiles, it runs”&lt;/em&gt; was never fully true, but in programming languages like Scala, Haskell, or Rust, our confidence in the code is indeed much higher once the code compiles.&lt;/p&gt;

&lt;p&gt;To give an example, Scala 3 has been on the market for a while, but there’s not much public code published that deals with Scala 3’s new macro system, and yet, “AI” Agents are able to generate code that works. This is very visible when using VS Code with GitHub Copilot, because it’s integrated with the LSP server, so you see its mistakes in real-time (&lt;a href=&quot;https://scalameta.org/metals/&quot;&gt;Metals&lt;/a&gt; being quick to highlight compilation errors); and so the agent goes through several iterations trying to fix whatever compiler error it sees; with the result most often being code that compiles.&lt;/p&gt;

&lt;p&gt;This ability to iterate and converge towards a working solution based on external feedback (from a compiler, from unit tests) is what makes “AI” Agents usable. And, having an expressive/powerful static type system provides much faster feedback than other validation types, such as unit tests. When people complain about Scala’s or Rust’s compilers being slow, they forget that they eliminate the need for unit tests guarding against entire classes of errors. And we need all the help we can get to guard against “AI” hallucinations 😉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) We need the ability to review what the “AI” Agent does. Can you reason about the generated code?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Programmers may describe &lt;em&gt;“what they want”&lt;/em&gt; instead of &lt;em&gt;“how”&lt;/em&gt; in natural language, however, they still need to ensure that they’re getting what they’ve asked for. Just executing the program, and looking at the output, is a very superficial way to test it, as we should all know by now. So at the very least you want tests, and tests are boring, we want them automated, so you want to see the tests that the agent has generated. Did the agent generate tests for the obvious edge cases? You can’t really say that without looking at the code.&lt;/p&gt;

&lt;p&gt;And there’s another looming issue that’s happening with agent-generated code that people aren’t aware of, yet: &lt;strong&gt;&lt;a href=&quot;https://codemanship.wordpress.com/2025/09/30/comprehension-debt-the-ticking-time-bomb-of-llm-generated-code/&quot;&gt;the comprehension debt&lt;/a&gt;&lt;/strong&gt;. You see, the software project isn’t just about telling the computer how it needs to behave, in order to produce some desired outcome. It’s also about the knowledge you’ve built along the way. And if you have no people left on the team that understand the inner workings of a project, you’re screwed. And “AI” Agents won’t help, because they have a limited context window that tends to vanish. You won’t keep around the dialogs you have with the agent, and even if you do, that kind of documentation is poor and can be misinterpreted; context poisoning is also a thing.&lt;/p&gt;

&lt;p&gt;Peter Naur writes in &lt;a href=&quot;https://pages.cs.wisc.edu/~remzi/Naur.pdf&quot;&gt;Programming as Theory Building&lt;/a&gt; that:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“&lt;em&gt;Although it is essential to upgrade software to prevent aging, changing software can cause a different form of aging. The designer of a piece of software usually had a simple concept in mind when writing the program. If the program is large, understanding that concept allows one to find those sections of the program that must be altered when an update or correction is needed. Understanding that concept also implies understanding the interfaces used within the system and between the system and its environment.&lt;/em&gt;”&lt;/p&gt;

  &lt;p&gt;“&lt;em&gt;Changes made by people who do not understand the original design concept almost always cause the structure of the program to degrade. Under those circumstances, changes will be inconsistent with the original concept; in fact, they will invalidate the original concept. Sometimes the damage is small, but often it is quite severe. After those changes, one must know both the original design rules, and the newly introduced exceptions to the rules, to understand the product. After many such changes, the original designers no longer understand the product. Those who made the changes, never did. In other words, nobody understands the modified product. Software that has been repeatedly modified (maintained) in this way becomes very expensive to update. Changes take longer and are more likely to introduce new “bugs”. Change induced aging is often exacerbated by the fact that the maintainers feel that they do not have time to update the documentation. The documentation becomes increasingly inaccurate thereby making future changes even more difficult.&lt;/em&gt;”&lt;/p&gt;

  &lt;p&gt;…&lt;/p&gt;

  &lt;p&gt;“&lt;em&gt;At least with certain kinds of large programs, the continued adaptation, modification, and correction of errors in them, is essentially dependent on a certain kind of knowledge possessed by a group of programmers who are closely and continuously connected with them.&lt;/em&gt;”&lt;/p&gt;

  &lt;p&gt;“&lt;em&gt;Programming should be regarded as an activity by which the programmers form or achieve a certain kind of insight, a theory, of the matters at hand. This suggestion is in contrast to what appears to be a more common notion, that programming should be regarded as a production of a program and certain other texts.&lt;/em&gt;”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the same time, it’s still true that the &lt;em&gt;source of truth&lt;/em&gt; is the source code itself, always has been, always will be. So how do you preserve knowledge, despite the natural churn and evolution that happens in software projects?&lt;/p&gt;

&lt;p&gt;Well, one way of doing it is with great source code that makes design and intent clear. And great source code is like math, ageless, describing what you want, not how, with an architecture that allows for evolution, but at the same time makes clear the design’s invariants, i.e., its so-called laws. Programming in a higher-level language matters for “AI” Agents as well. It matters if the source code fully describes the specifications (e.g., the original intent or design constraints) or not. “AI” Agents may be good at assembly language, but they can’t be that good, given that serializing specs in assembly is a lossy process.&lt;/p&gt;

&lt;p&gt;And for reviewing the source code, &lt;a href=&quot;https://en.wikipedia.org/wiki/Deductive_reasoning&quot;&gt;deductive reasoning&lt;/a&gt; will never go out of fashion, because it’s how the human brains work. Therefore, &lt;a href=&quot;https://alexn.org/blog/2017/10/15/functional-programming/&quot;&gt;functional programming&lt;/a&gt; with its “&lt;em&gt;equational reasoning&lt;/em&gt;” is still valuable in the age of “AI” Agents, and arguably, even more so, because you’re dealing with &lt;a href=&quot;https://alexn.org/blog/2025/10/27/ai-sucks-the-joy-out-of-programming/&quot;&gt;an inconsistent idiot that can’t learn&lt;/a&gt;.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/11/16/programming-languages-in-the-age-of-ai-agents/?pk_campaign=rss&quot;&gt;Programming Languages in the Age of AI Agents&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 16 Nov 2025 06:14:15 +0000</pubDate>
  <dc:modified>Sun, 16 Nov 2025 11:21:32 +0000</dc:modified>
  <atom:modified>Sun, 16 Nov 2025 11:21:32 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/11/16/programming-languages-in-the-age-of-ai-agents/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/11/16/programming-languages-in-the-age-of-ai-agents/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>AI</category>
  <category>FP</category>
  <category>Opinion</category>
  <category>Programming</category>
  <category>Languages</category>
  </item>


<item>
  <title>Try-catch-finally in Java is Cursed</title>
  <description>In Java, try-catch-finally can ignore returns, mask exceptions, and breaks the interruption protocol.</description>
  <content:encoded>&lt;p&gt;Java has a usable interruption protocol, and that’s good. However, one problem with it is that it relies on &lt;code&gt;InterruptedException&lt;/code&gt;, and it can be caught and ignored. Being a “checked exceptions”, many developers simply ignore it&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;BlockingQueue&lt;Task&gt; queue;
// ...
while (isActive) {
  try {
    var task = queue.take();
    process(task);
  } catch (InterruptedException e) {
    // ignore
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are reasons for why you may want to react to a thread interrupt. Maybe you want to close some resources. What’s bad about it is that you can continue as if nothing happened.&lt;/p&gt;

&lt;p&gt;But it’s not just the interruption protocol that’s problematic here, but the semantic of &lt;code&gt;try-catch-finally&lt;/code&gt; as well (&lt;a href=&quot;https://news.ycombinator.com/item?id=45808899&quot;&gt;sample attribution&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
void infiniteLoop() {
  while (true) {
    try { return; } 
    finally { continue; }
  }
}

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

&lt;p&gt;Yep, you can ignore &lt;code&gt;return&lt;/code&gt;, too. This works as well:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;try {
  return 42;
} finally {
  // What actually gets returned
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, exception suppression — in this case, the client won’t get &lt;code&gt;FileNotFoundException&lt;/code&gt;, not even as a “suppressed” exception.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;try {
  // can throw FileNotFoundException
  return Files.readString(Path.of(&quot;missing.txt&quot;)); 
} finally {
  throw new RuntimeException(&quot;Cleanup failed&quot;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you think this can’t happen, consider the classic resource-usage pattern:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;InputStream in = ...;
try {
  process(in);
} finally {
  // can throw IOException, masking any exception 
  // that happened in `process`
  in.close(); 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Thankfully, this is improved by &lt;code&gt;try-with-resources&lt;/code&gt;, in which case the exception thrown by &lt;code&gt;close()&lt;/code&gt; gets added as a “suppressed” exception to the one thrown by the &lt;code&gt;try&lt;/code&gt; block.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/11/10/try-catch-finally-in-java-is-cursed/?pk_campaign=rss&quot;&gt;Try-catch-finally in Java is Cursed&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 10 Nov 2025 09:54:08 +0000</pubDate>
  <dc:modified>Fri, 14 Nov 2025 08:18:11 +0000</dc:modified>
  <atom:modified>Fri, 14 Nov 2025 08:18:11 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/11/10/try-catch-finally-in-java-is-cursed/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/11/10/try-catch-finally-in-java-is-cursed/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Java</category>
  <category>Programming</category>
  </item>


<item>
  <title>Scala vs F#</title>
  <description>Which language leans more towards functional programming? In this binary choice, people have perceived F# to be that language, due to its ML roots, but I have a different perspective…</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2025/11/01/scala-vs-fsharp/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2025-scala-vs-fsharp.png?202603060940&quot; alt=&quot;&quot; width=&quot;1400&quot; height=&quot;800&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Scala logo on the left, F# logo on the right.
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Which language leans more towards functional programming? In this binary choice, people have perceived F# to be that language, due to its ML roots, but I have a different perspective... 
&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
&lt;strong&gt;Before bringing your pitchforks:&lt;/strong&gt; I’m an expert in Scala, but I only have superficial experience with F#, so take this opinion for what it is. I also think both languages are great, and this is just an opinion on which one I prefer.
&lt;/p&gt;

&lt;p&gt;F# is a wonderful language, and the primary choice between Scala and F# would actually be driven by your preferred choice of platform and ecosystem (JVM vs .NET). That being said,&lt;/p&gt;

&lt;p&gt;Scala is actually a more “functional” language than F# because it wins in the expressiveness and the FP culture departments.&lt;/p&gt;

&lt;p&gt;First, in Scala, you can work with higher-kinded types and type classes. To understand why that’s important, consider that Scala does not need .NET’s flavor of reification for generics because what it has is far more potent. These are features that Don Syme &lt;a href=&quot;https://github.com/fsharp/fslang-suggestions/issues/243#issuecomment-916079347&quot;&gt;has been explicitly against&lt;/a&gt; because, according to him, it complicates the type system. This is partially true, I’m actually inclined to agree; however, in my experience, the actual problems in programming come from elsewhere, code reuse and static type-safety being good. And I’d also argue that this opinion against type-classes and higher-kinds may also be due to bias, with .NET itself making higher-kinds more complicated due to its runtime-based reification (you can do type-erasure on .NET, but people and libraries expect reification, which would mean interop would suffer). The irony of .NET’s original marketing is that the JVM has been an easier-to-target platform for languages that are not Java or C#.&lt;/p&gt;

&lt;p&gt;To give an example of a type-class in action:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala 3
def sumList[A](list: List[A])(using Numeric[A]): A =
    val n = summon[Numeric[A]]
    list.foldLeft(n.zero)(n.plus)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I hope I’m not getting this wrong, it’s been a while since I worked with F#, but its standard library does something like this, which isn’t something you actually see in common code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-fsharp&quot;&gt;// F#
let inline sumList (list: ^T list) : ^T 
    when ^T : (static member (+) : ^T * ^T -&gt; ^T) 
    and ^T : (static member Zero : ^T) =
    List.fold (+) LanguagePrimitives.GenericZero list
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To note:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Scala’s version is a simple function making use of implicit parameters, &lt;code&gt;Numeric&lt;/code&gt; being a type-class;&lt;/li&gt;
  &lt;li&gt;F#’s version is an &lt;code&gt;inline&lt;/code&gt; function (due to adding restrictions not natively supported by .NET), and the restrictions refer to “static members” — note that Scala no longer has the notion of “static methods” in the language (although the JVM does).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can express this in the latest C#, actually, as they’ve added &lt;em&gt;“abstract static methods”&lt;/em&gt; (&lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/static-abstracts-in-interfaces&quot;&gt;link&lt;/a&gt;), which are frowned upon in F#, the general advice for F# devs being to steer clear of them, unless they need it for interop. So, C# almost has type classes.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-csharp&quot;&gt;// C#
interface INumeric&lt;T&gt; where T : INumeric&lt;T&gt;
{
    static abstract T Zero { get; }
    static abstract T Plus(T a, T b);
}

static T SumList&lt;T&gt;(List&lt;T&gt; list) where T : INumeric&lt;T&gt;
{
    return list.Aggregate(T.Zero, (acc, x) =&gt; T.Plus(acc, x));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But, let’s go one more level — we can work on any list-like type, that we can express as a type parameter, and note that working with a generic type restricted to implementing &lt;code&gt;Foldable&lt;/code&gt; is different in nature to using &lt;code&gt;Iterable&lt;/code&gt; / &lt;code&gt;Enumerator&lt;/code&gt; (OOP subtyping):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala 3
import cats.Foldable
import cats.syntax.all.given

def sumAll[F[_], A](list: F[A])(using Foldable[F], Numeric[A]): A =
    val n = summon[Numeric[A]]
    list.foldLeft(n.zero)(n.plus)

// Now it works for any sequence
sumAll(Vector(1,2,3))
sumAll(List(1,2,3))
sumAll(Array(1,2,3))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The true power of higher-kinds manifests when we have to keep that list type in the returned value, something that OOP subtyping (or .NET’s generics reification) can’t achieve:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala 3
import cats.{Foldable, MonoidK}

def flatten[F[_], A](list: F[F[A]])(using Foldable[F], MonoidK[F]): F[A] =
    val m = summon[MonoidK[F]]
    list.foldLeft(m.empty[A])(m.combineK)

// Note how the type gets preserved
val l1: List[Int] = 
    flatten(List(List(1,2,3), List(4,5,6)))
val l2: Array[Int] =
    flatten(Array(Array(1,2,3), Array(4,5,6)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And there’s a lot more to talk about here, such as the ability to auto-derive type-class instances, which in Scala is great. For instance, in Scala, you can develop something like &lt;a href=&quot;https://kotlinlang.org/docs/serialization.html&quot;&gt;Kotlin Serialization&lt;/a&gt; as a library, a library that can work for basic needs and that’s very type-safe, in a day. You don’t even need macros for it, unless you want customizability (e.g., by annotations).&lt;/p&gt;

&lt;p&gt;This difference is not only academic, manifesting itself for example in F#’s &lt;a href=&quot;https://github.com/fsprojects/FSharp.Control.AsyncSeq&quot;&gt;AsyncSeq&lt;/a&gt;, which is a library combining &lt;code&gt;Async&lt;/code&gt; with &lt;code&gt;Seq&lt;/code&gt;. This is nice and all, but in Scala, all the features in this &lt;code&gt;AsyncSeq&lt;/code&gt; are expressed more generically in the &lt;a href=&quot;https://typelevel.org/cats/&quot;&gt;Typelevel Cats&lt;/a&gt; library, increasing reuse for other types. To make a comparison, it’s like in Go, when people needing generics were simply duplicating the code for all the types they care about. This arguably works for some common cases, but also sucks.&lt;/p&gt;

&lt;p&gt;F# does have Hindley-Milner type inference, however, it only works as long as OOP subtyping isn’t involved, and due to its .NET interop and dependence, it has a lot of OOP subtyping. Hindley-Milner in general, being a type system with global type inference, makes error messages hard to read and understand, although, granted, this is more relevant in languages with more advanced type systems. Even in languages with HM (e.g., Haskell), the general advice is for public functions to have explicit types; otherwise the contract exposed is fragile. And also, the more advanced the type system, the more difficult HM becomes. For example, the more advanced features of Haskell you use, the more HM breaks down. See also Idris, in which type inference is undecidable in general.&lt;/p&gt;

&lt;p&gt;I always felt that this is a general problem with F#, inspired by two separate worlds, and not trying hard enough to combine them. For example, its generic types can have restrictions that can’t be expressed in .NET (like in the &lt;code&gt;sumList&lt;/code&gt; above). Therefore, to use them, you can only use &lt;code&gt;inline&lt;/code&gt; functions, which are functions that are not seen by the .NET runtime, so they can’t be passed around as &lt;em&gt;values&lt;/em&gt;. In fairness, Scala 3 makes heavy use of &lt;code&gt;inline&lt;/code&gt; functions as well, for compile-time magic and macros, but in Scala you can use inline functions to reify types and then expose any compile-time information to normal functions, via implicit parameters. So it doesn’t have the mixture I’ve felt while using F#.&lt;/p&gt;

&lt;p&gt;F# has a sort of mixed personality to it, not trying too much to mix the functional aspects with OOP, like Scala or OCaml are trying. This can be considered a feature, except, one interacts with .NET and OOP &lt;em&gt;a lot&lt;/em&gt; in F#, more than in your typical Scala FP project (IMO, YMMV). To give one example, when I last tried, in F# serialization was still done using runtime reflection, whereas in Scala we have libraries like &lt;a href=&quot;https://github.com/circe/circe&quot;&gt;Circe&lt;/a&gt; which work entirely at compile-time, providing static type-safety, and exposing a very FP API. If you compare .NET’s solutions for serialization with Java’s Jackson, for sure, .NET wins due to generics reification, but if you compare .NET with Scala’s solutions, or even with Kotlin’s Serialization, it leaves something to be desired (in the type-safety department, at least).&lt;/p&gt;

&lt;p&gt;Back to the FP aspects, Scala has a very healthy ecosystem of FP libraries. FP has been so successful in Scala that it ended up with two mature and competing ecosystems for it, i.e. &lt;a href=&quot;https://typelevel.org/&quot;&gt;Typelevel&lt;/a&gt; and &lt;a href=&quot;https://zio.dev/&quot;&gt;ZIO&lt;/a&gt;. Scala has one of the best books on FP around: &lt;a href=&quot;https://www.manning.com/books/functional-programming-in-scala-second-edition&quot;&gt;FP in Scala&lt;/a&gt;. And it has also inspired other ecosystems, see &lt;a href=&quot;https://github.com/Effect-TS/effect&quot;&gt;Effect&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that there are aspects of F# that I like. Off the top of my head, I can think of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/fsharp/tutorials/type-providers/&quot;&gt;Type providers&lt;/a&gt; — you could build something similar in Scala in a library, actually, however it’s challenging, and I haven’t seen something polished yet;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions&quot;&gt;Computation expressions&lt;/a&gt; — Scala has “for comprehensions”, but F#’s computation expressions are more evolved; this is for working with “monadic” or “applicative” types, but note that Scala also has plans to go the way of Kotlin and provide &lt;a href=&quot;https://alexn.org/blog/2025/08/29/scala-gamble-with-direct-style/&quot;&gt;direct style support&lt;/a&gt; (thus providing an alternative to monads because it was too boring before 😜);&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/query-expressions&quot;&gt;LINQ support&lt;/a&gt; — Scala has had libraries that are equivalent, such as &lt;a href=&quot;https://github.com/zio/zio-protoquill&quot;&gt;Quill&lt;/a&gt;, and while it’s nice that in Scala we can bring the full power of LINQ as a library, I also feel that proper support needs to be baked into the language, or it’s forever plagued with issues;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/active-patterns&quot;&gt;Active patterns&lt;/a&gt;, although Scala’s pattern matching is quite nice, too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;F# also has features that Scala can do better, but that are nice to have regardless, and worth mentioning, such as “units of measure” or “code quotations”.&lt;/p&gt;

&lt;p&gt;F# resembles Python, in the sense that its designers have introduced features to solve concrete use-cases. But, just like in Python, it has features that don’t feel orthogonal or very generic; in Python, for instance, I can think of several features that were added to avoid adding multi-line lambdas. So much for the &lt;em&gt;“one way of doing things”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But overall, F# is a language I would enjoy very much, if I wanted to target .NET. And .NET can be … an acquired taste.&lt;/p&gt;

&lt;p&gt;I’ve always preferred the Java ecosystem because it has always been closer in spirit and culture to Linux and Open-Source. This has pros and cons. .NET feels more like a cathedral and Java feels more like a bazaar. In terms of ecosystem, the difference is night and day. For instance, Oracle has a lot of power, as they still develop and own Java, but they don’t provide the IDE or the libraries or the tooling most people use. They don’t even have the most popular OpenJDK distribution. And if they stop being good stewards, OpenJDK can get forked, as they aren’t the only contributors to it. I like having competition, choices, communities (plural), instead of having Microsoft impose its solution du jour.&lt;/p&gt;

&lt;p&gt;The JVM also has had a great evolution, in some ways leapfrogging .NET (e.g., runtime optimizations, the “pauseless” GC implementations Project Loom, GraalVM), and in some ways closing the gaps (upcoming Valhalla, which finally brings value types and maybe generics specialization). There’s still plenty of healthy competition going on. .NET going for ‘abstract static methods’, being close to type-classes, is forcing Java to push for &lt;a href=&quot;https://youtu.be/Gz7Or9C0TpM&quot;&gt;type-classes support&lt;/a&gt;. Fun times.&lt;/p&gt;

&lt;p&gt;People do have good reasons to love the .NET ecosystem as well, since it has evolved a lot, too. It’s now open-source, multi-platform, performant, and it’s still the preferred high-level platform for games — which is why I may teach my son some C# or F# 😁&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/11/01/scala-vs-fsharp/?pk_campaign=rss&quot;&gt;Scala vs F#&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sat, 01 Nov 2025 06:58:37 +0000</pubDate>
  <dc:modified>Sun, 02 Nov 2025 06:09:06 +0000</dc:modified>
  <atom:modified>Sun, 02 Nov 2025 06:09:06 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/11/01/scala-vs-fsharp/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/11/01/scala-vs-fsharp/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  <category>FSharp</category>
  <category>JVM</category>
  <category>dotNet</category>
  </item>


<item>
  <title>Scala 3 / HOCON Parsing</title>
  <description>How to parse HOCON in Scala 3? How to use Circe for HOCON? How to work with multiple JSON codecs per data structure?</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2025/10/30/scala-3-hocon-parsing/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2025-scala-configcodec.png?202603060940&quot; alt=&quot;&quot; width=&quot;1132&quot; height=&quot;504&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  How to parse HOCON in Scala 3? How to use Circe for HOCON? How to work with multiple JSON codecs per data structure?
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
This article is using Scala 3 with &lt;a href=&quot;https://alexn.org/blog/2025/10/26/scala-3-no-indent/&quot;&gt;-no-indent&lt;/a&gt;. And this file is executable with &lt;a href=&quot;https://scala-cli.virtuslab.org/docs/guides/power/markdown&quot;&gt;Scala CLI’s Markdown support&lt;/a&gt; 🤖
&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;scala --power --enable-markdown \
  https://raw.githubusercontent.com/alexandru/alexn.org/refs/heads/main/_posts/2025-10-30-scala-3-hocon-parsing.md
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’ve just started migrating our project at work to Scala 3. It’s a work-in-progress, but it’s been going well, and thus far the biggest roadblock has been the &lt;a href=&quot;https://github.com/pureconfig/pureconfig&quot;&gt;PureConfig library&lt;/a&gt;, an awesome library, but it didn’t seem to have complete support for Scala 3. In particular, it doesn’t seem to have support for &lt;code&gt;ConfigWriter&lt;/code&gt; derivation, yet. So I’ve started to think of alternatives.&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot; name=&quot;update-1&quot;&gt;
&lt;strong&gt;UPDATE:&lt;/strong&gt; PureConfig apparently has &lt;code&gt;ConfigWriter&lt;/code&gt; derivation in the codebase, as part of a different module, found out about it from this &lt;a href=&quot;https://old.reddit.com/r/scala/comments/1okokac/scala_3_hocon_parsing/nmc3s2u/&quot;&gt;Reddit comment&lt;/a&gt;: see &lt;a href=&quot;https://github.com/pureconfig/pureconfig/blob/1f272aa/modules/generic-scala3/src/main/scala/pureconfig/generic/scala3/HintsAwareConfigWriterDerivation.scala&quot;&gt;source code&lt;/a&gt;, added in &lt;a href=&quot;https://github.com/pureconfig/pureconfig/pull/1671&quot;&gt;this PR&lt;/a&gt;. I don’t know how well it works, but it’s encouraging. Unfortunately, I checked the status by just &lt;a href=&quot;https://pureconfig.github.io/docs/scala-3-derivation.html#limitations&quot;&gt;looking at outdated docs&lt;/a&gt; 🤦‍♂️
&lt;/p&gt;

&lt;p&gt;One solution I’ve found is to use the &lt;a href=&quot;https://github.com/circe/circe&quot;&gt;circe&lt;/a&gt; library, with &lt;a href=&quot;https://github.com/circe/circe-config&quot;&gt;circe-config&lt;/a&gt;. And here-in lie challenges:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Rewriting the configuration files is not an option:
    &lt;ul&gt;
      &lt;li&gt;PureConfig used &lt;code&gt;kebab-case&lt;/code&gt; for its keys;&lt;/li&gt;
      &lt;li&gt;It also allowed us to use &lt;code&gt;type = type-name&lt;/code&gt; for discriminating union types.&lt;/li&gt;
      &lt;li&gt;Any solution we pick needs to be configured for these conventions.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Deriving the type-class instances should be painless — people shouldn’t need to remember an import.&lt;/li&gt;
  &lt;li&gt;We also do JSON encodings with &lt;code&gt;camelCase&lt;/code&gt; via Circe, sometimes for types that are also used in configuration files, therefore those types need different HOCON config vs JSON encodings.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So in summary:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Circe needs to be configured to parse and generate HOCON;&lt;/li&gt;
  &lt;li&gt;The type-class instances need to be different, but still globally visible — to avoid conflicts and preserve “type-class coherence”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Starting with some dependencies:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//&gt; using scala &quot;3.3.7&quot;
//&gt; using dep &quot;io.circe::circe-core:0.14.15&quot;
//&gt; using dep &quot;io.circe::circe-config:0.10.2&quot;
//&gt; using options -no-indent
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In order to respect our HOCON’s conventions, we needed a Circe Configuration:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import io.circe.derivation.Configuration

given hoconConventions: Configuration = {
  val kebabCase: String =&gt; String =
    _.replaceAll(&quot;([a-z])([A-Z])&quot;, &quot;$1-$2&quot;).toLowerCase

  Configuration.default
    .withTransformMemberNames(kebabCase)
    .withDiscriminator(&quot;type&quot;)
    .withTransformConstructorNames(kebabCase)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that with Circe, the auto-derivation we want goes something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class HttpConfig(
  hostname: String,
  port: Int,
  contextPath: Option[String]
)

object HttpConfig {
  given Codec[HttpConfig] = 
    Codec.AsObject.derivedConfigured
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As mentioned before, I’d rather have a different type-class, and I don’t want to have to remember to import &lt;code&gt;hoconConventions&lt;/code&gt;, but we can just create different type-classes that wrap Circe’s:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import io.circe.{Encoder, Decoder, Codec}

trait ConfigEncoder[A] {
  def encoder: Encoder.AsObject[A]
}

trait ConfigDecoder[A] {
  def decoder: Decoder[A]
}

trait ConfigCodec[A]
  extends ConfigEncoder[A]
  with ConfigDecoder[A] {

  def codec: Codec.AsObject[A]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The difficult part is auto-deriving these, but thankfully, Scala 3 makes it easy:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.deriving.Mirror

object ConfigEncoder {
  // Calling `derivedConfigured` ourselves, then wrapping it
  //
  inline def derived[A](using inline A: Mirror.Of[A]): ConfigEncoder[A] = {
    // IMPORTANT — Scala needs to know how to derive
    // a Circe `Encoder` from a `ConfigEncoder`.
    import Givens.given
    
    val underlying = io.circe.Encoder.AsObject.derivedConfigured[A]
    Derived(underlying)
  }

  final private case class Derived[A](encoder: Encoder.AsObject[A])
    extends ConfigEncoder[A]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Importantly, Scala must find the defined encoders for a class’s fields, therefore it must have a way to convert from &lt;code&gt;ConfigEncoder&lt;/code&gt; into &lt;code&gt;io.circe.Encoder&lt;/code&gt; and from &lt;code&gt;ConfigDecoder&lt;/code&gt; to &lt;code&gt;io.circe.Decoder&lt;/code&gt;. But these need to be imported only in the lexical scope of those &lt;code&gt;inline def derived&lt;/code&gt; functions:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;private object Givens {
  given circeEncoder[A](using encoder: ConfigEncoder[A]): Encoder.AsObject[A] =
    encoder.encoder

  given circeDecoder[A](using decoder: ConfigDecoder[A]): Decoder[A] =
    decoder.decoder
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Similarly, we describe the derivation logic for &lt;code&gt;ConfigDecoder&lt;/code&gt; and &lt;code&gt;ConfigCodec&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object ConfigDecoder {
  inline def derived[A](using inline A: Mirror.Of[A]): ConfigDecoder[A] = {
    // IMPORTANT — Scala needs to know how to derive
    // a Circe `Encoder` from a `ConfigEncoder`.
    import Givens.given
    val underlying = Decoder.derivedConfigured[A]
    Derived(underlying)
  }

  final private case class Derived[A](decoder: Decoder[A])
    extends ConfigDecoder[A]
}

object ConfigCodec {
  inline def derived[A](using inline A: Mirror.Of[A]): ConfigCodec[A] = {
    // IMPORTANT — Scala needs to know how to derive
    // a Circe `Encoder` from a `ConfigEncoder`.
    import Givens.given
    val underlying = Codec.AsObject.derivedConfigured[A]
    Derived(underlying)
  }

  final private case class Derived[A](codec: Codec.AsObject[A]) 
    extends ConfigCodec[A] {
    override def decoder = codec
    override def encoder = codec
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, so I think we can do better than this with some utilities. This is a copy/paste-able snippet:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigRenderOptions
import com.typesafe.config.ConfigValue
import com.typesafe.config.ConfigValueFactory
import io.circe.derivation.Configuration
import io.circe.syntax.given
import io.circe.Codec
import io.circe.Decoder
import io.circe.Encoder
import io.circe.Json
import scala.deriving.Mirror
import scala.jdk.CollectionConverters.*

trait ConfigEncoder[A] {
  def encoder: io.circe.Encoder.AsObject[A]

  extension (a: A) {
    def toRawConfig: Config = {
      given Encoder.AsObject[A] =
        encoder
      ConfigFactory.empty().withFallback(
        jsonToConfigValue(a.asJson)
      )
    }

    def renderConfigString: String =
      toRawConfig.root().render(renderOptions)
  }
}

object ConfigEncoder {
  inline def derived[A](using inline A: Mirror.Of[A]): ConfigEncoder[A] = {
    import Givens.given
    val underlying = io.circe.Encoder.AsObject.derivedConfigured[A]
    Derived(underlying)
  }

  final private case class Derived[A](encoder: Encoder.AsObject[A])
    extends ConfigEncoder[A]
}

trait ConfigDecoder[A] {
  def decoder: io.circe.Decoder[A]

  final def decodeConfig(
    config: com.typesafe.config.Config
  ): Either[io.circe.Error, A] = {
    import io.circe.config.parser
    parser.decode[A](config)(using decoder)
  }

  final def parseConfigString(
    configString: String
  ): Either[io.circe.Error, A] = {
    val config = ConfigFactory.parseString(configString)
    decodeConfig(config)
  }
}

object ConfigDecoder {
  def apply[A](using ConfigDecoder[A]): ConfigDecoder[A] =
    summon[ConfigDecoder[A]]

  inline def derived[A](using inline A: Mirror.Of[A]): ConfigDecoder[A] = {
    import Givens.given
    val underlying = Decoder.derivedConfigured[A]
    Derived(underlying)
  }

  final private case class Derived[A](decoder: Decoder[A])
    extends ConfigDecoder[A]
}

trait ConfigCodec[A]
  extends ConfigEncoder[A]
  with ConfigDecoder[A] {

  def codec: Codec.AsObject[A]
}

object ConfigCodec {
  inline def derived[A](using inline A: Mirror.Of[A]): ConfigCodec[A] = {
    import Givens.given
    val underlying = Codec.AsObject.derivedConfigured[A]
    Derived(underlying)
  }

  final private case class Derived[A](codec: Codec.AsObject[A]) extends ConfigCodec[A] {
    override def decoder =
      codec
    override def encoder =
      codec
  }
}

private object Givens {
  given circeEncoder[A](using encoder: ConfigEncoder[A]): Encoder.AsObject[A] =
    encoder.encoder

  given circeDecoder[A](using decoder: ConfigDecoder[A]): Decoder[A] =
    decoder.decoder

  given hoconConventions: Configuration =
    Configuration.default
      .withTransformMemberNames(kebabCase)
      .withDiscriminator(&quot;type&quot;)
      .withTransformConstructorNames(kebabCase)

  private val kebabCase: String =&gt; String =
    _.replaceAll(&quot;([a-z])([A-Z])&quot;, &quot;$1-$2&quot;).toLowerCase
}

private def jsonToConfigValue(json: Json): ConfigValue =
  json.fold(
    ConfigValueFactory.fromAnyRef(null),
    boolean =&gt; ConfigValueFactory.fromAnyRef(boolean),
    number =&gt;
      number.toLong match {
        case Some(long) =&gt; ConfigValueFactory.fromAnyRef(long)
        case None =&gt; ConfigValueFactory.fromAnyRef(number.toDouble)
      },
    str =&gt; ConfigValueFactory.fromAnyRef(str),
    arr =&gt; ConfigValueFactory.fromIterable(arr.map(jsonToConfigValue).asJava),
    obj =&gt; ConfigValueFactory.fromMap(obj.toMap.view.mapValues(jsonToConfigValue).toMap.asJava)
  )

private val renderOptions =
  ConfigRenderOptions
    .defaults()
    .setOriginComments(false)
    .setComments(true)
    .setFormatted(true)
    .setJson(false)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To test it, we first define a more complex data structure:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Providing both HOCON and JSON codecs, separately 
// (to prove it works)

final case class AppConfig(
  appName: String,
  http: HttpConfig,
  inputConfig: InputConfig
) derives ConfigCodec, Codec.AsObject

final case class HttpConfig(
  hostname: String,
  port: Int,
  contextPath: Option[String]
) derives ConfigCodec, Codec.AsObject

sealed trait InputConfig derives ConfigCodec, Codec.AsObject

object InputConfig {
  final case class Kafka(
    bootstrapServers: String,
    topic: String,
    groupId: String
  ) extends InputConfig derives ConfigCodec, Codec.AsObject

  final case class IbmMq(
    queueManager: String,
    channel: String,
    connectionName: String,
    queueName: String
  ) extends InputConfig derives ConfigCodec, Codec.AsObject
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then we can test it by decoding and the re-encoding, for both HOCON and JSON, to prove a point:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.syntax.all.*

val appConfigHocon = &quot;&quot;&quot;
app-name = &quot;my-app&quot;

http {
  hostname = &quot;localhost&quot;
  port = 8081
  context-path = &quot;/mq&quot;
}

input-config {
  type = ibm-mq
  queue-manager = &quot;QM1&quot;
  channel = &quot;CHANNEL1&quot;
  connection-name = &quot;localhost(1414)&quot;
  queue-name = &quot;VESPER.QUEUE&quot;
}
&quot;&quot;&quot;

val appConfigFromHocon = ConfigDecoder[AppConfig]
  .parseConfigString(appConfigHocon)
  .valueOr(throw _)
// encode it again and print it
println(&quot;FROM HOCON:\n---------&quot;)
println(appConfigFromHocon.renderConfigString)

// Proving that we have different codecs for JSON 
// (with different conventions):
val appConfigJson = &quot;&quot;&quot;
{
  &quot;appName&quot; : &quot;vesper-app-mq&quot;,
  &quot;http&quot; : {
    &quot;hostname&quot; : &quot;localhost&quot;,
    &quot;port&quot; : 8081,
    &quot;contextPath&quot; : &quot;/mq&quot;
  },
  &quot;inputConfig&quot; : {
    &quot;IbmMq&quot; : {
      &quot;queueManager&quot; : &quot;QM1&quot;,
      &quot;channel&quot; : &quot;CHANNEL1&quot;,
      &quot;connectionName&quot; : &quot;localhost(1414)&quot;,
      &quot;queueName&quot; : &quot;VESPER.QUEUE&quot;
    }
  }
}
&quot;&quot;&quot;

import io.circe.parser.decode
import io.circe.syntax.*

val appConfigFromJson = 
  decode[AppConfig](appConfigJson).valueOr(throw _)

println(&quot;FROM JSON:\n---------&quot;)
println(appConfigFromJson.asJson.spaces2)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; you just learned to provide multiple JSON encodings for THE SAME data-structures. Pretty cool, huh? 😉&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/10/30/scala-3-hocon-parsing/?pk_campaign=rss&quot;&gt;Scala 3 / HOCON Parsing&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 30 Oct 2025 17:33:31 +0000</pubDate>
  <dc:modified>Fri, 31 Oct 2025 10:23:27 +0000</dc:modified>
  <atom:modified>Fri, 31 Oct 2025 10:23:27 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/10/30/scala-3-hocon-parsing/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/10/30/scala-3-hocon-parsing/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  <category>Scala 3</category>
  <category>Programming</category>
  <category>Snippet</category>
  </item>


<item>
  <title>&#39;AI&#39; Sucks the Joy Out of Programming</title>
  <description>I’ve used spicy auto-complete, as well as agents running in my IDE, in my CLI, or on GitHub’s server-side. I’ve been experimenting enough with LLM/AI-driven programming to have an opinion on it. And it kind of sucks.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2025/10/27/ai-sucks-the-joy-out-of-programming/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2025-my-dogs.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;2000&quot; height=&quot;1250&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Talking with my dogs brings me greater pleasure, and I think it helps me get more work done.
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p&gt;I now think that AI/LLMs suck the joy out of programming. I’ve used spicy auto-complete, as well as agents running in my IDE, in my CLI, or on GitHub’s server-side. I’ve been experimenting enough with LLM/AI-driven programming to have an opinion on it. And it kind of sucks.&lt;/p&gt;

&lt;p&gt;I started programming when I was around 15 years old, and I’ve had about 28 years of pleasure from doing it. What I like the most is when things finally end up working, in the way I want them to work, and that happens after gradually building an understanding of the problem space, and of the algorithms used. It’s not just the destination, but the journey for getting there. There is nothing more gratifying than mastering some algorithm or technique, or finally understanding the problem that I need to solve.&lt;/p&gt;

&lt;p&gt;What I don’t like about programming is when things fail, and they fail for stupid reasons, such as a small detail I missed, and it nearly always happens either because I’m not paying attention, or because my understanding is incomplete, and I just copied some solution from somewhere, and it was a bad solution to begin with. For example, concurrency or performance problems are the worst, especially because they tend to be non-deterministic, and the documentation isn’t easily accessible, so you put together bits and pieces from the Internet. And I hate such parts because I end up with a trial-and-error workflow where I desperately try things out, in what can only be described as &lt;em&gt;“shooting bullets in the dark”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When I tell an LLM-driven Agent to do something, it may take care of the easy parts. Sometimes, those parts are boring, such as interacting with some 3rd party and proprietary API, but they are easy nonetheless. And for the hard parts? It fails, and it fails hard. The first impulse is to tell the LLM that it made mistakes, giving it high-level details about what to do next, in a very slow and error-prone feedback loop, and then I watch the LLM fail again. And because it got the easy parts right, I feel compelled to give it another chance, again telling it to fix its crap, and then I watch it fail again, and it fails harder this time.&lt;/p&gt;

&lt;p&gt;Being very frustrated, already, I checkout the code from the repository, giving the code a shot myself, because at least I know how to investigate and come up with a reasonable solution. But then I discover that the code is … hard to maintain crap. And the problem is that it doesn’t look like crap during the initial PR(s), but crap builds up (with crappy comments too), because I’m too afraid of telling it to make the code more maintainable, due to the high probability of mistakes.&lt;/p&gt;

&lt;p&gt;Even when things end up working, I’m left with the feeling that I could’ve done a better job, and this feeling permeates everything but insignificant scripts.&lt;/p&gt;

&lt;p&gt;With an LLM-driven workflow, I’m getting all the bad parts about programming, like the stress generated by not being in control when things aren’t working, desperately trying to shoot bullets in the dark and fix unmaintainable code, and without any of the gratification, which comes from the journey itself. We’re replacing that journey and all the learning, with a dialogue with an inconsistent idiot.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/10/27/ai-sucks-the-joy-out-of-programming/?pk_campaign=rss&quot;&gt;&apos;AI&apos; Sucks the Joy Out of Programming&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 27 Oct 2025 00:00:00 +0000</pubDate>
  <dc:modified>Mon, 27 Oct 2025 18:14:36 +0000</dc:modified>
  <atom:modified>Mon, 27 Oct 2025 18:14:36 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/10/27/ai-sucks-the-joy-out-of-programming/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/10/27/ai-sucks-the-joy-out-of-programming/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>AI</category>
  <category>Opinion</category>
  <category>Programming</category>
  <category>Programming Rant</category>
  </item>


<item>
  <title>Scala 3 / No Indent</title>
  <description>Scala 3 came with “significant indentation”. And I still dislike it, despite trying hard, so I’m switching back to braces.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
Scala 3 came with &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/other-new-features/indentation.html&quot;&gt;significant indentation&lt;/a&gt; (&lt;a href=&quot;https://web.archive.org/web/20250914105033/https://docs.scala-lang.org/scala3/reference/other-new-features/indentation.html&quot;&gt;🏛️&lt;/a&gt;). And I still &lt;a href=&quot;https://alexn.org/blog/2023/06/06/scala-3-significant-indentation-woes-sample/&quot;&gt;dislike it&lt;/a&gt;, despite &lt;a href=&quot;https://alexn.org/blog/2023/11/08/in-scala-3-use-4-spaces-for-indentation/&quot;&gt;trying hard&lt;/a&gt;. So I’m switching back to braces.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
Oh, no 😱 not this kind of rant again! Sorry, but it must be said about once per year 💪 — the rants will continue until morale improves!
&lt;/p&gt;

&lt;p&gt;Here are some reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It can lead to compilation errors that have weird explanations (e.g., types don’t match). My number one concern with significant indentation is ambiguity. CoffeeScript suffered from ambiguity (thank goodness it’s dead), YAML suffers from ambiguity, and Python doesn’t allow multi-line expressions (without a &lt;code&gt;\\&lt;/code&gt;) or multi-line lambdas to avoid ambiguity.&lt;/li&gt;
  &lt;li&gt;Copy/paste doesn’t work well, because when inserting a newline, editors have the tendency to keep the indentation of the previous line, so in most cases, when pasting, you’re at the wrong indentation level, and depending on the editor’s behavior, the first line of the pasted block might shift relative to the rest of the block. Scalafmt won’t help as it chokes on invalid syntax. My text editing skills are relatively good, and I still find myself unable to efficiently copy/paste blocks of code with significant indentation. Note that with braces, pasting at the wrong indentation level simply doesn’t matter and Scalafmt can do its job.&lt;/li&gt;
  &lt;li&gt;Editors now have to be smarter about jumping to the beginning and end of a block or expression. E.g., these classic Vim shortcuts no longer work for navigation:
    &lt;ul&gt;
      &lt;li&gt;
&lt;code&gt;[{&lt;/code&gt; and &lt;code&gt;[(&lt;/code&gt; for jumping to the opening brace or paren;&lt;/li&gt;
      &lt;li&gt;
&lt;code&gt;]}&lt;/code&gt; and &lt;code&gt;])&lt;/code&gt; for jumping to the closing brace or paren;&lt;/li&gt;
      &lt;li&gt;
&lt;code&gt;%&lt;/code&gt; for jumping to matching brace or paren.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You could avoid some braces before, e.g., by being more expression-oriented. Braces are a visual aid for blocks using statements, and for example, you could easily spot functions described by single expressions (with a high likelihood that they are pure), versus functions using statements.&lt;/li&gt;
  &lt;li&gt;Braces are a visual aid for &lt;a href=&quot;https://en.wikipedia.org/wiki/Scope_(computer_science)&quot;&gt;lexical scope&lt;/a&gt; — they make it easier to explain what scopes or blocks of code are to beginners. I’ve heard the argument that students have an easier time with significant indentation, but that’s just NOT true in my experience, quite the opposite. You can feel the tension due to the existence of (optional) &lt;code&gt;end&lt;/code&gt; markers, as if non-English students needed yet another English keyword.&lt;/li&gt;
  &lt;li&gt;Whitespace changes make diffs (in PR reviews) noisy. With braces, we do have formatting changes, but we can ignore it when insignificant.&lt;/li&gt;
  &lt;li&gt;Like it or not, braces are a &lt;em&gt;de facto&lt;/em&gt; standard due to the popularity of the C/C++ family. Even relatively newer languages, like Rust, use braces. Folks, sorry, but Pascal is dead, ML-languages are still niche, despite first appearing in the 1970s, and everyone hates CoffeeScript.&lt;/li&gt;
  &lt;li&gt;Scala 2.x codebases will be with us for a very long time, which is why we’ll have to live with both old-style and new-style syntax, forever. As with Perl’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Perl#Philosophy&quot;&gt;TMTOWTDI&lt;/a&gt;, having the ability to use the Klingon language is cool, but the risk/reward ratio isn’t great.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;no-indent-&quot;&gt;No-Indent 💪&lt;/h2&gt;

&lt;p&gt;Take a stand and reject significant indentation. Add this to your &lt;code&gt;build.sbt&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;ThisBuild / scalacOptions ++= Seq(
  &quot;-rewrite&quot;,
  &quot;-no-indent&quot;,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And if you’re using Scalafmt, an OK configuration for me in &lt;code&gt;.scalafmt.conf&lt;/code&gt; is this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;runner.dialect = scala3

# Even with old syntax, I dislike redundant braces, although there
# might be a case for adding them to aid clarity for big expressions
rewrite.rules = [RedundantBraces]
rewrite.redundantBraces.maxBreaks = 10

rewrite.scala3.convertToNewSyntax = true
rewrite.scala3.removeOptionalBraces = false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;UPDATE — As an alternative, &lt;a href=&quot;https://gist.github.com/kubukoz/95dc1abd3f5bc028b95a3927d73c4698/&quot;&gt;Jakub Kozłowski suggests&lt;/a&gt; disabling “significant indentation” in Scalafmt, unsure if this is better or worse, but note that the dialect override may prevent Scalafmt from recognizing code using significant indentation as being valid Scala code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;# Alternative to the above config
runner.dialect = scala3
runner.dialectOverride.allowSignificantIndentation = false
# allows `if x then y`
runner.dialectOverride.allowQuietSyntax = true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note: Scalafmt doesn’t appear to have the ability to rewrite the code from significant indentation to old-syntax, but it can rewrite from old-syntax to significant indentation (which is why we have to rely on Scalac’s &lt;code&gt;-no-indent -rewrite&lt;/code&gt;). This suggests Scalafmt has more information when braces are available, and so do we 😉&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/10/26/scala-3-no-indent/?pk_campaign=rss&quot;&gt;Scala 3 / No Indent&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 26 Oct 2025 08:35:53 +0000</pubDate>
  <dc:modified>Mon, 27 Oct 2025 05:07:05 +0000</dc:modified>
  <atom:modified>Mon, 27 Oct 2025 05:07:05 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/10/26/scala-3-no-indent/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/10/26/scala-3-no-indent/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Languages</category>
  <category>Programming</category>
  <category>Programming Rant</category>
  <category>Scala</category>
  <category>Scala 3</category>
  </item>


<item>
  <title>Scala 3 / Match Types</title>
  <description>Scala has a neat new feature, resembling TypeScript’s “conditional types”, but more powerful.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
Scala has a neat feature called &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/new-types/match-types.html&quot;&gt;match types&lt;/a&gt;. Let’s play…
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
This article is using &lt;a href=&quot;https://docs.scala-lang.org/scala3/new-in-scala3.html&quot;&gt;Scala 3&lt;/a&gt; syntax and features using &lt;a href=&quot;https://alexn.org/blog/2025/10/26/scala-3-no-indent/&quot;&gt;-no-indent&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Head[T] = T match {
  case Array[a]        =&gt; Option[a]
  case List[a]         =&gt; Option[a]
  case String          =&gt; Option[Char]
  case NonEmptyList[a] =&gt; a
  case Map[k, v]       =&gt; Option[(k, v)]
  case k *: v          =&gt; k
  case _               =&gt; Nothing
}

def head[T](t: T): Head[T] = t match {
  case ref: Array[a] =&gt;
    ref.headOption
  case ref: List[a] =&gt;
    ref.headOption
  case ref: String =&gt;
    ref.headOption
  case ref: NonEmptyList[a] =&gt;
    ref.head
  case ref: Map[k, v] =&gt;
    ref.headOption
  case ref: (k *: v) =&gt;
    ref.head.asInstanceOf[Head[k *: v]]
  case _ =&gt;
    throw IllegalArgumentException()
}

// Using it works as expected, with the compiler
// correctly inferring the types in each case:
val v1: Option[Int] =
  head(Array(1, 2, 3))
val v2: Option[String] =
  head(List(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;))
val v3: Option[Char] =
  head(&quot;hello&quot;)
val v4: Int =
  head(NonEmptyList.of(10, 20, 30))
val v5: Option[(String, Int)] =
  head(Map(&quot;a&quot; -&gt; 1, &quot;b&quot; -&gt; 2))
val v6: String =
  head(&quot;hello&quot; *: 42 *: true *: EmptyTuple)
val v7: Nothing =
  head(())
val v8: Nothing =
  head(123)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The above seems to achieve &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependent_type&quot;&gt;dependent typing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Scala isn’t alone in having this ability, here’s a TypeScript equivalent using its &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/conditional-types.html&quot;&gt;conditional types&lt;/a&gt; (&lt;a href=&quot;https://web.archive.org/web/20251011202517/https://www.typescriptlang.org/docs/handbook/2/conditional-types.html&quot;&gt;archive&lt;/a&gt;), although note that Scala’s match types are more powerful (and better looking):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// TypeScript code

type Head&lt;T&gt; =
  // Warn: tuples are arrays at runtime
  T extends [infer K, ...infer _] ? K :
  T extends Array&lt;infer A&gt; ? A | undefined :
  T extends string ? string | undefined :
  T extends Map&lt;infer K, infer V&gt; ? [K, V] | undefined :
  never;

function head&lt;T&gt;(t: T): Head&lt;T&gt; {
  if (Array.isArray(t)) {
    // covers arrays and tuples at runtime
    return (t[0] ?? undefined) as Head&lt;T&gt;;
  }
  if (typeof t === &quot;string&quot;) {
    return (t[0] ?? undefined) as Head&lt;T&gt;;
  }
  if (t instanceof Map) {
    const it = t.entries().next();
    return (it.done ? undefined : it.value) as Head&lt;T&gt;;
  }
  throw new Error(&quot;Unsupported type&quot;);
}

// Examples:
const v1: number | undefined =
    head([1, 2, 3]);
const v2: string | undefined =
    head([&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]);
const v3: string | undefined =
    head(&quot;hello&quot;);
const v4: [string, number] | undefined =
    head(new Map([[&quot;a&quot;, 1], [&quot;b&quot;, 2]]));
const v5: string = // tuple
    head([&quot;hello&quot;, 42, true] as [string, number, boolean]);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;recursivity&quot;&gt;Recursivity&lt;/h2&gt;

&lt;p&gt;Scala’s match types can also have &lt;em&gt;recursive definitions&lt;/em&gt;, so for example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type AtomOf[T] = T match {
  case Iterable[a] =&gt; AtomOf[a]
  case t =&gt; t
}

// These are valid
val x: AtomOf[List[List[String]]] = 
  &quot;atom&quot;
val y: AtomOf[Int] = 
  42
val z: AtomOf[List[Set[Map[String, Int]]]] = 
  (&quot;key&quot;, 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This makes inferring types related to tuples easier, e.g., straight from that documentation page, we can see that tuple concatenation can be expressed:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Concat[Xs &lt;: Tuple, Ys &lt;: Tuple] = 
  Xs match {
    case EmptyTuple =&gt; Ys
    case h *: t     =&gt; h *: Concat[t, Ys]
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want to waste time on things that bring you joy, you can now do type-level arithmetic (already expressed in &lt;code&gt;scala.compiletime.ops.int.+&lt;/code&gt;), taking inspiration from &lt;a href=&quot;https://en.wikipedia.org/wiki/Peano_axioms#Addition&quot;&gt;Peano’s axioms&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/c09bb6ddabe74edd03e6e331290560f4.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{cases} a + 0 = a \\ a + Succ(b) = Succ(a + b) \end{cases} \implies Succ(a) + b = a + Succ(b)&quot; width=&quot;708&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Which can be expressed almost literally:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.compiletime.ops.int.S as Succ

type Sum[A &lt;: Int, B &lt;: Int] &lt;: Int =
  A match {
    case 0        =&gt; B
    case Succ[a0] =&gt; Sum[a0, Succ[B]]
  }

val x: Sum[3, 4] = 7 // works
val y: Sum[3, 4] = 8 // fails with a compile-time error
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As a note, one would think that &lt;code&gt;Succ&lt;/code&gt; could be defined like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Succ[A &lt;: Int] &lt;: Int =
  A match {
    case 0 =&gt; 1
    case 1 =&gt; 2
    case 2 =&gt; 3
    //...
    case 2147483646 =&gt; 2147483647
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But I couldn’t make it work, maybe some kind soul from the Internet could explain why. Thankfully, it’s already defined by the Scala standard library at &lt;code&gt;scala.compiletime.ops.int.S&lt;/code&gt;, and this one works. And note that the Scala library defines types in terms of &lt;code&gt;S&lt;/code&gt;, with gems such as this one:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Standard library
package scala

object Tuple {
  /** Literal constant Int size of a tuple */
  type Size[X &lt;: Tuple] &lt;: Int = 
    X match {
      case EmptyTuple =&gt; 0
      case x *: xs =&gt; S[Size[xs]]
    }
}

//...
val x: Tuple.Size[(Int, String, Double)] = 3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can just smell the Turing completeness 😁&lt;/p&gt;

&lt;h2 id=&quot;caveat&quot;&gt;Caveat&lt;/h2&gt;

&lt;p&gt;Match types without exhaustive matches don’t really work. And the behavior changed somewhat in later Scala versions. For example, the following would trigger a compile time error in Scala &lt;code&gt;3.3.7&lt;/code&gt; (&lt;a href=&quot;https://www.scala-lang.org/blog/2022/08/17/long-term-compatibility-plans.html&quot;&gt;LTS&lt;/a&gt;), but not in the latest &lt;code&gt;3.7.3&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Head[T] = T match {
  case Array[a] =&gt; Option[a]
  case List[a]  =&gt; Option[a]
}

def head[T](t: T): Head[T] = 
  t match {
    case ref: Array[a] =&gt;
      ref.headOption
    case ref: List[a] =&gt;
      ref.headOption
  }

// ... these calls would trigger compile-time errors in 3.3.7,
// but not in later versions...
head(Iterator(1))
head(&quot;a string&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The issue here is that &lt;code&gt;Head[String]&lt;/code&gt;, in the above definition, is not allowed to exist in Scala 3.3.7 (LTS), but is allowed to exist in later versions. For me, this was surprising. But note the LTS is not free of surprises, as this sample compiles just fine on Scala 3.3.7 (LTS), when my intuition suggests it should not:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class Foo[T](val value: T)

type Unpacked[T] = 
  T match {
    case Foo[a] =&gt; a
  }

def unpack[T](t: T): Unpacked[T] = 
  t match {
    case ref: Foo[a] =&gt; ref.value
  }

// No compile-time errors whatsoever, in either versions,
// just runtime  exceptions:
unpack(&quot;a string&quot;)
unpack(List(1,2,3))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The kicker here is that you can make the above fail at compile-time, on Scala 3.3.7 LTS, if you add the &lt;code&gt;final&lt;/code&gt; keyword to that &lt;code&gt;Foo&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;final class Foo[T](val value: T)

type Unpacked[T] = T match {
  case Foo[a] =&gt; A
}

// Compile-time error in Scala 3.3.7
// Compilation passes in Scala 3.7.3
unpack(&quot;a string&quot;)
unpack(List(1,2,3))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;My shoddy rationalization goes like this: If &lt;code&gt;Foo&lt;/code&gt; is an open class (a class that can be extended or an interface/trait), it means that &lt;code&gt;String&lt;/code&gt; could eventually inherit from it in later Java/Scala versions. That’s highly unlikely, but the compiler probably has no way of knowing that. But it’s a poor rationalization, because TBH, I don’t see a problem with upgrades to &lt;code&gt;String&lt;/code&gt; making &lt;code&gt;Head[String]&lt;/code&gt; exist. It would be worse if it happened the other way around, IMO. This may be one of those cases in which the compiler team couldn’t make it work well, so decided to just shrug. So we’ll have to live with it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution&lt;/strong&gt; to the above is to just allow it to exist, by having a &lt;code&gt;case _ =&gt; Nothing&lt;/code&gt; branch:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Head[T] = T match {
  case Array[a] =&gt; Option[a]
  case List[a]  =&gt; Option[a]
  case _        =&gt; Nothing
}

// Type allowed to exist, but it reduces to Nothing
def x: Head[String] = throw IllegalArgumentException(&quot;Boo&quot;)
val y: Nothing = x
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And keep in mind that this match type is a return type that’s equivalent to a “union type” function parameter, which is how you can protect functions:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Head[T] = T match {
  case Array[a] =&gt; Option[a]
  case List[a]  =&gt; Option[a]
  case _        =&gt; Nothing
}

// Protecting the function call by using an 
// &quot;untagged union type&quot; as the &quot;upper bound&quot; 
// of our type parameter.
def head[T &lt;: Array[?] | List[?]](t: T): Head[T] = 
  t match {
    case ref: Array[a] =&gt;
      ref.headOption
    case ref: List[a] =&gt;
      ref.headOption
    case _ =&gt;
      // Note we don&apos;t really need this branch, but 
      // the compiler can&apos;t see it, and it also gives 
      // us a really scary compiler error, if we try 
      // removing it.
      throw IllegalArgumentException(&quot;Boo&quot;)
  }
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/10/25/scala-3-match-types/?pk_campaign=rss&quot;&gt;Scala 3 / Match Types&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sat, 25 Oct 2025 00:00:00 +0000</pubDate>
  <dc:modified>Mon, 27 Oct 2025 05:33:38 +0000</dc:modified>
  <atom:modified>Mon, 27 Oct 2025 05:33:38 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/10/25/scala-3-match-types/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/10/25/scala-3-match-types/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Languages</category>
  <category>Programming</category>
  <category>Scala</category>
  <category>Scala 3</category>
  <category>TypeScript</category>
  </item>


<item>
  <title>Update on Math Formulas via Copilot</title>
  <description>Or how I&apos;m using GitHub&apos;s Copilot in Agent mode for yak shaving, evolving my Jekyll-powered website for rendering mathematical formulas by SVG images, instead of heavy JavaScript.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
Or how I&apos;m using GitHub&apos;s Copilot in Agent mode for yak shaving, evolving my Jekyll-powered website for rendering mathematical formulas by SVG images, instead of heavy JavaScript.
&lt;/p&gt;

&lt;p&gt;This blog uses &lt;a href=&quot;https://github.com/mathjax/MathJax&quot;&gt;Mathjax&lt;/a&gt; for rendering math formulas, see my posts on &lt;a href=&quot;https://alexn.org/blog/tag/math/&quot;&gt;Math&lt;/a&gt;. But Mathjax is a JavaScript library, and it was running client-side, in the browser. And I tend to avoid JavaScript for this particular website.&lt;/p&gt;

&lt;p&gt;Given that I intend to write more math formulas, it bothered me that the dependence on JavaScript is hurting this blog’s &lt;a href=&quot;https://alexn.org/feeds/blog.xml&quot; target=&quot;_blank&quot;&gt;RSS feed&lt;/a&gt;, as RSS feed items can’t have JS in them. Also, the page rendering is slow and dirty, hurting the user experience due to that brief moment between the static HTML being loaded and MathJax doing its job, during which one can see the raw TeX syntax, and the page layout shifts to accommodate the JS-powered rendering.&lt;/p&gt;

&lt;p&gt;I’ve now switched the implementation to one that uses Mathjax on the server-side, when the website is built, translating those formulas to SVG images. Here’s how:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/alexandru/alexn.org/pull/83&quot;&gt;PR, started by Copilot&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/alexandru/alexn.org/commit/ebe455f2c5e450227e744412f5f66aedaa584f7d&quot;&gt;Commit fixing RSS and dark-mode&lt;/a&gt;, because life can’t be simple.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a sample. You can inspect it or “view source” for confirmation:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/0349585f18238d55f8fd783f0b7d7ef0.svg&quot; alt=&quot;Math formula&quot; title=&quot;F = G\frac{m1 \cdot m2}{r^2}&quot; width=&quot;180&quot; height=&quot;48&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;As a side-note, this is one of those times when I appreciate having full control over the implementation of my blog, instead of using WordPress or other, more evolved off-the-shelf solutions (I’m thinking here of &lt;a href=&quot;https://alexn.org/blog/2025/10/13/outsourced-voices-outsourced-minds/&quot;&gt;my previous article on outsourced voices&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I used GitHub’s Copilot, &lt;a href=&quot;https://docs.github.com/en/copilot/concepts/agents/coding-agent/about-coding-agent&quot;&gt;running as an Agent on GitHub&lt;/a&gt;, to start the PR and take care of the most difficult parts. It worked, but it needed supervision. Therefore, this is also a tale of how I used Copilot to modify my blog’s implementation.&lt;/p&gt;

&lt;p&gt;For instructing Copilot, I started with this prompt:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This website currently uses Mathjax for rendering math formulas. However, I’d like those math formulas to be more portable, i.e., to not require JavaScript for rendering.&lt;/p&gt;

  &lt;p&gt;Modify the website such that math formulas get rendered to SVG images, using the original TeX formula as “alt” text for the visually impaired.&lt;/p&gt;

  &lt;p&gt;Suggestions:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;Use mathjax-node for the rendering to SVG files (placed in &lt;code&gt;/assets/math&lt;/code&gt; at build time).&lt;/li&gt;
    &lt;li&gt;Use the formula’s hashcode as the SVG file name.&lt;/li&gt;
    &lt;li&gt;Reuse already generated files for repeated formulas.&lt;/li&gt;
    &lt;li&gt;Introduce a Jekyll plugin that searches and replaces math/TeX code to image tags pointing to these SVG files, also generating the files when needed.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Upon inspecting the result, which wasn’t bad, I then followed up with a change request:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Unfortunately, I now saw that &lt;code&gt;mathjax-node&lt;/code&gt; is an old package.&lt;/p&gt;

  &lt;p&gt;Drop it from the project and use the latest stable version of Mathjax and whatever it is needed to make it work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After reviewing the generated code, I noticed Copilot didn’t do the right thing. It broke the command meant for development, &lt;code&gt;jekyll serve&lt;/code&gt;. It certainly helped that I know how to do the job well:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There is a problem with this approach. These SVG files shouldn’t be generated directly in the project’s sources, for one, because I don’t want them to be added to the repository, but also, because it breaks &lt;code&gt;jekyll serve&lt;/code&gt;.&lt;/p&gt;

  &lt;p&gt;These files should be generated using Jekyll’s mechanism, by appending to &lt;code&gt;site.static_files&lt;/code&gt; a &lt;code&gt;Jekyll::StaticFile&lt;/code&gt; instance. There is already an example in &lt;code&gt;managed_js.rb&lt;/code&gt;.&lt;/p&gt;

  &lt;p&gt;The result of this should be that &lt;code&gt;/assets/math&lt;/code&gt; should be available only in the &lt;code&gt;_site&lt;/code&gt; directory after a jekyll build and the images should be served via &lt;code&gt;jekyll serve&lt;/code&gt; as well (so without an explicit &lt;code&gt;_site&lt;/code&gt; directory being built).&lt;/p&gt;

  &lt;p&gt;Also, remove the current &lt;code&gt;assets/math&lt;/code&gt; directory from this PR.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Plenty of micro-management here, telling it precisely what to do. And then the result was buggy:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I discovered that it doesn’t escape the SVG’s &lt;code&gt;title&lt;/code&gt; properly, and followed up with a fix myself.&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes were not calculated correctly by my setup, due to Mathjax preferring &lt;code&gt;ex&lt;/code&gt; as the unit type, referring to the width and height of an &lt;code&gt;x&lt;/code&gt; character of a font (weird). I did plenty of CSS tweaks that I’m not sure Copilot could’ve done.&lt;/li&gt;
  &lt;li&gt;The RSS feed wouldn’t work in dark mode, because the SVGs are black text on transparent background, and I couldn’t find a way to add CSS styling to the RSS feeds. Here, Copilot was completely disappointing. My final solution was to generate “transparent background” versions for the website and “light background” versions for the RSS feed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I used the “agent mode” in Visual Studio Code as well. The results when using GPT-4.1 are very poor, which is a pity, as this is the model with an unlimited number of requests on GitHub Copilot’s Pro plan. Claude Sonnet fared much better (at coding tasks in agent mode, but it’s poor at others, such as high-school math).&lt;/p&gt;

&lt;p&gt;At the time of writing, I now have another attempt at using Copilot Agent for optimizations: &lt;a href=&quot;https://github.com/alexandru/alexn.org/pull/84&quot;&gt;Optimize Jekyll build time for Mathjax and image processing&lt;/a&gt;; because the build times have gone up and that’s bad, too.&lt;/p&gt;

&lt;p&gt;It certainly has potential.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/10/21/update-on-math-formulas/?pk_campaign=rss&quot;&gt;Update on Math Formulas via Copilot&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 21 Oct 2025 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2025/10/21/update-on-math-formulas/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/10/21/update-on-math-formulas/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>AI</category>
  <category>Blogging</category>
  <category>Jekyll</category>
  <category>Self Hosting</category>
  </item>


<item>
  <title>Math Pill #2: Square Roots</title>
  <description>Simplifying radicals is strangely satisfying.</description>
  <content:encoded>&lt;p&gt;Simplifying radicals is strangely satisfying.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
I’m helping my son with mathematics, and I have to re-learn it, but this is fun. Hence, I’m hoping to start a &lt;a href=&quot;https://alexn.org/blog/tag/math/&quot;&gt;series of articles&lt;/a&gt;.
&lt;/p&gt;

&lt;h2 id=&quot;problem-statement&quot;&gt;Problem statement&lt;/h2&gt;

&lt;p&gt;Given:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/57a8e57d6677c16629fad2414d4b73a8.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{cases} \begin{aligned} A &amp;= \sqrt{4 + \sqrt{11} + \sqrt{23 - 2\sqrt{132}}} \\ B &amp;= \sqrt{\sqrt{97 + 56\sqrt{3}}} \end{aligned} \end{cases}&quot; width=&quot;396&quot; height=&quot;132&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Show that:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/c5997b69213d978014e6a24d3ef6c863.svg&quot; alt=&quot;Math formula&quot; title=&quot;\frac{B^2 - 4A}{B - A} \in \mathbb{N}.&quot; width=&quot;168&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;

&lt;p&gt;Starting with:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/9bea0dcfcc10a704026448a61927aeed.svg&quot; alt=&quot;Math formula&quot; title=&quot;B = \sqrt{\sqrt{97 + 56\sqrt{3}}}&quot; width=&quot;228&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Often such sums can be rewritten like this:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/6cb3934ad33f1a10f2fc8f7d6c89857d.svg&quot; alt=&quot;Math formula&quot; title=&quot;97 + 56\sqrt{3} = (\sqrt{a} + \sqrt{b})^2&quot; width=&quot;288&quot; height=&quot;24&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;We observe the formula:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/3728a7ee0a7375dd1ff121395ce7f944.svg&quot; alt=&quot;Math formula&quot; title=&quot;(\sqrt{a} + \sqrt{b})^2 = a + b + 2\sqrt{ab}&quot; width=&quot;324&quot; height=&quot;24&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Therefore, we end up with the following system of equations:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/de657b2a7f999fcac530e05fc38d2b7c.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{cases} a + b = 97 \\ ab = 28^2 \cdot 3 \end{cases}&quot; width=&quot;144&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;The solutions may or may not jump at you, but there’s a little &lt;a href=&quot;https://en.wikipedia.org/wiki/Vieta%27s_formulas&quot;&gt;Vieta’s formula&lt;/a&gt; that can help — we can find &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; as being the solutions to this quadratic equation:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/76d072d247db8197c1ff674c25bfb408.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} (x - a)(x + b) &amp;= 0 \iff \\ x^2 - (a + b)x + ab &amp;= 0 \iff \\ x^2 - 97 x + 2352 &amp;= 0 \end{aligned}&quot; width=&quot;336&quot; height=&quot;96&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Solving that:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/b776a1f2552bce244d3b7d0144017518.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} \Delta &amp;= 97^2 - 4 \cdot 2352 \\ &amp;= 9409 - 9408 \\ &amp;= 1 \\ x_1 &amp;= a = \frac{97 + \sqrt{1}}{2} = 49 \\ x_2 &amp;= b = \frac{97 - \sqrt{1}}{2} = 48 \end{aligned}&quot; width=&quot;276&quot; height=&quot;240&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Threfore:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/a0698a9300f432630445ad6c2bbcdf66.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} 97 + 56\sqrt{3} &amp;= (\sqrt{49} + \sqrt{48})^2 \\ &amp;= (7 + 4\sqrt{3})^2 \end{aligned}&quot; width=&quot;324&quot; height=&quot;72&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Going back to our original value, we rewrite it:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/bcc478f355ddd584e10358ce4dd70380.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} B &amp;= \sqrt{\sqrt{97 + 56\sqrt{3}}} \\ &amp;= \sqrt{\sqrt{(7 + 4\sqrt{3})^2}} \\ &amp;= \sqrt{7 + 4\sqrt{3}} \end{aligned}&quot; width=&quot;240&quot; height=&quot;192&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;We still have a square of a sum, but this time we can spot the &lt;img src=&quot;https://alexn.org/assets/math/white/9abb3dbf80119c1ac482c855c88a56e9.svg&quot; alt=&quot;Math formula&quot; title=&quot;(a + b)^2&quot; class=&quot;math-inline&quot; width=&quot;84&quot; height=&quot;24&quot; loading=&quot;lazy&quot;&gt; formula easily:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/e5493fc6a322f9b34f4c29a07c1d3c10.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} B &amp;= \sqrt{7 + 4\sqrt{3}} \\ &amp;= \sqrt{2^2 + 2 \cdot 2\sqrt{3} + \sqrt{3}^2} \\ &amp;= \sqrt{(2 + \sqrt{3})^2} \\ &amp;= 2 + \sqrt{3} \end{aligned}&quot; width=&quot;300&quot; height=&quot;204&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Next, for simplifying A, we’ll focus on rewriting this:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/c129741932f66d107421afe9033cdbfd.svg&quot; alt=&quot;Math formula&quot; title=&quot;23 - 2\sqrt{132} = (\sqrt{a} - \sqrt{b})^2&quot; width=&quot;312&quot; height=&quot;24&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Same trick applies, so we’re dealing with this system:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/bd8c3d180bc92342b44a29e7c69aa567.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{cases} a + b = 23 \\ ab = 132 \end{cases}&quot; width=&quot;132&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Which will have solutions generated by this quadratic equation:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/447b663943cbf054e01a521084195511.svg&quot; alt=&quot;Math formula&quot; title=&quot;x^2 - 23x + 132 = 0&quot; width=&quot;216&quot; height=&quot;24&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Solving it:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/50c672d8e8ed482b43d72b75279fcd3a.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} \Delta &amp;= 23^2 - 4 \cdot 132 = 529 - 528 = 1 \\ x_1 &amp;= a = \frac{23 + 1}{2} = \frac{24}{2} = 12 \\ x_2 &amp;= b = \frac{23 - 1}{2} = \frac{22}{2} = 11 \end{aligned}&quot; width=&quot;408&quot; height=&quot;156&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Therefore our sum can be rewritten as (we remember that we have a minus sign though 🙂):&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/e2a09a7968c0aae06d5455d95124ed82.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} 23 - 2\sqrt{132} &amp;= (\sqrt{12} - \sqrt{11})^2 \\ &amp;= (2\sqrt{3} - \sqrt{11})^2 \end{aligned}&quot; width=&quot;336&quot; height=&quot;72&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;We can now rewrite our A:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/a23595e3eca88df2995a8738d4cc0095.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} A &amp;= \sqrt{4 + \sqrt{11} + \sqrt{23 - 2\sqrt{132}}} \\ &amp;= \sqrt{4 + \sqrt{11} + \sqrt{(2\sqrt{3} - \sqrt{11})^2}} \\ &amp;= \sqrt{4 + \sqrt{11} + 2\sqrt{3} - \sqrt{11}} \\ &amp;= \sqrt{4 + 2\sqrt{3}} \\ &amp;= \sqrt{1^2 + 2\sqrt{3} + \sqrt{3}^2} \\ &amp;= \sqrt{(1 + \sqrt{3})^2} \\ &amp;= 1 + \sqrt{3} \end{aligned}&quot; width=&quot;408&quot; height=&quot;408&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;And finally:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/8b0b1b0418f6091835dd113e7a0c9eb0.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} \frac{B^2 - 4A}{B - A} &amp;= \frac{(2 + \sqrt{3})^2 - 4(1 + \sqrt{3})}{(2 + \sqrt{3}) - (1 + \sqrt{3})} \\ &amp;= \frac{4 + 4\sqrt{3} + 3 - 4 - 4\sqrt{3}}{1} \\ &amp;= 3 \in \mathbb{N} \end{aligned}&quot; width=&quot;432&quot; height=&quot;180&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/10/15/math-pill-2-square-roots/?pk_campaign=rss&quot;&gt;Math Pill #2: Square Roots&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 15 Oct 2025 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2025/10/15/math-pill-2-square-roots/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/10/15/math-pill-2-square-roots/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Math</category>
  <category>Learning</category>
  </item>


<item>
  <title>Math Pill #1: Sums</title>
  <description>My son started high-school, so I’m helping him with mathematics. It’s been a long time, and I have to re-learn. But it’s fun, and I’m hoping to start a series of articles.</description>
  <content:encoded>&lt;p&gt;My son started high-school, so I’m helping him with mathematics. It’s been a long time, and I have to re-learn. But it’s fun, and I’m hoping to start a &lt;a href=&quot;https://alexn.org/blog/tag/math/&quot;&gt;series of articles&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s an interesting sum:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/d0d115fa9019e2a8d6efca8dbe858af4.svg&quot; alt=&quot;Math formula&quot; title=&quot;S = \frac{1}{3 \cdot 7} + \frac{1}{7 \cdot 11} + \frac{1}{11 \cdot 15} + \cdots + \frac{1}{99 \cdot 103}&quot; width=&quot;528&quot; height=&quot;48&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;In order to write it with the summation notation, we first need to observe that the difference between elements in this number sequence is 4, therefore &lt;code&gt;4k&lt;/code&gt; is involved in the formula of the general term:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/88861847bee6be5feedff47e7b8bd333.svg&quot; alt=&quot;Math formula&quot; title=&quot;S = \sum_{k=1}^{25} \frac{1}{(4k - 1)(4k + 3)}&quot; width=&quot;300&quot; height=&quot;72&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Such sums are actually &lt;a href=&quot;https://en.wikipedia.org/wiki/Telescoping_series&quot;&gt;telescopic&lt;/a&gt;. And when you have fractions like these with a constant numerator, the general term can be split in 2 fractions, with the help of an equation, needing to find an &lt;code&gt;a&lt;/code&gt; satisfying this:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/c60fee23a0860e71c2f7c87db072b117.svg&quot; alt=&quot;Math formula&quot; title=&quot;\frac{1}{(4k-1)(4k+3)} = a \left( \frac{1}{4k-1} - \frac{1}{4k+3} \right)&quot; width=&quot;504&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/4b4aa9c9180863b2597e7eb2c021a8b8.svg&quot; alt=&quot;Math formula&quot; title=&quot;a \left( (4k+3) - (4k-1) \right) = a \cdot 4 = 1 \implies a = \frac{1}{4}&quot; width=&quot;540&quot; height=&quot;48&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;The sum becomes:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/423f75e09ad63cf8bb3398496d244c73.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} S &amp;= \sum_{k=1}^{25} \frac{1}{(4k-1)(4k+3)} \\ &amp;= \sum_{k=1}^{25} \frac{1}{4} \left( \frac{1}{4k-1} - \frac{1}{4k+3} \right) \\ &amp;= \frac{1}{4} \sum_{k=1}^{25} \left( \frac{1}{4k-1} - \frac{1}{4k+3} \right) \end{aligned}&quot; width=&quot;372&quot; height=&quot;252&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Expanding it:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/e078a4b0fd73be713c58195065d764e9.svg&quot; alt=&quot;Math formula&quot; title=&quot;S = \frac{1}{4} \left( \frac{1}{3} - \frac{1}{7} + \frac{1}{7} - \frac{1}{11} + \frac{1}{11} - \frac{1}{15} + \ldots + \frac{1}{99} - \frac{1}{103} \right)&quot; width=&quot;696&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;The terms get cancelled, the result being:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/46b55745990e775c5bbc79a7ce4fa493.svg&quot; alt=&quot;Math formula&quot; title=&quot;S = \frac{1}{4} \left( \frac{1}{3} - \frac{1}{103} \right)&quot; width=&quot;228&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;h2 id=&quot;more-samples&quot;&gt;More samples&lt;/h2&gt;

&lt;p&gt;We can apply this solution to other similar sums as well, for example:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/b2b1fef4c0a190c32e8740c92cf106cb.svg&quot; alt=&quot;Math formula&quot; title=&quot;\sum_{k=1}^{n} \frac{1}{(2k-1)(2k+1)(2k+3)}&quot; width=&quot;336&quot; height=&quot;72&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;In which case the fraction decomposition can be found with this equation:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/26f1b414c8003ef8bdf71a20ca5eed4c.svg&quot; alt=&quot;Math formula&quot; title=&quot;\frac{1}{(2k-1)(2k+1)(2k+3)} = a \left( \frac{1}{(2k-1)(2k+1)} - \frac{1}{(2k+1)(2k+3)} \right)&quot; width=&quot;828&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;And it works with more denominator factors as well:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/a7f4d7f0861c5b0191ae88a9b74eb504.svg&quot; alt=&quot;Math formula&quot; title=&quot;\sum_{k=1}^{n} \frac{1}{k(k+1)(k+2)(k+3)}&quot; width=&quot;312&quot; height=&quot;72&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;With the equation for finding the fraction decomposition being:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/dec5bd0a7c389faab13797fc2f888ac3.svg&quot; alt=&quot;Math formula&quot; title=&quot;\frac{1}{k(k+1)(k+2)(k+3)} = a \left( \frac{1}{k(k+1)(k+2)} - \frac{1}{(k+1)(k+2)(k+3)} \right)&quot; width=&quot;840&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;h2 id=&quot;non-constant-numerators&quot;&gt;Non-constant numerators&lt;/h2&gt;

&lt;p&gt;For this one we no longer have a constant numerator and the above solution no longer works:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/b91aaa9a17667cfd9150b3743672d5f0.svg&quot; alt=&quot;Math formula&quot; title=&quot;S = \sum_{k=1}^n \frac{7k^2 + k}{(7k-3)(7k+4)}&quot; width=&quot;300&quot; height=&quot;72&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;To do this fraction decomposition, we now need to find 2 constants, &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, the equation now being:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/d28b9f3d47f26e6bacbe39aef0532a30.svg&quot; alt=&quot;Math formula&quot; title=&quot;\frac{7k^2 + k}{(7k-3)(7k+4)} = a + \frac{b}{7k-3} - \frac{b}{7k+4}&quot; width=&quot;492&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;To solve it, after eliminating the denominator, the trick is to group by powers of &lt;code&gt;k&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/70130427cb34c0820679be0cde0f04cd.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} 7k^2 + k &amp;= a(7k-3)(7k+4) + b(7k+4) - b(7k-3) \\ 7k^2 + k &amp;= a(49k^2 + 28k - 21k - 12) + 7kb + 4b - 7kb + 3b \\ 0 &amp;= 49a k^2 + 7a k + 7b - 12a \\ 0 &amp;= k^2 (49a-7) + k(-1+7a) + (7b - 12a) \end{aligned}&quot; width=&quot;672&quot; height=&quot;144&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;k&lt;/code&gt; being variable, it means that, in order for the above equation to have solutions, we need the constants to nullify &lt;code&gt;k&lt;/code&gt;, so we have this system of equations:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/522b2fa2b19ac427a28f1cfc1488f1c4.svg&quot; alt=&quot;Math formula&quot; title=&quot;\left\{ \begin{array}{l} 49a - 7 = 0 \\ 7a - 1 = 0 \\ 7b - 12a = 0 \end{array} \right.&quot; width=&quot;168&quot; height=&quot;96&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/624182b4f56ade356f7650b299777f6f.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} a &amp;= \frac{1}{7} \\ 7b - \frac{12}{7} &amp;= 0 \\ 7b &amp;= \frac{12}{7} \\ b &amp;= \frac{12}{49} \end{aligned}&quot; width=&quot;168&quot; height=&quot;240&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;And now we can finally write the sum as:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/ef667caa96fbdbb2805111d5f88006d6.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{aligned} S &amp;= \sum_{k=1}^{n} \left( \frac{1}{7} + \frac{12}{49} \left( \frac{1}{7k-3} - \frac{1}{7k+4} \right) \right) \\ &amp;= \frac{n}{7} + \frac{12}{49} \sum_{k=1}^{n} \left( \frac{1}{7k-3} - \frac{1}{7k+4} \right) \\ &amp;= \frac{n}{7} + \frac{12}{49} \left( \frac{1}{4} - \frac{1}{7n+4} \right) \end{aligned}&quot; width=&quot;480&quot; height=&quot;228&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/10/15/math-pill-1-sums/?pk_campaign=rss&quot;&gt;Math Pill #1: Sums&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 15 Oct 2025 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2025/10/15/math-pill-1-sums/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/10/15/math-pill-1-sums/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Learning</category>
  <category>Math</category>
  </item>


<item>
  <title>Outsourced Voices, Outsourced Minds</title>
  <description>We are not machines, or automatons. We were fooled, but we can fight back. Don’t let algorithms control your thoughts and actions.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2025/10/13/outsourced-voices-outsourced-minds/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2025-thomas-in-a-box.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;2000&quot; height=&quot;1562&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;My cat, Thomas, sitting in a box, telling me that maybe it&apos;s better if I went to touch some grass.
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  We were fooled.
&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Jekyll_(software)&quot;&gt;Jekyll&lt;/a&gt;, the most popular static site generator, was released in 2008. That’s around the time I registered the &lt;code&gt;alexn.org&lt;/code&gt; domain, although I wouldn’t start blogging on it until later. I had another blog before this, it was powered by WordPress, hosted by a local service provider, but it died due to neglect, the articles I had on it lost forever. And before turning it off, I discovered that it had been infested with malware.&lt;/p&gt;

&lt;p&gt;That’s how I could see the value in a static website generator like Jekyll: a git repository seemed immortal, I could no longer lose my old thoughts, and the cheaper it is to host, the higher the probability that it would stay alive and kicking, just waiting for me to come back and share new articles. And nothing could be more secure than a static website.&lt;/p&gt;

&lt;p&gt;This was happening around 2010, it was right when people were starting to use social media, alongside forums, like Hacker News, Reddit, to distribute and comment on links. So tech blogs stopped having their own commenting widget, and those that continued to have comments, outsourced them to services such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Disqus&quot;&gt;Disqus&lt;/a&gt;. Alongside comments, amongst dynamic features of blogs, other casualties were &lt;a href=&quot;https://wordpress.org/documentation/article/trackbacks-and-pingbacks/&quot;&gt;trackbacks and pingbacks&lt;/a&gt; (&lt;a href=&quot;https://web.archive.org/web/20251007002950/https://wordpress.org/documentation/article/trackbacks-and-pingbacks/&quot;&gt;archive&lt;/a&gt;), which were the equivalent of seeing who mentioned or quoted you on social media. And yet another was the mailing list, outsourced to Feedburner, then Mailgun. In optimizing my online presence, I achieved what I wanted, but in retrospect, I now realize that optimizing for hosting costs is foolish.&lt;/p&gt;

&lt;p&gt;Up until around 2010, it seemed like RSS/Atom feeds were thriving, but then in 2013 &lt;a href=&quot;https://en.wikipedia.org/wiki/Google_Reader#Discontinuation&quot;&gt;Google killed Reader&lt;/a&gt;, being perceived as the death of RSS/Atom feed readers. They were trying to create their own Facebook competitor, &lt;a href=&quot;https://en.wikipedia.org/wiki/Google%2B&quot;&gt;Google+&lt;/a&gt;, and Reader was standing in their way. I can’t tell you how much joy the death of Google+ brought, I’ve never been happier about an online service dying, but I digress. Well, feed readers are still alive and thriving, just with a much smaller audience. The web is dying, and Google Reader proved to be the canary in the coal mine.&lt;/p&gt;

&lt;p&gt;It’s 2025, and you’re still posting and commenting on links, but you’re most likely doing it on social media. Facebook, 𝕏/Twitter, LinkedIn are deprioritizing links, which means that posts containing links will have a lower reach. Let me repeat that — social media silos are fighting against web links, the foundation of the open web. They do so to “encourage” content and discussions on their own platforms, and now these platforms are filled with politics, rage, and AI slop.&lt;/p&gt;

&lt;p&gt;You’re no longer in control of what you consume on the web. &lt;a href=&quot;https://www.youtube.com/watch?v=QEJpZjg8GuA&quot;&gt;Algorithms are now in control&lt;/a&gt;, and those algorithms want you to be a mindless zombie that consumes ads, ads that serve malware, scams, or politics. Not to be misunderstood, I recently bought theater tickets to a show via an ad, curated ads can clearly be valuable, but curation is incompatible with the ambitions of these social networks.&lt;/p&gt;

&lt;p&gt;I’d rather not leave the original sin out of this discussion, of course: Google Search becoming increasingly filled with SEO spam, and again, index curation was incompatible with Google’s ambitions due to the conflict of interest generated by their DoubleClick acquisition. After that, everything else was inevitable, such as Google increasingly stealing website content to show it directly in results, due to how poisoned the index became.&lt;/p&gt;

&lt;p&gt;It wasn’t always like this. I remember a young Google filled with interesting websites, a young Twitter filled with enthusiasts talking about programming, gardening, other hobbies, a young Facebook filled with photos and life updates of acquaintances. And that was the norm, not the exception. But following 100 people on social media, waiting for their status updates, wouldn’t generate much engagement, so the platforms started force-feeding people the status updates of strangers and bots, discussions converging inevitably to politics, sprinkled with rage, and low-quality humor, as that’s what keeps people engaged.&lt;/p&gt;

&lt;p&gt;There are still people online with interests other than politics, but I bet that many of you, even if you aren’t contributing political sludge, at the very least you’re engaging in &lt;a href=&quot;https://en.wikipedia.org/wiki/Doomscrolling&quot;&gt;doomscrolling&lt;/a&gt;, as that’s what the algorithm optimizes for. To make matters worse, even when there’s no algorithm, people are now so trained on this behavior that it persists, as seen on Mastodon or Bluesky. You could do anything you want, and you could be anyone you’d like when going online, and yet, many willingly choose to be armchair political commentators. In fairness, &lt;a href=&quot;https://en.wikipedia.org/wiki/Godwin%27s_law&quot;&gt;Godwin’s law&lt;/a&gt; was always a thing. And it’s easier to keep your feed curated when there’s no algorithm, but only if you’re willing to unfriend/unfollow acquaintances who have gone off the deep end.&lt;/p&gt;

&lt;p&gt;And now social media platforms are being filled with AI slop, with the platform owners providing the tools for it. Meta/Facebook, 𝕏/Twitter, LinkedIn are literally encouraging AI-generated posts, because it’s a cheap way of keeping you active on their platforms, in a zombie state, ready to consume whatever ads they throw at you. For these companies, it’s a good thing if &lt;a href=&quot;https://youtu.be/6aVRQDKJ9Dg&quot;&gt;we are getting dumber due to ChatGPT&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’ve outsourced our voices on the Internet, because it was convenient. We’ve outsourced our minds as well.&lt;/p&gt;

&lt;p&gt;But we are people with ideas, feelings, aspirations, lives. We are not machines, we are not automatons, we have souls. And we deserve to own our identity, our voice, and our thoughts. We deserve access to an open web, a web that’s good for connecting with like-minded people, a web good for learning and exploring our passions.&lt;/p&gt;

&lt;p&gt;We were fooled, but we can fight back. Don’t let algorithms control your actions, don’t outsource your voice and your mind. Choose wisely, as in the future we may find ourselves completely unable to make choices.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/10/13/outsourced-voices-outsourced-minds/?pk_campaign=rss&quot;&gt;Outsourced Voices, Outsourced Minds&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 13 Oct 2025 05:24:14 +0000</pubDate>
  <dc:modified>Mon, 03 Nov 2025 07:05:47 +0000</dc:modified>
  <atom:modified>Mon, 03 Nov 2025 07:05:47 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/10/13/outsourced-voices-outsourced-minds/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/10/13/outsourced-voices-outsourced-minds/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>AI</category>
  <category>Blogging</category>
  <category>Opinion</category>
  <category>Politics</category>
  <category>Web</category>
  </item>


<item>
  <title>Effects and Concurrency in Functional Programming</title>
  <description>I’ve delivered (sometime this year) this presentation at a local meetup (ING Hubs Romania). The target was mainstream developers, with the intent to give them a taste of FP and working with I/O in Scala.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      
&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=RSWnKrx9Vt8&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/RSWnKrx9Vt8/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=RSWnKrx9Vt8&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I&apos;ve delivered (sometime this year) this presentation at a local meetup (ING Hubs Romania). The target was mainstream developers, with the intent to give them a taste of FP and working with I/O in Scala.
&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=RSWnKrx9Vt8&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/RSWnKrx9Vt8/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=RSWnKrx9Vt8&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I’ve posted this on my social media accounts in September, but I’m including it on my blog for posterity. Ignore the noise if you’ve already seen it.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/09/17/effects-and-concurrency-in-functional-programming-youtube/?pk_campaign=rss&quot;&gt;Effects and Concurrency in Functional Programming&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 17 Sep 2025 14:43:37 +0000</pubDate>
  <link>https://alexn.org/blog/2025/09/17/effects-and-concurrency-in-functional-programming-youtube/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/09/17/effects-and-concurrency-in-functional-programming-youtube/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Programming</category>
  <category>Scala</category>
  <category>Video</category>
  </item>


<item>
  <title>Scala&#39;s Gamble with Direct Style</title>
  <description>Scala does not move in the direction of more monadic IO, but rather in the direction of “direct style”, preferring continuations to monads, but without providing support for continuations out of the box.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2025/08/29/scala-gamble-with-direct-style/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala-stairs.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;1200&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;The staircase at EPFL that inspired Scala&apos;s logo.&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;info-bubble&quot;&gt;
  This is a more superficial article, i.e., an opinion piece. I’m making it my mission, again, to publish more thoughts on my own blog.
&lt;/p&gt;

&lt;p&gt;Scala has had a wide ecosystem for functional programming™️ directly inspired by Haskell and OCaml, due to its expressive type system and support for both type class encodings and OOP. As such it has inspired not one, but multiple runtimes for monadic IO, such as &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats-Effect&lt;/a&gt;, &lt;a href=&quot;https://zio.dev/&quot;&gt;ZIO&lt;/a&gt;, &lt;a href=&quot;https://getkyo.io/&quot;&gt;Kyo&lt;/a&gt;. And these libraries served as an inspiration for others, see &lt;a href=&quot;https://effect.website/&quot;&gt;Effect-TS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Yet, Scala 3, the language, does not move in the direction of more monadic IO, but rather in the direction of “direct style”, preferring continuations to monads, but without providing support for continuations out of the box. There are some attempts to fill that gap:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;a href=&quot;https://github.com/dotty-cps-async/dotty-cps-async&quot;&gt;dotty-cps-async&lt;/a&gt; approach is IMO the best bet, even for retrofitting monadic IO to direct style. But in my limited experience, it has edge cases, and in the projects making use of it, like &lt;a href=&quot;https://github.com/typelevel/cats-effect-cps&quot;&gt;Cats-Effect&lt;/a&gt; (possibly &lt;a href=&quot;https://zio.dev/zio-direct/&quot;&gt;ZIO&lt;/a&gt; or &lt;a href=&quot;https://getkyo.io/#/?id=direct-syntax&quot;&gt;Kyo&lt;/a&gt; as well), this support isn’t used much. For example, one reason this happens is because the interruption model is different from that of the JVM, e.g., if you don’t turn a cancellation into an &lt;code&gt;InterruptedException&lt;/code&gt;, it won’t blend well with the language’s constructs, like &lt;code&gt;try-catch-finally&lt;/code&gt;. But also, support not being part of the actual language, in this case, may mean the implementation is cursed to battle edge cases and bugs forever.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/lampepfl/gears/&quot;&gt;gears&lt;/a&gt; builds on top of virtual threads for the JVM, and it supports Scala Native as well. It can support WASM via &lt;a href=&quot;https://v8.dev/blog/jspi&quot;&gt;WASM JSPI&lt;/a&gt;, possibly in the next release. So it builds on the runtime’s support for either blocking threads or (one-shot) continuations. That’s incredibly limiting. For example, it has no JavaScript support and blocking threads is still very taxing on JVM-like platforms that don’t have virtual threads, such as Android. And obviously, execution cannot be fine-tuned, and you don’t have the abilities of a user-space runtime such as that of Cats-Effect or ZIO.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/softwaremill/ox&quot;&gt;ox&lt;/a&gt; is a JVM library for blocking threads and doesn’t make any attempts of supporting anything else but the JVM. If you work on the JVM, I guess that’s fine, although the library will be somewhat less useful after &lt;a href=&quot;https://rockthejvm.com/articles/structured-concurrency-jdk-25&quot;&gt;Structured Concurrency lands in Java 25&lt;/a&gt;. If we want to go back to blocking threads (with mostly the same caveats applying), I guess that’s acceptable with the support for virtual threads since Java 21, but what about Scala Native, JS or Wasm? Ox is a cool library and may be right for a lot of projects, but for the ecosystem, if Scala doesn’t escape the JVM, or at least JVM-isms, it’s far less interesting than the next versions of Java (which will also have &lt;a href=&quot;https://www.youtube.com/watch?v=Gz7Or9C0TpM&quot;&gt;type-classes&lt;/a&gt; BTW).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keep the above in mind and compare with Kotlin:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/Kotlin/kotlinx.coroutines&quot;&gt;Kotlin Coroutines&lt;/a&gt; have multi-platform support, and this means — JVM, Android, iOS (Native), JS and WasmGC.
    &lt;ul&gt;
      &lt;li&gt;Watch &lt;a href=&quot;https://www.youtube.com/watch?v=Mj5P47F6nJg&quot;&gt;Structured concurrency&lt;/a&gt; by Roman Elizarov to get a sense of the design considerations that went into it. This isn’t your grandpa’s async/await.&lt;/li&gt;
      &lt;li&gt;Those coroutines, along with its support for context parameters, can be leveraged not just for I/O, but also for handling of resources in general, matching Scala’s libraries such as Cats-Effect and ZIO (see &lt;a href=&quot;https://arrow-kt.io/learn/coroutines/resource-safety/&quot;&gt;Arrow&lt;/a&gt;).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.jetbrains.com/kotlin-multiplatform/&quot;&gt;Multiplatform&lt;/a&gt; support is top-notch. It has a &lt;a href=&quot;https://klibs.io/&quot;&gt;growing ecosystem of libraries&lt;/a&gt;, with &lt;a href=&quot;https://www.jetbrains.com/compose-multiplatform/&quot;&gt;Compose Multiplatform&lt;/a&gt; having stable iOS support and getting contributions from Google and others.&lt;/li&gt;
  &lt;li&gt;It’s a language that evolves as well. For instance, &lt;a href=&quot;https://github.com/Kotlin/KEEP/blob/context-parameters/proposals/context-parameters.md&quot;&gt;context parameters&lt;/a&gt; are almost here, &lt;a href=&quot;https://www.youtube.com/watch?v=IUrA3mDSWZQ&quot;&gt;rich errors&lt;/a&gt; as well, and it may even get better &lt;a href=&quot;https://www.youtube.com/watch?v=qpM3_ymNkP8&quot;&gt;immutability support&lt;/a&gt; before Scala.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scala obviously relies more on community and less on commercial support. I actually loved that about Scala, despite it being unable to remain viable for targeting mobile devices, but…&lt;/p&gt;

&lt;p&gt;Scala 2.x thrived due to making it saner to work with asynchronous I/O and concurrency. And yet the world isn’t standing still and alternatives have improved. Scala could’ve taken the path of &lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions&quot;&gt;F#’s computation expressions&lt;/a&gt;, thus improving the ergonomics of working with monadic IO. Scala could also include support for continuations out-of-the-box. Scala 3 does neither of those things, which means monadic IO is not getting the support it needs in order to go mainstream and the &lt;em&gt;“direct style”&lt;/em&gt; approaches are currently in limbo.&lt;/p&gt;

&lt;p&gt;I understand why Scala’s designers may prefer a “direct style” path. I’m not sure if I believe in the long-term success of monadic IO. Undoubtedly, it’s currently a marketplace failure, and when you solve concurrency issues by other means, &lt;a href=&quot;https://alexn.org/blog/2022/10/13/the-case-against-effect-systems-io-data-type/&quot;&gt;it’s debatable if monadic IO is still worth it&lt;/a&gt;. Even those that swear by &lt;a href=&quot;https://effect.website/&quot;&gt;Effect-TS&lt;/a&gt; have to realize that its apparent success only has to do with how much async/await/Promise in JavaScript sucks, and if that pain is ever fixed, the project’s growth will likely stagnate.&lt;/p&gt;

&lt;p&gt;But Scala’s evolution is currently alienating the part of the community that builds cutting-edge, user-space I/O runtimes that are the envy of the industry, while not providing the support required for making “direct style” work for the folks that would rather prefer that over monads. And I think that’s bad, especially as alternatives exist, one of those alternatives being Java 25.&lt;/p&gt;

&lt;p&gt;I still ❤️ Scala, it’s a productive language, and I believe it will be even more awesome with &lt;a href=&quot;https://nrinaudo.github.io/articles/capture_checking.html&quot;&gt;capture checking&lt;/a&gt;. But making programming safer is just one aspect of what makes or breaks a language. There are other aspects, such as the platforms and problem domains a language is able to target. Most problems we solve on a daily basis are I/O-related problems and without a consistent story that targets the mainstream, I fear for its future.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/08/29/scala-gamble-with-direct-style/?pk_campaign=rss&quot;&gt;Scala&apos;s Gamble with Direct Style&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 29 Aug 2025 05:33:16 +0000</pubDate>
  <dc:modified>Fri, 29 Aug 2025 08:25:48 +0000</dc:modified>
  <atom:modified>Fri, 29 Aug 2025 08:25:48 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/08/29/scala-gamble-with-direct-style/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/08/29/scala-gamble-with-direct-style/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Opinion</category>
  <category>Programming Rant</category>
  <category>Scala</category>
  <category>Scala 3</category>
  </item>


<item>
  <title>Backup Script for My Cloud Storage</title>
  <description>This is a script that I use for backing up my OneDrive to a Nextcloud instance.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2025/04/18/backup-script-for-my-cloud-storage/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2025-backup-cloud.png?202603060940&quot; alt=&quot;&quot; width=&quot;1972&quot; height=&quot;504&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p&gt;I currently have around ~370 GB stored in OneDrive, including the family’s photo archive that I’d rather not lose. It needs backups, and currently I don’t have a home NAS. I used to just sync my files, via &lt;a href=&quot;https://rclone.org/&quot;&gt;rclone&lt;/a&gt; to Backblaze B2, which can keep &lt;a href=&quot;https://www.backblaze.com/docs/cloud-storage-file-versions&quot;&gt;older versions of files&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Recently, I moved my backups to a &lt;a href=&quot;https://www.hetzner.com/storage/storage-share/&quot;&gt;Hetzner’s Storage Share&lt;/a&gt;, which is a managed &lt;a href=&quot;https://nextcloud.com/&quot;&gt;Nextcloud&lt;/a&gt; service — I prefer this because it’s a reasonably priced EU service, and it’s based on FOSS that I could self-host. But the problem is: &lt;strong&gt;how to keep older versions of files?&lt;/strong&gt; This is important as backups are meant to prevent accidents, such as accidental deletions, or &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_degradation&quot;&gt;data degradation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The trick is in using the &lt;code&gt;--backup-dir&lt;/code&gt; option of &lt;code&gt;rclone sync&lt;/code&gt; (&lt;a href=&quot;https://rclone.org/docs/#backup-dir-dir&quot;&gt;see documentation&lt;/a&gt;). This tells the &lt;code&gt;rclone&lt;/code&gt; command to copy any files that have changed or were deleted in the specified directory.&lt;/p&gt;

&lt;p&gt;Here’s a script, built for my own needs, use with care (i.e., don’t execute it if you don’t understand what it does).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;#!/usr/bin/env python3

import argparse
import datetime
import os
import re
import subprocess
import sys

RSOURCE = &quot;onedrive&quot;
RDEST = &quot;nextcloud&quot;
SYNC_PARAMS = &quot;--delete-excluded -c --track-renames --onedrive-hash-type sha1&quot;

EXCLUDE_PATTERNS = [
    &quot;.git&quot;,
    &quot;.DS_Store&quot;,
    &quot;.localized&quot;,
    &quot;*.swp&quot;,
    &quot;.#*&quot;,
]

def execute(command, verbose):
    if verbose:
        sys.stdout.write(&quot;--------------------------------------------------------------------------\n&quot;)
        sys.stdout.write(command + &quot;\n&quot;)
        sys.stdout.write(&quot;--------------------------------------------------------------------------\n&quot;)
    r = os.system(command)
    if r != 0:
        sys.stderr.write(f&quot;Command &apos;{command}&apos; failed with exit code {r}\n&quot;)
        sys.exit(r)

def execute_capture_output(command):
    r = subprocess.run(
        command,
        capture_output=True,
        text=True
    )
    if r.returncode != 0:
        sys.stderr.write(r.stderr)
        sys.stderr.write(&quot;\n&quot;)
        sys.exit(r.returncode)
    return r.stdout

def list_dirs(label):
    r = execute_capture_output([&quot;rclone&quot;, &quot;lsd&quot;, f&quot;{label}:&quot;])
    names = []
    for l in r.splitlines():
        parts = re.split(r&apos;\s+&apos;, l, maxsplit=5)
        if parts[-1].startswith(&quot;.&quot;): continue
        names.append(parts[-1])
    return names

def main():
    parser = argparse.ArgumentParser(description=&apos;Backs up files to cloud storage.&apos;)
    parser.add_argument(&apos;-d&apos;, &apos;--dry-run&apos;, action=&apos;store_true&apos;)
    parser.add_argument(&apos;-q&apos;, &apos;--quiet&apos;, action=&apos;store_true&apos;)
    args = parser.parse_args()

    date = datetime.datetime.now().strftime(&quot;%Y-%m-%d.%H-%M-%S&quot;)
    extra_params = [item
        for list in [
            [f&quot;--exclude \&quot;{e}\&quot;&quot; for e in EXCLUDE_PATTERNS],
            [&quot;--verbose&quot;] if not args.quiet else [&quot;-q&quot;],
            [&quot;--dry-run&quot;] if args.dry_run else [],
        ]
        for item in list
    ]

    for dirname in list_dirs(RSOURCE):
        backup_dir = f&quot;{RDEST}:Backups/OneDrive/{date}/{dirname}&quot;
        execute(
            f&quot;rclone sync \&quot;{RSOURCE}:{dirname}\&quot; \&quot;{RDEST}:{dirname}\&quot; {SYNC_PARAMS} \&quot;--backup-dir={backup_dir}\&quot; {&quot; &quot;.join(extra_params)}&quot;,
            not args.quiet
        )

if __name__ == &quot;__main__&quot;:
    main()
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/04/18/backup-script-for-my-cloud-storage/?pk_campaign=rss&quot;&gt;Backup Script for My Cloud Storage&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 18 Apr 2025 15:53:12 +0000</pubDate>
  <dc:modified>Fri, 18 Apr 2025 16:59:58 +0000</dc:modified>
  <atom:modified>Fri, 18 Apr 2025 16:59:58 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/04/18/backup-script-for-my-cloud-storage/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/04/18/backup-script-for-my-cloud-storage/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Python</category>
  <category>Self Hosting</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Tagged vs Untagged Unions (in Scala)</title>
  <description>What’s the difference between Option[A] and A | Null? What about between Either[A, B] and A | B?</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
What’s the difference between &lt;code&gt;Option[A]&lt;/code&gt; and &lt;code&gt;A | Null&lt;/code&gt;? How about between &lt;code&gt;Either[A, B]&lt;/code&gt; and &lt;code&gt;A | B&lt;/code&gt;?
&lt;/p&gt;

&lt;p&gt;Scala has had the &lt;a href=&quot;https://scala-lang.org/api/3.x/scala/Option.html&quot;&gt;Option&lt;/a&gt; data-type for dealing with &lt;code&gt;null&lt;/code&gt; values:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val person: Option[Person] = ???

// You can pattern match on it:
person match {
  case Some(e) =&gt; updateState(e)
  case None =&gt; doNothing
}

// You can combine it with other values, sequentially:
for {
  p &lt;- person
  a &lt;- p.address
  t &lt;- transaction
} yield updateState(a, t)

// ... or in parallel (with the ability to get all error messages):
import cats.syntax.all.*

(person, transaction).mapN { (p, t) =&gt;
  updateState(p, t)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The big benefit of &lt;code&gt;Option&lt;/code&gt; is that it’s a “monadic type”, which also has to do with the fact that it’s a “boxed” type, meaning that &lt;code&gt;Option[Option[T]]&lt;/code&gt; is not the same as &lt;code&gt;Option[T]&lt;/code&gt;. This is very important, as that means that &lt;code&gt;Option&lt;/code&gt; has predictable behaviour (it’s lawful), and can be used in instances in which &lt;code&gt;Option[Option[T]]&lt;/code&gt; makes sense:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class Person(
  name: String,
  address: Option[Address]
)

// For an HTTP PATCH, if a field is provided, it should be 
// updated, otherwise, if `None`, then the old value is kept.
case class PersonHttpPatchRequest(
  name: Option[String],
  address: Option[Option[Address]]
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Scala 3 also has &lt;code&gt;A | Null&lt;/code&gt; as a type, with the &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/experimental/explicit-nulls.html&quot;&gt;explicit-nulls&lt;/a&gt; compiler option being required to make it useful. This is similar to what &lt;a href=&quot;https://kotlinlang.org/docs/null-safety.html&quot;&gt;Kotlin provides&lt;/a&gt;, the so-called &lt;code&gt;A?&lt;/code&gt;, although slightly less mature.&lt;/p&gt;

&lt;p&gt;The downside of &lt;code&gt;A | Null&lt;/code&gt; is that it’s not a monadic type. It’s not lawful in the same way as &lt;code&gt;Option&lt;/code&gt; is. And that’s because it’s not a boxed type. &lt;code&gt;A | Null | Null&lt;/code&gt; is the same as &lt;code&gt;A | Null&lt;/code&gt;. Therefore, this no longer works:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class Person(
  name: String,
  address: Address | Null
)

// Oops! This isn&apos;t right:
case class PersonHttpPatchRequest(
  name: String | Null,
  address: String | Null | Null
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another downside is that you can’t really use &lt;code&gt;A | B&lt;/code&gt; for expressing &lt;code&gt;Either[Error, Result]&lt;/code&gt;. This is because you don’t know which is the error and which is the result.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Parser[A] {
  // Doesn&apos;t work as `parse` could produce a `Right(ParseError)`, 
  // after all, I can&apos;t see why errors shouldn&apos;t be serializable 
  // and deserializable.
  def parse(input: String): ParseError | A 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;A | B&lt;/code&gt; type is auto-flattening because &lt;code&gt;A | B&lt;/code&gt; is a supertype of &lt;code&gt;A&lt;/code&gt;, meaning that &lt;code&gt;A &lt;: A | B&lt;/code&gt; and &lt;code&gt;B &lt;: A | B&lt;/code&gt;. So &lt;code&gt;A | Null | Null&lt;/code&gt; is the same as &lt;code&gt;A | Null&lt;/code&gt;, which is a supertype of &lt;code&gt;A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This has 2 advantages:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Scala is an OOP language, and we care about the variance of type parameters, so &lt;code&gt;A | B&lt;/code&gt; is better than &lt;code&gt;AA &gt;: A&lt;/code&gt; in the type signature of methods.&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;A | Null&lt;/code&gt; being a supertype it means that using it can preserve backwards-compatibility.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the first point, consider this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// we&apos;ve got a covariant type parameter
sealed trait List[+A] { 

  def prepend1[B &gt;: A](value: B): List[B] = ???

  def prepend2[B](value: B): List[A | B] = ???
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which of these two methods is better? IMO, it’s the second one because it’s more expressive, whereas the first one is losing information. In fairness, the Scala compiler can and probably does infer that &lt;code&gt;B &gt;: A&lt;/code&gt; can be &lt;code&gt;A | B&lt;/code&gt;, so we’re essentially comparing Scala 2 with Scala 3 here. And I’d rather talk about a &lt;code&gt;List[Int | String]&lt;/code&gt;, for example, than a &lt;code&gt;List[Any]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the second point, given these methods:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// For testing contra-variance
def foo(value: A): B
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we change its signature to using &lt;code&gt;A | Null&lt;/code&gt;, then we aren’t breaking compatibility, because all the call sites still work:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Contra-variance, still compatible
def foo(value: A | Null): B

// ....
// Still works in all the older code
val a: A = ???
foo(a) 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But if we’d use &lt;code&gt;Option[A]&lt;/code&gt; instead, we’d break source and binary compatibility, which is especially problematic on the JVM due to all the dynamic linking of transitive dependencies:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def foo(value: Option[A]): B

// ...
// This now breaks
val a: A = ???
foo(a) // Error
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course, the old fashioned way of dealing with this is to use method overloading, assuming you can do it (unless type erasure gets in the way):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def foo(value: A): B = foo(Some(value))
def foo(value: Option[A]): B
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, it wouldn’t work for return types, so for example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// If we are forced to keep this signature
def foo(value: A): Option[B]

// We can&apos;t add an overload like this
def foo(value: A): B
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So there you have it. Currently, there’s no free lunch and I actually like both.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/04/02/tagged-vs-untagged-unions-in-scala/?pk_campaign=rss&quot;&gt;Tagged vs Untagged Unions (in Scala)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 02 Apr 2025 08:30:19 +0000</pubDate>
  <dc:modified>Wed, 02 Apr 2025 09:40:02 +0000</dc:modified>
  <atom:modified>Wed, 02 Apr 2025 09:40:02 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/04/02/tagged-vs-untagged-unions-in-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/04/02/tagged-vs-untagged-unions-in-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  <category>Scala 3</category>
  <category>Programming</category>
  </item>


<item>
  <title>My Favorite Firefox Extensions</title>
  <description>In my previous post, I mentioned that I now use Firefox as my main browser and you should too. Firefox’s strength is its extensions, with many available on Android devices as well. Here’s a list of my favorites.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  &lt;a href=&quot;https://alexn.org/blog/2025/03/03/use-firefox/&quot;&gt;In my previous post&lt;/a&gt;, I mentioned that I now use Firefox as my main browser and you should too. Firefox’s strength is its extensions, with many available on Android devices as well. Here’s a list of my favorites.
&lt;/p&gt;

&lt;p&gt;On both the desktop and in &lt;a href=&quot;https://www.mozilla.org/en-US/firefox/browsers/mobile/android/&quot;&gt;Firefox for Android&lt;/a&gt; 🤖:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/darkreader/&quot;&gt;Dark Reader&lt;/a&gt;: an extension that modifies the styles of websites to make them dark-themed. It can also auto-switch depending on the system’s theme (light vs. dark), or detect the theme of the website in order to not interfere. It’s the best at what it does.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/leechblock-ng/&quot;&gt;LeechBlock NG&lt;/a&gt;: an extension that helps me with building healthy habits by blocking distracting websites during certain hours of the day, or how long I’ve spent on those websites.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/sponsorblock/&quot;&gt;SponsorBlock - Skip Sponsorships on YouTube&lt;/a&gt;: as the name suggests, it skips the sponsorships. I already pay for YouTube Premium, I’d rather not watch any ads, even when embeded in the video.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/styl-us/&quot;&gt;Stylus&lt;/a&gt;: Helps with modifying the styles of websites. I rarely need it, but it’s so nice to have when I do.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/&quot;&gt;uBlock Origin&lt;/a&gt;: The best ad-blocker, period. Chrome stopped supporting it, now it’s only available on Firefox. For example, it’s the only one that attempts ad-blocking Facebook.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/view-page-archive/&quot;&gt;Web Archives&lt;/a&gt;: View archived and cached versions of web pages on various search engines, such as the Wayback Machine and Archive․is.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/yang-addon/&quot;&gt;Yang!&lt;/a&gt;: An extension that brings client-side search bangs (which first appeared in &lt;a href=&quot;https://duckduckgo.com/bangs&quot;&gt;DuckDuckGo&lt;/a&gt;). You can keep using your favorite search engine (e.g., Google), it avoids an extra server roundtrip (which may be problematic for privacy as well), it’s faster, and it’s supported on Android.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the desktop only:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/1password-x-password-manager/&quot;&gt;1Password&lt;/a&gt;: The &lt;a href=&quot;https://alexn.org/blog/2024/08/20/1password-vs-bitwarden/&quot;&gt;best password manager&lt;/a&gt;, kind of expensive, though.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/activate-reader-view/&quot;&gt;Activate Reader View&lt;/a&gt;: Sometimes Firefox’s Reader View can’t be activated due to it not detecting an article on the page. This extension forces the “reader view” to be activated.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/audiocontext-suspender/&quot;&gt;AudioContext Suspender&lt;/a&gt;: This fixes an issue with Firefox due to how websites wrongly use AudioContexts, preventing battery drain.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/auto-tab-discard/&quot;&gt;Auto Tab Discard&lt;/a&gt;: Inactivates tabs that haven’t been used in a while, freeing up memory and CPU. Chromiums started adding this as a feature, but this extension has customization options, like what tabs should never be discarded.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/clickbait-remover-for-youtube/&quot;&gt;Clickbait Remover for Youtube&lt;/a&gt;: Replaces thumbnails and modifies titles on YouTube to remove clickbait. It works.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/close-tabs-shortcuts/&quot;&gt;Close Tabs Shortcuts&lt;/a&gt; + &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/toggle-pin-tab/&quot;&gt;Toggle Pin Tab&lt;/a&gt;: I need &lt;code&gt;Alt-P&lt;/code&gt; for (un)pinning the current tab, and &lt;code&gt;Alt-W&lt;/code&gt; for “close other tabs”. Firefox, unfortunately, doesn’t allow for adding or customizing shortcuts for such tab actions, out of the box, but there’s nothing that an extension can’t fix.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/floccus/&quot;&gt;Floccus&lt;/a&gt;: This can sync your bookmarks between browsers, so for example, you can maintain the same set of bookmarks between Firefox and Chromium. It can use a GitHub repository as the backend.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/languagetool/&quot;&gt;LanguageTool&lt;/a&gt;: I’m not a native English speaker, so this helps me with grammar and spelling. The server is FOSS and can be installed offline, but I pay for Premium. The company is from the EU, so that’s a plus.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/linkding-extension/&quot;&gt;Linkding extension&lt;/a&gt; + &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/single-file/&quot;&gt;SingleFile&lt;/a&gt;: I have my own &lt;a href=&quot;https://links.alexn.org&quot;&gt;Linkding server&lt;/a&gt;, that works like Pinboard, a repository of searchable links, some of which are shared. The Linkding extension also has integration with “SingleFile”, which is another extension that can save a copy of the page you’re viewing as a single HTML file, such that it’s archived on the Linkding server.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/old-reddit-redirect/&quot;&gt;Old Reddit Redirect&lt;/a&gt;: Redirects Reddit links to &lt;code&gt;old.reddit.com&lt;/code&gt; because the new UI sucks.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/rsspreview/&quot;&gt;RSSPreview&lt;/a&gt;: Finds and previews RSS feeds on websites. Useful if you use a feed reader.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/sidebery/&quot;&gt;Sideberry&lt;/a&gt;: Vertical tabs tree. I don’t use “tree style tabs” all the time, but (compared with tab groups) trees are automatic, and when I need this sidebar, it’s one &lt;code&gt;Ctrl-E&lt;/code&gt; away.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/streetpass-for-mastodon/&quot;&gt;StreetPass for Mastodon&lt;/a&gt;: Discover people you’d like to follow on Mastodon, by the websites you visit. It’s based on the &lt;a href=&quot;https://docs.joinmastodon.org/spec/webfinger/&quot;&gt;WebFinger&lt;/a&gt; protocol. So if you’re vising my website, you should get a suggestion for &lt;a href=&quot;https://social.alexn.org/@alexelcu&quot;&gt;@alexelcu@social.alexn.org&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/substitoot/&quot;&gt;Substitoot — improved Mastodon federation&lt;/a&gt;: This extension loads missing replies and stats for posts on Mastodon. My instance is a small one (it’s only me on it) and without this extension I wouldn’t see the replies of the posts from my feed, which is somewhat of a flaw in the distributed nature of Mastodon.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/tabliss/&quot;&gt;Tabliss&lt;/a&gt;: New Tab page with beautiful backgrounds and a clean design.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/vimium-ff/&quot;&gt;Vimium&lt;/a&gt;: Vim-like keybindings for Firefox. With it, you can discard the mouse or touchpad, and use just the keyboard to navigate the web. It’s great and very addictive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What are your favorite Firefox extensions? Any goodies I should try?&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/03/15/firefox-extensions/?pk_campaign=rss&quot;&gt;My Favorite Firefox Extensions&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sat, 15 Mar 2025 18:29:27 +0000</pubDate>
  <dc:modified>Sat, 15 Mar 2025 21:38:27 +0000</dc:modified>
  <atom:modified>Sat, 15 Mar 2025 21:38:27 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/03/15/firefox-extensions/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/03/15/firefox-extensions/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Browser</category>
  <category>Open Source</category>
  <category>Products</category>
  <category>Web</category>
  </item>


<item>
  <title>Use Firefox in 2025</title>
  <description>I grew up with the Internet, since before people had Internet connections at home or in their pocket. The browser, being the window to the open web, holds a special place in my heart. In this article I’m suggesting the use of Firefox in 2025, for both technical and political reasons, as it’s still the “user agent” that it set out to be.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  I grew up with the Internet, since before people had Internet connections at home or in their pocket. The browser, being the window to the open web, holds a special place in my heart. In this article I’m suggesting the use of Firefox in 2025, for both technical and political reasons, as it’s still the &lt;em&gt;“user agent”&lt;/em&gt; that it set out to be.
&lt;/p&gt;

&lt;h2 id=&quot;on-the-desktop&quot;&gt;On the desktop&lt;/h2&gt;

&lt;p&gt;Firefox remains the only one supporting &lt;a href=&quot;https://github.com/gorhill/uBlock&quot;&gt;uBlock Origin&lt;/a&gt;, the version that’s not defective by the design of the browser. Many may not notice a difference by using its &lt;a href=&quot;https://github.com/uBlockOrigin/uBOL-home&quot;&gt;Lite version&lt;/a&gt;, the one based on Manifest v3, but I can tell you that most ad-blocking tech is easy to circumvent, whereas the full version of uBlock Origin has been the nightmare of online advertisers.&lt;/p&gt;

&lt;p&gt;Firefox can have extensions that expose a sidebar. This is how &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/sidebery/&quot;&gt;Sideberry&lt;/a&gt; or &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/tree-style-tab/&quot;&gt;Tree Style Tab&lt;/a&gt; can work. Tab grouping from Chrome is nice, but you have to make a conscious effort to use groups, whereas trees are automatic, and you can simply hide that sidebar if you’re not interested in it. It actually works well with Firefox’s vertical tabs, with &lt;code&gt;Ctrl-E&lt;/code&gt; toggling my “Sideberry” panel whenever I need it, otherwise seeing a nice vertical column of icons.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  Vertical tabs have been officially released in &lt;a href=&quot;https://www.mozilla.org/en-US/firefox/136.0/releasenotes/&quot;&gt;Firefox 136&lt;/a&gt;, and the implementation seems to be quite good. Tab groups (experimental) can be enabled if you toggle &lt;code&gt;browser.tabs.groups.enabled&lt;/code&gt; in &lt;code&gt;about:config&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Ctrl-Tab&lt;/code&gt; in Firefox has the best behavior, and it’s nice that if you keep &lt;code&gt;Ctrl&lt;/code&gt; pressed it shows you a graphical switcher previewing around 7 tabs on my laptop’s screen. I’ve only seen something equivalent in Vivaldi.&lt;/p&gt;

&lt;p&gt;Firefox has great privacy, with features such as &lt;a href=&quot;https://blog.mozilla.org/en/products/firefox/firefox-rolls-out-total-cookie-protection-by-default-to-all-users-worldwide/&quot;&gt;Total Cookie Protection&lt;/a&gt; which isolate third-party cookies without breaking websites. It also blocks many trackers by default, although note that I don’t enable “Strict” mode, as it breaks websites (and honestly, uBlock Origin is enough). It’s still nice that it blocks the worst privacy offenders out of the box.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/multi-account-containers/&quot;&gt;Multi-account Containers&lt;/a&gt; are really nice when you have to manage multiple accounts for the same online service (e.g., AWS). Although, note that it doesn’t do much for privacy (ever since Total Cookie Protection) and the feature provides less isolation than when using “profiles”.&lt;/p&gt;

&lt;p&gt;The suggestions in the address bar, aka “Awesome Bar”, are the best. Don’t get me wrong, Chromium’s Omnibar is pretty good, as well, but despite its improvements, IMO it’s still prioritizing search over bookmarks and history.&lt;/p&gt;

&lt;p&gt;Firefox’s history synchronization works better than in all Chromium browsers I’ve tested. Chrome’s synchronized history is missing items when you’re enabling encryption, like for example when you’re jumping from page to page by clicking links. What gets synchronized are the pages and the searches that you enter directly in the address bar. And the time window is more limited. Firefox’s history of visited URLs, and its bookmarks, are helpful when using its address bar, as it can reliably give you suggestions, thus avoiding Google searches.&lt;/p&gt;

&lt;p&gt;Firefox supports &lt;a href=&quot;https://en.wikipedia.org/wiki/DNS_over_HTTPS&quot;&gt;DNS over HTTPS&lt;/a&gt; with the best customizability — i.e., it can fall back to the system’s DNS. This is important for me in case I’m connected to the corporate VPN in charge of serving corporate resources, but I still want my regular DNS queries to go through my own DoH service, encrypted as well.&lt;/p&gt;

&lt;p&gt;Firefox has &lt;a href=&quot;https://support.mozilla.org/en-US/kb/website-translation&quot;&gt;offline translations&lt;/a&gt; via offline AI. I remember disliking Google Translate because it is slow, and I also worried about my privacy, as you’re sending your web page to a server. Speaking of, if you think AI isn’t useful in a browser and that Mozilla shouldn’t invest in AI, well, here’s one sample where you’re definitely wrong.&lt;/p&gt;

&lt;p&gt;Other things I like:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Firefox has had the best Linux and BSD support. For example, many switched to it due to its support for Wayland.&lt;/li&gt;
  &lt;li&gt;The PDF viewer has support for editing PDF documents. On macOS this doesn’t sound like much (due to Preview), but on Windows or Linux it’s a blessing.&lt;/li&gt;
  &lt;li&gt;UI of Picture-in-Picture is nice and PiP can be automatic when you switch tabs (in preview / labs).&lt;/li&gt;
  &lt;li&gt;The Reader View is good and reliable (also &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/activate-reader-view/&quot;&gt;see this extension&lt;/a&gt; to force activate it in the rare cases where article detection fails).&lt;/li&gt;
  &lt;li&gt;Has great customizability, even though it feels limited at times — there’s nothing that an extension, a custom stylesheet or some setting in &lt;code&gt;about:config&lt;/code&gt; can’t fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;for-android-mobile&quot;&gt;For Android (Mobile)&lt;/h2&gt;

&lt;p&gt;Firefox on Android supports extensions, and here are the ones I’m using:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/cookie-autodelete/&quot;&gt;Cookie AutoDelete&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/darkreader/&quot;&gt;Dark Reader&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/leechblock-ng/&quot;&gt;LeechBlock NG&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/sponsorblock/&quot;&gt;SponsorBlock - Skip Sponsorships on YouTube&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/styl-us/&quot;&gt;Stylus&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/&quot;&gt;uBlock Origin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/view-page-archive/&quot;&gt;Web Archives&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/yang-addon/&quot;&gt;Yang!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of these features may be built into some of the available browsers, but not all of them, plus the functionality provided is better, for example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Dark Reader is better than the &lt;em&gt;“apply dark theme to websites”&lt;/em&gt; checkbox from Chrome (activated via &lt;code&gt;chrome://flags&lt;/code&gt;), it usually gets out of the way, but also allowing customizations for when it fails; I’m also one of those users that auto-switches to dark mode only at night.&lt;/li&gt;
  &lt;li&gt;Cookie AutoDelete is built into the Brave browser, but with fewer customizations and functionality; being a power user, I prefer Firefox’s extension.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other features of Firefox for Android that I like:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
&lt;em&gt;“Open in another app”&lt;/em&gt; can be disabled, or Firefox can ask what you want. It also provides a neat shortcut in the menu if you change your mind.&lt;/li&gt;
  &lt;li&gt;New Tab page is helpful.&lt;/li&gt;
  &lt;li&gt;Synchronization of tabs with the desktop works well, and the UI is nice (I like that I can find where it is).&lt;/li&gt;
  &lt;li&gt;Reader Mode works well. Compared with the desktop, it can’t do text to speech on its own, but there are other solutions for that, including built-in Android functionality or Pocket.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Firefox for Android has issues, such as poor performance on some websites (e.g., Mastodon, I even &lt;a href=&quot;https://github.com/mastodon/mastodon/issues/32554&quot;&gt;opened an issue&lt;/a&gt;) or poor PWA support. But I use my mobile browser primarily for reading articles, and for that, having a good ad-blocker, dark mode (for when needed), or a working reader mode are much more important.&lt;/p&gt;

&lt;h2 id=&quot;firefox-the-user-agent&quot;&gt;Firefox, the User Agent&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/User_agent&quot;&gt;user agent&lt;/a&gt; is a piece of software responsible for interacting with the web, such as a browser, but it’s critical that this agent represents the user and its interests. A user agent shouldn’t represent the interests of the publishers or that of the advertisers while harming the user. Publishers and advertisers are important as well, but the user should come first.&lt;/p&gt;

&lt;p&gt;Think of Chrome. When you log into Chrome, it automatically logs you into your Google account on the web. It also activates a setting named &lt;em&gt;“improve search suggestions”&lt;/em&gt; by which Chrome shares your navigation history with Google. It doesn’t matter if you have encryption enabled, that feature will be on for every new device, as it’s not synchronizing from your account’s settings either. Chrome is adversarial towards users. On every released version, any privacy conscious user would have to carefully read its release notes and look at its settings page, thinking about &lt;em&gt;“how will these new features screw me in the future?”&lt;/em&gt; Do you like uBlock Origin? Google has deprecated it and lied about the reasoning for doing so, knowing full well that the replacement is much less capable. We’re talking about the desktop because Chrome on Android does not support extensions, even though it could without much effort, being the same codebase.&lt;/p&gt;

&lt;p&gt;Chrome is an excellent browser, but when the user’s interests conflict with that of Google, it’s the interests of Google that win.&lt;/p&gt;

&lt;p&gt;A browser being a good user agent isn’t solely about trust, but about ability as well. A browser isn’t a good user agent if it can’t be extended in ways that conflicts with the interests of its maker. You need extensions &lt;a href=&quot;https://andregarzia.com/2025/02/retaking-the-web-browser-one-small-step-at-a-time.html&quot;&gt;to retake your browser&lt;/a&gt;. I believe Firefox is still a worthy User Agent, despite Mozilla’s blunders. This isn’t just a feeling, but a fact based in Firefox’s current technical abilities.&lt;/p&gt;

&lt;p&gt;But for Firefox’s sake, I hope Mozilla understands why many people still use Firefox because once trust is lost, it may never return.&lt;/p&gt;

&lt;h2 id=&quot;politics&quot;&gt;Politics&lt;/h2&gt;

&lt;p&gt;I tried staying apolitical for a long time, but this is no longer possible, as this is now about my self-interest. And given the worldwide politics, especially in light of the US administration becoming hostile towards the European Union, I’m becoming increasingly more uncomfortable using or recommending products or services from the US’s Big Tech companies. Likewise, I’m uncomfortable with products built by MAGA figures. When other people place their country first, voting for an administration that turns against allies, I have to remember that I’m a European first, sorry.&lt;/p&gt;

&lt;p&gt;You may disagree, and that’s fine by me. Software is usually amoral, and your threat model may be different from mine. But being EU-friendly is important to me for obvious reasons and unfortunately, in the world we now inhabit, I find myself increasingly wary about the software that I’m adopting. And don’t get me wrong, I try avoiding Russian and Chinese software and services as well 🤷‍♂️&lt;/p&gt;

&lt;p&gt;Other browsers that would bring me some peace of mind would be &lt;a href=&quot;https://www.torproject.org/&quot;&gt;Tor&lt;/a&gt;, &lt;a href=&quot;https://mullvad.net/&quot;&gt;Mullvad&lt;/a&gt;, or &lt;a href=&quot;https://vivaldi.com/&quot;&gt;Vivaldi&lt;/a&gt;. There may be others, like &lt;a href=&quot;https://zen-browser.app/&quot;&gt;Zen&lt;/a&gt;. As a general rule, they either have to be community maintained or backed by an EU company, with Firefox being the only exception that I’m going to allow, for now.&lt;/p&gt;

&lt;p&gt;Note that I’m not naive about where the major contributions are coming from. There are only 3 major browser engines, all 3 developed by US companies, all 3 primarily funded by Google’s Ads. But I can live with Open-Source and I think the forks can do a reasonable job at disabling hostile functionality, such as all the phoning to the mothership, with &lt;a href=&quot;https://privacytests.org/&quot;&gt;mixed results&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;controversies&quot;&gt;Controversies&lt;/h2&gt;

&lt;p&gt;Mozilla isn’t without controversy, and lately, they’ve &lt;a href=&quot;https://blog.mozilla.org/en/mozilla/mozilla-leadership-growth-planning-updates/&quot;&gt;doubled down&lt;/a&gt; on them diversifying their revenue via more advertising, &lt;a href=&quot;https://blog.mozilla.org/en/products/firefox/update-on-terms-of-use/&quot;&gt;updating their privacy&lt;/a&gt; to make it unambiguous that they intend to share your personal data with advertisers. Yikes!&lt;/p&gt;

&lt;p&gt;Many people view this as a betrayal of their values, and there’s some truth to that. Take a look at this old ad, when they seemed to have more of a drive for doing the right thing:&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=AIKLdVEWPrE&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/AIKLdVEWPrE/hqdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=AIKLdVEWPrE&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Firefox a different kind of browser
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;But when talking about Mozilla’s direction, one has to keep in mind that to develop and maintain a browser, you need a lot of money. In our country, we have a saying like &lt;em&gt;“you’re my brother, but cheese costs money”.&lt;/em&gt; Chrome’s estimates, for example, exceed 1 billion $ per year in development costs. People don’t want to pay for browsers, you can’t rely on the donations of people preferring to ad-block YouTube instead of paying for Premium. And asking for governments, like the EU, to fund it is not a great idea for obvious reasons, such as Mozilla not being an EU entity or the fact that the state serves the interest of their taxpayers, and not the interest of the whole world.&lt;/p&gt;

&lt;p&gt;Mozilla has been surviving on Google’s Ads ever since the Search deal. Google, at this point, is funding all 3 major browser engines, and this includes Safari, given that Google is paying Apple around 20 billions per year in the search deal. This has consequences. For example, even though both Mozilla and Apple have been singing the privacy tune, they never did anything to upset their cash cow, which is Google Search. So let’s be honest — Firefox has been funded by ad-tech since 2006, and Mozilla diversifying their revenue can’t be a worse betrayal of their values than what happened since then.&lt;/p&gt;

&lt;p&gt;What’s important for me aren’t the words, but what they actually accomplish. Thus far, Firefox has gone to further lengths than any other browser to preserve privacy in ways that actually matter. For example, the aforementioned &lt;a href=&quot;https://support.mozilla.org/en-US/kb/website-translation&quot;&gt;offline translation&lt;/a&gt; feature that doesn’t leak your web page to an online server. I also remember when they released &lt;a href=&quot;https://github.com/mozilla/pdf.js&quot;&gt;PDF.js&lt;/a&gt;, so back when the PDF viewer in Chrome was a proprietary blob (FoxIt, does it still ship with it?), Mozilla was like “hold my beer” and built an Open-Source PDF viewer in freaking JavaScript and HTML. Their history is filled with great feats, both old and recent, that just can’t be easily erased.&lt;/p&gt;

&lt;p&gt;In fact, the introduction of their &lt;a href=&quot;https://support.mozilla.org/en-US/kb/privacy-preserving-attribution&quot;&gt;privacy-preserving attribution&lt;/a&gt; feature is far more worrying than any of the new words in their Privacy Policy. On the other hand, I can give them the benefit of the doubt, at least for now. At the very least, I know that they’ll try making PPA privacy-preserving. Mostly because I don’t have much choice left.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/03/03/use-firefox/?pk_campaign=rss&quot;&gt;Use Firefox in 2025&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 03 Mar 2025 21:51:40 +0000</pubDate>
  <dc:modified>Sat, 15 Mar 2025 18:27:58 +0000</dc:modified>
  <atom:modified>Sat, 15 Mar 2025 18:27:58 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/03/03/use-firefox/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/03/03/use-firefox/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Browser</category>
  <category>Open Source</category>
  <category>Politics</category>
  <category>Products</category>
  <category>Web</category>
  </item>


<item>
  <title>Self-hosted Bookmarks Manager</title>
  <description>I like having a database of links I encounter on the web, like a searchable database, complete with archive links as well. I found a solution.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  I like having a database of links I encounter on the web, like a searchable database, complete with archive links as well. I found a solution.
&lt;/p&gt;

&lt;p&gt;Storing bookmarks in your browser is OK, especially if you use a solution for synchronizing that archive, such as &lt;a href=&quot;https://floccus.org/&quot;&gt;floccus&lt;/a&gt; (&lt;a href=&quot;https://github.com/floccusaddon/floccus&quot;&gt;GitHub&lt;/a&gt;), but that’s not enough, as I also want it to be searchable (with tags and descriptions) and shareable. I used Pinboard, Pocket, private notes, &lt;a href=&quot;https://alexn.org/wiki/teach-kids/&quot;&gt;wiki notes&lt;/a&gt; and I even tried a links section on this blog.&lt;/p&gt;

&lt;p&gt;I finally found a Pinboard-like replacement that I can easily self-host and that’s just perfect for my needs: &lt;a href=&quot;https://linkding.link/&quot;&gt;linkding&lt;/a&gt; (&lt;a href=&quot;https://github.com/sissbruecker/linkding&quot;&gt;GitHub link&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;My links are now hosted here: &lt;a href=&quot;https://links.alexn.org/&quot;&gt;links.alexn.org&lt;/a&gt; (&lt;a href=&quot;https://links.alexn.org/feeds/shared&quot;&gt;RSS feed&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;The official &lt;a href=&quot;https://linkding.link/installation/&quot;&gt;installation instructions&lt;/a&gt; are pretty good, but in case it helps, what follows is my setup.&lt;/p&gt;

&lt;p&gt;Entry in my &lt;code&gt;docker-compose.yaml&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;linkding:
  container_name: linkding
  image: sissbruecker/linkding:latest
  restart: unless-stopped
  healthcheck:
    test: [&quot;CMD-SHELL&quot;, &quot;curl --silent --fail http://localhost:9090/health || exit 1&quot;]
  ports:
    - &quot;3009:9090&quot;
  volumes:
    - &apos;linkding:/etc/linkding/data&apos;
  networks:
    - external_network
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;My Nginx reverse-proxy setup:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-conf&quot;&gt;location / {
    root   /var/www/links.alexn.org;
    include ./snippets/cloudflare-ips.conf;
    
    proxy_pass http://0.0.0.0:3009;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;

    # Prevent Cloudflare from caching while allowing client caching
    add_header Cache-Control &quot;private, no-transform&quot;;
    add_header CDN-Cache-Control &quot;no-store, no-cache&quot;;  # Cloudflare-specific
    add_header Cloudflare-CDN-Cache-Control &quot;no-store&quot;; # Cloudflare-specific
}

location /static/ {
    root   /var/www/links.alexn.org;
    include ./snippets/cloudflare-ips.conf;
    
    proxy_pass http://0.0.0.0:3009;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    
    # Nginx caching
    proxy_cache CACHE;
    proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
    proxy_cache_valid 200 302 30d;
    proxy_cache_valid 404 1m;
    proxy_cache_key $host$request_uri;
    
    # Cache settings for browsers and CDN
    expires 30d;
    add_header Cache-Control &quot;public, no-transform&quot;;
    add_header Vary Accept-Encoding;
    add_header X-Cache-Status $upstream_cache_status; # Optional: helps with debugging
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’m also doing targeted &lt;a href=&quot;https://alexn.org/blog/2022/12/02/personal-server-backups/&quot;&gt;server backups&lt;/a&gt;, so here’s the script that I’m periodically executing via cron:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/bin/bash

set -e

FILENAME=&quot;linkding-$(date +&quot;%Y-%m&quot;).zip&quot;
FILEPATH=&quot;/var/lib/my-backups/$FILENAME&quot;
CONTAINER_BACKUP=&quot;/etc/linkding/data/backup.zip&quot;

if [ &quot;$(docker inspect -f &apos;{{.State.Running}}&apos; linkding)&quot; ]; then
  echo &quot;[$(date +&quot;%Y-%m-%d %H:%M:%S%z&quot;)] Generating $FILEPATH&quot;
  docker exec -it linkding python manage.py full_backup &quot;$CONTAINER_BACKUP&quot;
  docker cp linkding:&quot;$CONTAINER_BACKUP&quot; &quot;$FILEPATH&quot;
  docker exec linkding rm -f &quot;$CONTAINER_BACKUP&quot;

  if [ -f &quot;$FILEPATH&quot; ]; then
    rclone copy &quot;$FILEPATH&quot; &quot;backup:AlexnOrg/Linkding/&quot;
  fi
fi

rm -f /var/lib/my-backups/linkding-*.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With the cron entry being like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;50 */6 * * * root cronic /path/to/bin/vm-backup-linkding
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ensure to &lt;a href=&quot;https://alexn.org/blog/2025/02/14/updating-docker-containers/&quot;&gt;auto-upgrade it&lt;/a&gt; as well.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/02/14/self-hosted-bookmarks-manager/?pk_campaign=rss&quot;&gt;Self-hosted Bookmarks Manager&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 14 Feb 2025 05:03:54 +0000</pubDate>
  <dc:modified>Fri, 14 Feb 2025 05:23:09 +0000</dc:modified>
  <atom:modified>Fri, 14 Feb 2025 05:23:09 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/02/14/self-hosted-bookmarks-manager/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/02/14/self-hosted-bookmarks-manager/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Docker</category>
  <category>Open Source</category>
  <category>Self Hosting</category>
  <category>Server</category>
  <category>Web</category>
  </item>


<item>
  <title>Auto-updating Docker containers</title>
  <description>I’m self-hosting stuff using Docker on my own server. One problem that comes up for a personal server is to keep it up to date, as old software has security issues. And we don’t want to self-host servers that can become vulnerable due to neglect.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  I&apos;m self-hosting stuff using Docker on my own server. One problem that comes up for a personal server is to keep it up to date, as old software has security issues. And we don&apos;t want to self-host servers that can become vulnerable due to neglect.
&lt;/p&gt;

&lt;p&gt;There are a bunch of solutions floating around, but for a personal server, the most pragmatic solution I found is a simple script:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/usr/bin/env bash
set -e

cd &quot;$(dirname &quot;$0&quot;)&quot; || exit 1
BINDIR=&quot;$(pwd)&quot;
SC=&apos;\033[0;36m&apos; # Cyan (0;36)
NC=&apos;\033[0m&apos; # No Color

printf &quot;${SC}------------------------------------------------${NC}\n&quot;
printf &quot;${SC}Updating &amp; Cleaning Docker — $(date +&quot;%Y-%m-%d %H:%M:%S %Z&quot;)${NC}\n&quot;
printf &quot;${SC}------------------------------------------------${NC}\n&quot;

printf &quot;\n${SC}&gt; docker image prune -af${NC}\n\n&quot;
docker image prune -af  2&gt;&amp;1

printf &quot;\n${SC}&gt; docker images | grep -v REPOSITORY | awk &apos;{print \$1\&quot;:\&quot;\$2}&apos; | xargs -Iname docker pull name${NC}\n\n&quot;
docker images | grep -v REPOSITORY | awk &apos;{print $1&quot;:&quot;$2}&apos; | xargs -Iname docker pull --quiet name 2&gt;&amp;1

printf &quot;\n${SC}&gt; docker compose up -d --remove-orphans${NC}\n\n&quot;
docker compose up -d --remove-orphans  2&gt;&amp;1

printf &quot;\n${SC}&gt; docker image prune -af${NC}\n\n&quot;
docker image prune -af  2&gt;&amp;1

printf &quot;\n${SC}&gt; docker system prune -f${NC}\n\n&quot;
docker system prune -f  2&gt;&amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can then add this to &lt;code&gt;/etc/cron.d/&lt;/code&gt; to run once per day:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-cron&quot;&gt;0 3 * * * root cronic /path/to/bin/vm-docker-update-all
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that I’m using &lt;a href=&quot;https://habilis.net/cronic/&quot;&gt;cronic&lt;/a&gt; for getting alerted over email when my cron scripts are failing. You can ignore that part.&lt;/p&gt;

&lt;p&gt;The astute reader will wonder — doesn’t this aggressive policy have the potential to break your setup? Upgrades for docker images, especially &lt;code&gt;latest&lt;/code&gt; images, aren’t necessarily security upgrades. So the answer is: of course, new versions can break backwards compatibility with your current setup (e.g., database schemas), but I’d rather have a broken server than a vulnerable one. And I think the only problem I encountered thus far was when my &lt;a href=&quot;https://social.alexn.org/&quot;&gt;Mastodon instance&lt;/a&gt; was automatically upgraded from 4.2.x to 4.3.x, but then I quickly got an email from my &lt;a href=&quot;https://alexn.org/blog/2023/01/17/server-monitoring-with-monit/&quot;&gt;Monit instance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With upgrade policies in place, health monitoring and &lt;a href=&quot;https://alexn.org/blog/2022/12/02/personal-server-backups/&quot;&gt;backups&lt;/a&gt;, self-hosting stuff is cheap and joyful.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2025/02/14/updating-docker-containers/?pk_campaign=rss&quot;&gt;Auto-updating Docker containers&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 14 Feb 2025 05:00:00 +0000</pubDate>
  <dc:modified>Fri, 14 Feb 2025 13:01:58 +0000</dc:modified>
  <atom:modified>Fri, 14 Feb 2025 13:01:58 +0000</atom:modified>
  <link>https://alexn.org/blog/2025/02/14/updating-docker-containers/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2025/02/14/updating-docker-containers/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Docker</category>
  <category>Self Hosting</category>
  <category>Server</category>
  </item>


<item>
  <title>Join the Open Web</title>
  <description>Now that you’ve seen the dangers of social media, the question is, what are you going to do about it?</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2024/11/20/join-the-open-web/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2024-www-painting.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;694&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;&quot;Discussing The Divine Comedy With Dante&quot;, a painting by Dai Dudu, Li Tiezi and Zhang An
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
Now that you&apos;ve seen the dangers of social media, the question is, what are you going to do about it?
&lt;/p&gt;

&lt;p&gt;Social media networks are built to be walled gardens, and come with all the problems of walled gardens. For instance, social media networks can be bought and remade in the image of their owners, they can deprioritize your posts if you’re not paying, they can indoctrinate you via algorithms meant for maximizing engagement, they can ban you for wrongthink.&lt;/p&gt;

&lt;p&gt;Maybe it’s time for you to adopt the open web, in these (possibly not so) easy steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Adopt an RSS/Atom feed reader.&lt;/li&gt;
  &lt;li&gt;Own your online identity, by starting a blog on your domain.&lt;/li&gt;
  &lt;li&gt;Break up with your smartphone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Social media posts are shallow, whereas more thought and details goes into website articles and blog posts. Your favorite people on the web have better thoughts when they blog. And RSS/Atom feeds are still the best way to consume the web.&lt;/p&gt;

&lt;p&gt;You don’t want your livelihood to depend on the whims of algorithms or polarized mobs or tech owners that want to do politics. Starting a blog on your domain is still the best way to have an online voice.&lt;/p&gt;

&lt;p&gt;Blogs are still relevant and awesome. Initially, you may not have much of an audience, but you need to remember that the primary audience for your blog is you. The more you write, the more you clarify your thoughts, and also, the more you remember. My blog is also a personal wiki. That you get an audience out of it, that’s a bonus. Although, note that people who have had blogs for a while actually get more traffic on their blogs; that’s because blogs get linked in documentation, or are indexed by search engines, or are subscribed (by RSS or email) by loyal followers, so the traffic you get is constant, whereas the traffic for social media posts is fleeting.&lt;/p&gt;

&lt;p&gt;I like alternatives like Mastodon and Bluesky, but make no mistake about it — the perils are still there because it’s the same format that drives people to shallowness and polarization, and their distribution and federation story is less than ideal. Yes, join Mastodon or Bluesky, but use social networks primarily for the distribution of web links and for the discovery of blogs that you can follow. &lt;a href=&quot;https://alexn.org/blog/2023/09/21/post-once-syndicate-everywhere-pose/&quot;&gt;Adopt POSSE!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Social media is driven by its always-on availability due to the internet-connected device in our pocket. It’s junk food for socialization or for staying up to date. If we remove social media from our phone, its appeal drops. Therefore, we have to &lt;a href=&quot;https://www.goodreads.com/book/show/40672036-digital-minimalism&quot;&gt;adopt digital minimalism&lt;/a&gt; and make our smartphone a dumber one by uninstalling all addictive slot machines from it.&lt;/p&gt;

&lt;p&gt;Write and read blogs, you’ll be happier for it 😉&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2024/11/20/join-the-open-web/?pk_campaign=rss&quot;&gt;Join the Open Web&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 20 Nov 2024 07:43:54 +0000</pubDate>
  <dc:modified>Wed, 20 Nov 2024 11:17:04 +0000</dc:modified>
  <atom:modified>Wed, 20 Nov 2024 11:17:04 +0000</atom:modified>
  <link>https://alexn.org/blog/2024/11/20/join-the-open-web/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2024/11/20/join-the-open-web/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Blogging</category>
  <category>Opinion</category>
  <category>Politics</category>
  <category>Web</category>
  </item>


<item>
  <title>Cancellable HTTP requests via Scala&#39;s Tapir</title>
  <description>This sample shows an HTTP server and an HTTP client that can cleanly cancel requests. It’s using Tapir and Sttp, with Netty and AsyncHttpClient backends, all powered by Cats-Effect.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  This sample shows an HTTP server and an HTTP client, that can cleanly cancel requests, both on the client-side and on the server-side. This is needed for safe disposal of resources. 
&lt;/p&gt;

&lt;p&gt;On the client-side, it’s important to close or reuse the connection early, to avoid connection leaks. And on the server-side, the cancellation signal can be received when the client closes its connection, so the server may choose to cancel the processing of the request, since there’s no longer a client waiting for the response.&lt;/p&gt;

&lt;p&gt;This sample is using &lt;a href=&quot;https://github.com/softwaremill/tapir&quot;&gt;Tapir&lt;/a&gt; for describing HTTP endpoints. For the server backend, Tapir is configured to use Netty. And for the client making HTTP requests, it’s using &lt;a href=&quot;https://github.com/softwaremill/sttp&quot;&gt;Sttp&lt;/a&gt;, powered by the standard &lt;a href=&quot;https://github.com/AsyncHttpClient/async-http-client&quot;&gt;async-http-client&lt;/a&gt;. And I’m also using &lt;a href=&quot;https://github.com/typelevel/cats-effect&quot;&gt;Cats-Effect&lt;/a&gt;, as the effect system because it rocks, with its interruption model being best in class.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;#!/usr/bin/env -S scala shebang

//&gt; using scala &quot;3.3.4&quot;
//&gt; using dep &quot;com.softwaremill.sttp.tapir::tapir-netty-server-cats:1.11.5&quot;
//&gt; using dep &quot;com.softwaremill.sttp.tapir::tapir-sttp-client:1.11.5&quot;
//&gt; using dep &quot;com.softwaremill.sttp.client3::async-http-client-backend-cats:3.9.8&quot;
//&gt; using dep &quot;org.typelevel::cats-effect:3.5.4&quot;
//&gt; using dep &quot;org.slf4j:slf4j-nop:2.0.16&quot;

import cats.effect.*
import cats.effect.std.Dispatcher
import sttp.tapir.*
import sttp.tapir.server.netty.cats.NettyCatsServer
import sttp.client3.*
import sttp.client3.asynchttpclient.cats.AsyncHttpClientCatsBackend
import sttp.tapir.client.sttp.SttpClientInterpreter
import scala.concurrent.duration.*
import scala.concurrent.TimeoutException

object Endpoints:
  type Type = Endpoint[Unit, Unit, Unit, String, Any]

  val slow: Type = endpoint.get
    .in(&quot;slow&quot;)
    .out(stringBody)

  val fast: Type = endpoint.get
    .in(&quot;fast&quot;)
    .out(stringBody)

def startServer: Resource[IO, Unit] =
  val fastEndpoint = Endpoints.fast.serverLogic: _ =&gt;
    IO.pure(Right(&quot;fast response&quot;))

  val slowEndpoint = Endpoints.slow.serverLogic: _ =&gt;
    IO.monotonic.flatMap: startedAt =&gt;
      val task =
        for
          _ &lt;- IO.println(&quot;[Server] Received ping request!&quot;)
          _ &lt;- IO.sleep(10.seconds)
        yield Right(&quot;slow response&quot;)

      task.onCancel:
        for
          now &lt;- IO.monotonic
          elapsedSecs = (now - startedAt).toNanos / 1_000_000_000.0
          _ &lt;- IO.println(
            f&quot;[Server] Request cancelled after $elapsedSecs%.2f seconds!&quot;
          )
        yield ()

  for
    d &lt;- Dispatcher.parallel[IO]
    _ &lt;- Resource
      .make:
        NettyCatsServer[IO](d)
          .port(8080)
          .addEndpoints(List(fastEndpoint, slowEndpoint))
          .start()
      .apply: s =&gt;
        for
          _ &lt;- IO.println(&quot;[Server] Shutting down...&quot;)
          _ &lt;- s.stop()
          _ &lt;- IO.println(&quot;[Server] Bye, bye 👋&quot;)
        yield ()
  yield ()

def makeRequest(e: Endpoints.Type, backend: SttpBackend[IO, Any]): IO[Unit] =
  val send = SttpClientInterpreter()
    .toRequest(e, Some(uri&quot;http://localhost:8080&quot;))
    .apply(())
    .response(asStringAlways)
    .send(backend)
    .flatMap: response =&gt;
      IO.println(s&quot;[Client] Response: ${response.body}&quot;)
    .timeout(1.second)
    .recoverWith:
      case _: TimeoutException =&gt;
        IO(System.err.println(&quot;[Client] ERROR: Request timed out!&quot;))
      case e =&gt;
        IO.apply:
          System.err.println(s&quot;[Client] ERROR Request failed!&quot;)
          e.printStackTrace()
  for
    _ &lt;- IO.println(s&quot;[Client] Sending request to ${e.show}&quot;)
    _ &lt;- send
  yield ()

object Main extends IOApp.Simple:
  override def run: IO[Unit] =
    val resources =
      for
        _ &lt;- startServer
        clientBackend &lt;- AsyncHttpClientCatsBackend.resource[IO]()
      yield clientBackend

    resources.use: clientBackend =&gt;
      for
        _ &lt;- makeRequest(Endpoints.fast, clientBackend)
        _ &lt;- makeRequest(Endpoints.slow, clientBackend)
      yield ()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To run this sample, you can use &lt;a href=&quot;https://scala-cli.virtuslab.org/&quot;&gt;Scala CLI&lt;/a&gt;, which is the default &lt;code&gt;scala&lt;/code&gt; launcher since Scala 3.5.0. For macOS:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Installs the latest Scala via Homebrew
brew install scala

# Makes the above script executable
chmod +x ./tapir-client-server.scala

# Runs the above script
./tapir-client-server.scala
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2024/09/29/cancellable-http-server-client-requests-via-scala-s-tapir/?pk_campaign=rss&quot;&gt;Cancellable HTTP requests via Scala&apos;s Tapir&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 29 Sep 2024 08:21:34 +0000</pubDate>
  <dc:modified>Sun, 29 Sep 2024 09:26:11 +0000</dc:modified>
  <atom:modified>Sun, 29 Sep 2024 09:26:11 +0000</atom:modified>
  <link>https://alexn.org/blog/2024/09/29/cancellable-http-server-client-requests-via-scala-s-tapir/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2024/09/29/cancellable-http-server-client-requests-via-scala-s-tapir/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Cats Effect</category>
  <category>Programming</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Trusting Open-Source</title>
  <description>“Shrink-wrapped”, “off-the-shelf” apps, or what the young have come to know as premium apps from the app store, are destined to languish, to become expensive subscriptions, or to be sold to shady companies that will sell your data or make your computer part of a botnet. Proprietary apps are destined to either disappear, most of them taking your data with them, or to rip you off.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2024/09/06/trusting-open-source/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2024-thomas-surprised.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;2000&quot; height=&quot;1726&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;My cat, Thomas, trying to understand &quot;source available&quot; licenses
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
“Shrink-wrapped”, “off-the-shelf” apps, or what the young have come to know as premium apps from the app store, are destined to languish, to become expensive subscriptions, or to be sold to shady companies that will sell your data or make your computer part of a botnet. Proprietary apps are destined to either disappear, most of them taking your data with them, or to rip you off.
&lt;/p&gt;

&lt;p&gt;I use plenty of proprietary software, my days of FOSS idealism are long gone. But I still prefer Open-Source apps when suitable choices are available. Even if I have to pay for a subscription (e.g., Newsblur), even if it is ads funded (e.g., all browsers), and sometimes even when the product is inferior, as long as it meets my needs (e.g., Gimp). This need is amplified when we build products because I want sane foundations to build on. I would never willingly pick a programming language with a proprietary compiler, a proprietary database system, or depend on proprietary libraries.&lt;/p&gt;

&lt;p&gt;This is because Open-Source can accept contributions, or it can be &lt;em&gt;forked&lt;/em&gt;. If you need control or responsibility, you can assume it. If you don’t have the expertise for it, you can pay others to provide service. You may not want control, or you may not have the resources, but that possibility is there. Open-Source software is not immortal, but as long as there’s interest, people can find ways to keep it going.&lt;/p&gt;

&lt;p&gt;The point of Open-Source isn’t and has never been “&lt;em&gt;source available&lt;/em&gt;”. That’s just a prerequisite and a nice to have. The purpose has always been giving users the freedom to use for whatever purpose, or to fork the software, which in turn translates to lower development costs for the software makers. Software makers have to give up control, the bargain they have to make to receive contributions. This obviously wouldn’t be a good business model, unless you treat the software as a gift to the world, and as a &lt;a href=&quot;https://www.joelonsoftware.com/2002/06/12/strategy-letter-v/&quot;&gt;commoditized complement&lt;/a&gt; of other products or services. Beware of companies selling support for Open-Source software, as this creates the perverse incentive to keep the software difficult to use and insecure.&lt;/p&gt;

&lt;p&gt;There are multiple issues with “&lt;em&gt;source available&lt;/em&gt;” licensing.&lt;/p&gt;

&lt;p&gt;Firstly, Open-Source licensing gives you peace of mind because they are old and tested. You know exactly what you’re getting. The problem with freemium licensing is that money doesn’t change hands, there’s no contract, no negotiation, so the license is all you have, and that license is open to interpretation. Legal departments in corporations may ban copyleft licenses, but copyleft licenses are well understood, whereas licensing that’s designed to ban AWS is not.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
As a side-note, I find it worrying that idealism in youth, nowadays, is less about freedom, and more about hatred against the rich and powerful. On computer forums, whenever you see someone defending Free Software / Open-Source, that person is likely a graybeard that remembers the times before Open-Source software became this common infrastructure we all rely on.
&lt;/p&gt;

&lt;p&gt;You’d think that the source being available is still a good thing because you can read it, helping with understanding and debugging. But that just opens you up to copyright or patent lawsuits, should you end up being inspired by that source code in your own work. This was a thing back when Microsoft had their &lt;a href=&quot;https://en.wikipedia.org/wiki/Shared_Source_Initiative&quot;&gt;Shared Source initiative&lt;/a&gt;, a company that has continuously threatened Linux and Android phone makers with patent lawsuits, even post-Ballmer, while their “Microsoft changed” marketing campaign was ongoing.&lt;/p&gt;

&lt;p&gt;You may be able to contribute to the project, but then you’re just foolishly doing unpaid labor, as you won’t be able to assume control, should you desire it. The raison d’être of Open-Source is gone. And if the software maker goes under, if you built your business on top, forking the software won’t be possible, or if it is under some restricted freedoms, few will want to touch it.&lt;/p&gt;

&lt;p&gt;Note that &lt;a href=&quot;https://mariadb.com/bsl-faq-mariadb/&quot;&gt;BSL&lt;/a&gt;, a license designed for &lt;a href=&quot;https://opensource.org/delayed-open-source-publication&quot;&gt;delayed Open-Source publication&lt;/a&gt;, is at least more honest and better than source-available licensing designed to ban a company’s competition, like &lt;a href=&quot;https://en.wikipedia.org/wiki/Server_Side_Public_License&quot;&gt;SSPL&lt;/a&gt;. Due to the breach of trust, software like MongoDB, Redis or Elasticsearch are dead to me. Interestingly, Elasticsearch recently returned to Open-Source, re-licensed as AGPL, although, I don’t understand why anyone would want to return to it, instead of the more free and more secure &lt;a href=&quot;https://opensearch.org/&quot;&gt;Opensearch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Proprietary software has a place in this world. We all have to put food on the table. Open-Source is infrastructure, it’s “the commons”, but it doesn’t have good business models, and we don’t need control for everything. Some tools can be rented instead of owned. But trust in business is everything. And once gone, it’s gone, although it seems like the young may have to relearn history’s lessons the hard way 🥲&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2024/09/06/trusting-open-source/?pk_campaign=rss&quot;&gt;Trusting Open-Source&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 06 Sep 2024 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2024/09/06/trusting-open-source/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2024/09/06/trusting-open-source/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Open Source</category>
  <category>Proprietary Software</category>
  </item>


<item>
  <title>1Password vs. Bitwarden</title>
  <description>Optimising costs and my workflow is a personal obsession of mine. I&apos;ve been a 1Password user for years, and I keep trying Bitwarden. If you want to pick between the two, here are the differences between them at the time of writing.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  Optimising costs and my workflow is a personal obsession of mine. I&apos;ve been a 1Password user for years, and I keep trying Bitwarden. If you want to pick between the two, here are the differences between them at the time of writing.
&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
Take this comparisson for what it is: a snapshot in time. In a year from now, both would have evolved, and some of these items may no longer be valid.
&lt;/p&gt;

&lt;p&gt;I’m not enumerating here what they both do well, such as trustworthiness, the ability to reliably autofill login credentials, or the cross-platform and cross-browser coverage. These are their pros and cons relative to each other:&lt;/p&gt;

&lt;h2 id=&quot;1password&quot;&gt;1Password&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Significantly better UI and UX — and this isn’t a subjective opinion.&lt;/li&gt;
  &lt;li&gt;Sort by date created / updated — useful to find the items that have changed. This seems like a small thing, but it’s difficult to extract this info from Bitwarden (&lt;a href=&quot;https://alexn.org/wiki/bitwarden/#cli-commands&quot;&gt;see workaround&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Full history of items, available on the web UI — Bitwarden only keeps a history of the main password.&lt;/li&gt;
  &lt;li&gt;Attachments management (that doesn’t suck).&lt;/li&gt;
  &lt;li&gt;Flawless Passkey support — I did not bump into any issues with it.&lt;/li&gt;
  &lt;li&gt;Auto-filling works for TOTP codes, and multi-step dialogs are now automated, no longer requiring intervention (i.e., UIs that first ask for email, then for password, then for TOTP).&lt;/li&gt;
  &lt;li&gt;Useful &lt;a href=&quot;https://developer.1password.com/docs/cli/get-started/&quot;&gt;CLI&lt;/a&gt;, very straightforward to use for managing secrets in your local environment.&lt;/li&gt;
  &lt;li&gt;Flawless unlocking with &lt;a href=&quot;https://support.1password.com/touch-id-mac/&quot;&gt;Touch ID&lt;/a&gt;, including the CLI.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://developer.1password.com/docs/ssh/manage-keys/&quot;&gt;SSH key management&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://support.1password.com/share-items/&quot;&gt;Share items with anyone&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Global shortcut (&lt;code&gt;⌘\&lt;/code&gt;) that’s very efficient, on macOS at least; also on macOS, 1Password can autofill in other apps, not just the browser, easily invoked via this global shortcut.&lt;/li&gt;
  &lt;li&gt;Keyboard shortcuts that work really well — for both the desktop app and the browser extension.&lt;/li&gt;
  &lt;li&gt;“Show in large type”.&lt;/li&gt;
  &lt;li&gt;More document types — e.g. bank accounts, software licenses, Wi-Fi networks.&lt;/li&gt;
  &lt;li&gt;Offline support — possible to edit or save new items while offline.&lt;/li&gt;
  &lt;li&gt;Nicer integration with &lt;a href=&quot;https://support.1password.com/fastmail/&quot;&gt;Fastmail’s masked emails&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Managing the vaults of your organization or family is very intuitive.&lt;/li&gt;
  &lt;li&gt;Exports (for backups or migrations) contain everything, including shared vaults or attachments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As downsides for 1Password:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The autofill behavior for the provided “websites” are limiting — for example, I would have liked URL-prefix matching.&lt;/li&gt;
  &lt;li&gt;Android has some issues — e.g., the aforementioned customizable autofill behavior (i.e., host vs base domain) does not work (I hope they fix it), and sometimes, the UI failed to open, so I had to restart the app.&lt;/li&gt;
  &lt;li&gt;High cost — I pay 68 EUR per year for the family plan (5.65 EUR per month), and I only share the subscription with my son — for professionals this is cheap, but for students, unemployed folks, or the average Joe in general, it’s definitely expensive.&lt;/li&gt;
  &lt;li&gt;Proprietary software, closed-source — this isn’t a problem for me, except…&lt;/li&gt;
  &lt;li&gt;Subscription-based — they used to have a standalone version that was connecting to Dropbox, and it felt like a betrayal when they dropped it.&lt;/li&gt;
  &lt;li&gt;Good, reliable software, but I have trouble trusting companies that took a lot of venture capital and are pressured to grow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;bitwarden&quot;&gt;Bitwarden&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Open Source — being FOSS at the very least protects it somewhat from the company dying or introducing unreasonable prices.
    &lt;ul&gt;
      &lt;li&gt;It has a server-side clone, &lt;a href=&quot;https://github.com/dani-garcia/vaultwarden&quot;&gt;Vaultwarden&lt;/a&gt;, that can be easily self-hosted for $0 — but be warned, the &lt;a href=&quot;https://bitwarden.com/blog/third-party-security-audit/&quot;&gt;third-party audits&lt;/a&gt; do not apply to it.&lt;/li&gt;
      &lt;li&gt;The company may not keep their Open-Source policy (see below).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Usable free plan.&lt;/li&gt;
  &lt;li&gt;Very cheap Premium for solo professionals ($10 / year).&lt;/li&gt;
  &lt;li&gt;Username generator.&lt;/li&gt;
  &lt;li&gt;Usable CLI, although a little awkward, and lacking Touch ID support, AFAIK. You need &lt;a href=&quot;https://jqlang.github.io/jq/&quot;&gt;jq&lt;/a&gt; and general wizardry with Unix command-line tools for it to be usable.&lt;/li&gt;
  &lt;li&gt;Send text or files.&lt;/li&gt;
  &lt;li&gt;Translated in more languages — e.g., Romanian.&lt;/li&gt;
  &lt;li&gt;Usable Passkey support (but see below).&lt;/li&gt;
  &lt;li&gt;The settings for URL matching are more flexible and work on Android as well (vs 1Password, which is experiencing issues).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As downsides for Bitwarden:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Deplorable UI — there’s no other way to describe it; I tried getting my father used to it, but it was mission impossible.
    &lt;ul&gt;
      &lt;li&gt;You have to use both the desktop app and the web vault because both suck in different ways, and neither is sufficient, so you have to throw the CLI in the mix for common maintenance tasks.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;No usable offline support — you can disconnect from the network, but it becomes read-only, and the UI is confusingly letting you edit items, and you can lose those edits.&lt;/li&gt;
  &lt;li&gt;Managing organizations is less than ideal. E.g., if you move items in an organization, you can only change their ownership afterward by cloning them, and you can only do that on the web UI.&lt;/li&gt;
  &lt;li&gt;The browser extension fails to auto-complete TOTP codes, you have to rely on those codes being copied in the clipboard.&lt;/li&gt;
  &lt;li&gt;Almost no usable keyboard shortcuts — i.e., &lt;code&gt;Cmd+Shift+Y&lt;/code&gt; in the browser, for activating the extension, is unusable because it doesn’t let you do anything via the keyboard next. &lt;a href=&quot;https://bitwarden.com/help/keyboard-shortcuts/&quot;&gt;Their documentation&lt;/a&gt; should warn people that the handful of available shortcuts are not usable in keyboard-only flows. The desktop app is really bad at it, e.g., when editing an item, you can’t even press &lt;code&gt;Cmd/Ctrl+S&lt;/code&gt; for save, or &lt;code&gt;Esc&lt;/code&gt; for cancel, like in every other app. This isn’t just a nice to have, for people with visual impairment being an accessibility disaster.&lt;/li&gt;
  &lt;li&gt;Managing attachments is very unintuitive. And you can’t view attached PDFs without downloading them.&lt;/li&gt;
  &lt;li&gt;The browser extension is difficult to configure, e.g., to use Touch ID, although this has more to do with it being more conservative when asking for permissions.&lt;/li&gt;
  &lt;li&gt;Passkey support isn’t as flawless, I bumped into some issues with it when generating passkeys.&lt;/li&gt;
  &lt;li&gt;CLI utility is very slow; it’s as if it interrogates the server on every command, yet it still needs &lt;code&gt;bw sync&lt;/code&gt; for the synchronization of the latest changes.&lt;/li&gt;
  &lt;li&gt;CLI utility does not have integration with the desktop app’s biometrics login, so you end up with a &lt;code&gt;BW_SESSION&lt;/code&gt; in your bash/zsh profile, making it insecure, or you have to introduce your master password every time, which is annoying.&lt;/li&gt;
  &lt;li&gt;Exports (for backups or migrations) don’t contain attachments, and you need separate exports for organizations — makes it unintuitive and hard to backup your data. And most of their documentation articles on exports don’t mention that organizations need separate exports.&lt;/li&gt;
  &lt;li&gt;On Android, the UI can become very slow, if the server is slow — at the time of writing, when using the &lt;code&gt;vault.bitwarden.eu&lt;/code&gt; server, the app was unusable for me due to how slow it was, with Android sometimes complaining that the app should be killed, but it worked significantly better with my self-hosted Vaultwarden instance. So the app is very dependent on the server’s latency, and doesn’t have good cache management.&lt;/li&gt;
  &lt;li&gt;On Android, the UX for auto-completion is not ideal, with the accessibility draw-over being frequently in the way.&lt;/li&gt;
  &lt;li&gt;Bitwarden took VC capital as well, and while it’s Open-Source nature may protect the project’s future…&lt;/li&gt;
  &lt;li&gt;Their new Secrets Manager is, apparently, not fully open source and its UI couldn’t be used by &lt;a href=&quot;https://github.com/dani-garcia/vaultwarden/discussions/3368&quot;&gt;Vaultwarden&lt;/a&gt;. This at least points to the very real possibility that the company may pull a bait and switch in the future, like so many other companies that build their popularity via FOSS licensing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve tried self-hosting Vaultwarden, the clone, via my Docker-enabled server, and it was effortless to install, and the running process very efficient. I’m impressed, that’s how all FOSS projects meant for self-hosting should be. Furthermore, I want more stuff built with Rust + SQLite. The Fediverse should take notes 😉&lt;/p&gt;

&lt;p&gt;For me, Bitwarden’s Open-Source nature almost makes up for the above deficiencies. Almost, but not quite. I can see myself using Bitwarden, if I were solo, but I’m trying to get my family to use password managers, and right now the UX makes that difficult. I’ll try it again next year.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2024/08/20/1password-vs-bitwarden/?pk_campaign=rss&quot;&gt;1Password vs. Bitwarden&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 20 Aug 2024 06:41:41 +0000</pubDate>
  <dc:modified>Wed, 04 Sep 2024 06:58:20 +0000</dc:modified>
  <atom:modified>Wed, 04 Sep 2024 06:58:20 +0000</atom:modified>
  <link>https://alexn.org/blog/2024/08/20/1password-vs-bitwarden/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2024/08/20/1password-vs-bitwarden/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Products</category>
  <category>Self Hosting</category>
  <category>Open Source</category>
  </item>


<item>
  <title>Cryptographically Strong Random on the JVM</title>
  <description>When generating random numbers for certain use-cases, such as when generating keys / IDs, it’s recommended for the random function to be “cryptographically strong”. Otherwise, attackers could predict random values, enabling serious security vulnerabilities.</description>
  <content:encoded>&lt;p&gt;When generating random numbers for certain use-cases, such as when generating keys / IDs, it’s recommended for the random function to be “cryptographically strong”. Otherwise, attackers could predict random values, enabling serious security vulnerabilities.&lt;/p&gt;

&lt;p&gt;Instances created via Java’s &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Random.html&quot;&gt;Random&lt;/a&gt;, or &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api///java.base/java/util/concurrent/ThreadLocalRandom.html&quot;&gt;ThreadLocalRandom&lt;/a&gt;, or &lt;a href=&quot;https://www.scala-lang.org/api/current/scala/util/Random$.html&quot;&gt;Scala’s Random&lt;/a&gt; are not cryptographically strong. How such random functions usually work is that they use a “pseudo-random number generator” algorithm that starts with a seed initiated from the current timestamp. Therefore, if you can guess the timestamp and know the algorithm, you can predict the entire sequence of pseudo-random numbers.&lt;/p&gt;

&lt;p&gt;It’s probably good to avoid them by default, unless being insecure (and fast) is the requirement. Prefer the use of &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/SecureRandom.html&quot;&gt;SecureRandom&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.security.SecureRandom

final var secureRandom = new SecureRandom()
// ...
secureRandom.nextInt()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;SecureRandom&lt;/code&gt; supports several algorithms, &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/specs/security/standard-names.html#securerandom-number-generation-algorithms&quot;&gt;see list&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;new java.security.SecureRandom().getAlgorithm()
// Output: NativePRNG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The default on my machine is &lt;code&gt;NativePRNG&lt;/code&gt;. This should mean that &lt;code&gt;nextBytes&lt;/code&gt; uses &lt;code&gt;/dev/urandom&lt;/code&gt; (shouldn’t block), but &lt;code&gt;generateSeed()&lt;/code&gt; uses &lt;code&gt;/dev/random&lt;/code&gt;, so it can block. You can specify an algorithm explicitly:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;final var secureRandom = SecureRandom.getInstance(&quot;NativePRNGNonBlocking&quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Depending on the algorithm used, these calls can do I/O that can block the current thread in case the random stream has less entropy than requested (see &lt;a href=&quot;https://en.wikipedia.org/wiki//dev/random&quot;&gt;Wikipedia entry&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;What about multi-threading? &lt;code&gt;SecureRandom&lt;/code&gt; instances should be thread-safe; however, the implementation could do expensive synchronization, so I find it better to distribute the contention:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Java
import java.security.SecureRandom;

public class ThreadLocalSecureRandom {
  private static final int COUNT = 100;
  private static final SecureRandom[] INSTANCES = new SecureRandom[COUNT];

  static {
    for (int i = 0; i &lt; COUNT; i++) {
      INSTANCES[i] = new SecureRandom();
    }
  }

  public static SecureRandom current() {
    var threadId = Thread.currentThread().getId();
    var index = Math.floorMod(threadId, COUNT);
    return INSTANCES[index];
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/UUID.html#randomUUID()&quot;&gt;UUID.randomUUID&lt;/a&gt; is cryptographically strong, using &lt;code&gt;SecureRandom&lt;/code&gt; under the hood. This also means that it shares the issues of &lt;code&gt;SecureRandom&lt;/code&gt; — the small possibility that the thread underneath gets blocked when generating random UUIDs. This only happens under certain conditions, however, when we generate UUIDs, we generate a lot of them, in horizontally scaled nodes being started as Docker instances, so the likelihood of hitting this in production increases.&lt;/p&gt;

&lt;p&gt;In our Scala project, we have this helper that redirects the generation of new UUIDs to threads that can be blocked (by semantically marking the operation as “blocking”):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code
import cats.effect.IO
import java.util.UUID

object UUIDUtils {
  /**
    * `UUID.randomUUID` is a risky operation, as it can block the current thread.
    * This function redirects such calls to the thread-pool meant for blocking IO.
    */
  def generateRandomUUID: IO[UUID] =
    IO.blocking(UUID.randomUUID())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This can be easily done with Kotlin’s Coroutines as well:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// Kotlin code
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.UUID

suspend fun generateRandomUUID(): UUID = 
    withContext(Dispatchers.IO) {
        UUID.randomUUID()
    }
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2024/08/13/cryptographically-strong-random-jvm/?pk_campaign=rss&quot;&gt;Cryptographically Strong Random on the JVM&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 13 Aug 2024 08:17:53 +0000</pubDate>
  <dc:modified>Tue, 13 Aug 2024 13:12:44 +0000</dc:modified>
  <atom:modified>Tue, 13 Aug 2024 13:12:44 +0000</atom:modified>
  <link>https://alexn.org/blog/2024/08/13/cryptographically-strong-random-jvm/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2024/08/13/cryptographically-strong-random-jvm/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Java</category>
  <category>Scala</category>
  <category>Kotlin</category>
  <category>Programming</category>
  <category>Security</category>
  <category>Snippet</category>
  </item>


<item>
  <title>On Advertising and Tracking</title>
  <description>Ads are now, unfortunately, a vehicle for malware, scams, or services that are deceptive and barely legal. But, should we block ads?</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
Ads on 𝕏 (formerly Twitter) can be blocked. You can use &lt;a href=&quot;https://ublockorigin.com/&quot;&gt;uBO&lt;/a&gt;, &lt;a href=&quot;https://chromewebstore.google.com/detail/ublock-origin-lite/ddkjiahejlhfcafbddmgiahcphecmpfh&quot;&gt;uBO Lite&lt;/a&gt;, or &lt;a href=&quot;https://brave.com/&quot;&gt;Brave&lt;/a&gt;. And on Android, the web interface is a decent alternative to their app, and can be used as a PWA (I recommend Brave for Android, not Firefox). This, of course, is a cat and mouse game. For instance, Facebook has made it hard for ad-blockers to keep up, they probably have a team of engineers working on anti-ad-blocking tech; uBO still works, but I wonder for how long. For the most part, ad-blocking in the browser works well.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
My wish is to write more and to publish more on my blog, and less on social media. This may mean more noise for you, my dear reader. I try maintaining a useful set of tags, so for example, you may want only my articles on &lt;a href=&quot;https://alexn.org/blog/tag/programming/&quot;&gt;Programming&lt;/a&gt; or &lt;a href=&quot;https://alexn.org/blog/tag/scala/&quot;&gt;Scala&lt;/a&gt;. As a PRO-tip, many feed readers can filter feeds by tags; personally, I use &lt;a href=&quot;https://newsblur.com/&quot;&gt;Newsblur&lt;/a&gt;, which has excelent filtering.
&lt;/p&gt;

&lt;p&gt;Last night, I was watching “House of the Dragon” on MAX (former HBO MAX), and they’ve introduced ads in their “Basic” plan. I did not mind an ad for cleaning products, although a little obnoxious, but I did mind their ad for a sports betting app. “Recorder”, an online publication from Romania, has recently covered a vast international online fraud operating in Eastern Europe, gaining access to people’s bank accounts via social engineering, and stealing their money. The way they reach people is via Google and Facebook ads, linking to deep fakes of public figures. And I’ve seen those ads with my own eyes, in my own Facebook feed, I’ve reported them repeatedly, and Facebook rejected my reports.&lt;/p&gt;

&lt;p&gt;Ads are now, unfortunately, a vehicle for malware, scams, or services that are deceptive and barely legal, which is why many secretly wish for the entire business model to burn to the ground. Also, ads are very annoying. So the answer to this question should be settled already:&lt;/p&gt;

&lt;h2 id=&quot;should-we-block-ads&quot;&gt;Should we block ads?&lt;/h2&gt;

&lt;p&gt;Unfortunately, there are second-order effects to blocking ads…&lt;/p&gt;

&lt;p&gt;The free web was built on ads. Yes, there was a web before ads, but speaking as someone who has been on the Internet since the late 90s, it was a shitty web. You may not like it, but some online services are costly to host. A service like YouTube isn’t possible without a sustainable business model, and it’s really difficult to build YouTube alternatives because Google can only make it work at their huge scale. And peer-to-peer alternatives are a romantic notion that will just not happen. Therefore, a completely ads-free YouTube would be a service inaccessible to the poor. Even if your government started collecting taxes for keeping certain Internet services free, that could mean poorer countries may get blocked from those services. I remember being blocked from a BBC show because I’m not a UK citizen. And wanting the Internet accessibility to depend on whomever is in power is foolish.&lt;/p&gt;

&lt;p&gt;The fact of the matter is that, in many ways, advocating for an ads-free Internet is currently advocating against the notion that &lt;em&gt;information wants to be free&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Ad-blocking, just like piracy before it, hurts alternatives and helps incumbents. People used to pirate Microsoft Windows, or Adobe Photoshop, back in the day, even if alternatives such as Linux or Gimp were more than suitable for the average Joe’s needs. Companies can’t compete with free alternatives, unless they establish a monopoly. And that’s precisely what happened, current day monopolies having been greatly helped by piracy. It’s hard nowadays to be an indie game or software maker, which is why I can’t be so harsh against DRM-enabled distribution platforms. We helped the rise of DRM and of centralized distribution channels by pirating software.&lt;/p&gt;

&lt;p&gt;Just as with piracy, blocking ads is keeping users from trying ads-free alternatives. People are less likely to try Mastodon or Bluesky, if their 𝕏 feed isn’t filled with annoying ads, and the issue is that they are still contributing to that platform’s success by engaging or distributing content. “Voting with your wallet” no longer works, and then we start wishing for some government to step in and break monopolies that we helped create.&lt;/p&gt;

&lt;p&gt;Ad-blockers are contributing to the death of the open Web. You should have noticed that the web is less popular on mobile phones. Services push people to use native apps. For example, the Reddit app is being forced on users, despite the web interface being more than adequate.&lt;/p&gt;

&lt;p&gt;And the reason is simple — you can’t block ads in apps. If your Pi-hole-based solution works right now for some use-cases, it won’t work forever. Pi-hole can’t work for 1st party ads, and apps can use their own DNS-Over-HTTPS endpoints.&lt;/p&gt;

&lt;p&gt;The web works so well because the user agent is ours, acting on our behalf. We are in control, and the browser is the perfect sandbox. But with all that power comes great responsibility, and the trend that has been happening is companies driving users away from the web browser and into privacy-invasive apps. This is why browsers have tried addressing privacy-concerns in ways that don’t invalidate ads-driven business models, or that breaks the web, such as Chrome’s &lt;a href=&quot;https://privacysandbox.com/&quot;&gt;Privacy Sandbox&lt;/a&gt; initiative, or Firefox with its &lt;a href=&quot;https://github.com/mozilla/explainers/tree/main/ppa-experiment&quot;&gt;privacy-preserving attribution API&lt;/a&gt;. Such initiatives &lt;a href=&quot;https://www.reddit.com/r/firefox/comments/1e43w7v/a_word_about_private_attribution_in_firefox/&quot;&gt;have been met with hostility&lt;/a&gt; by the extremely online laptop class, without them suggesting any alternative, and with the discourse highlighting that for them the issue isn’t with privacy at all.&lt;/p&gt;

&lt;h2 id=&quot;good-and-bad-reasons-to-block-ads&quot;&gt;Good and bad reasons to block ads&lt;/h2&gt;

&lt;p&gt;Blocking ads is legitimate if you want to protect yourself or others from scams, malware, or privacy-invasive tracking. Personally, I think I can protect myself, although absolutely everyone can fall for scams, it’s just an issue of resources and the right timing. And I certainly would like to protect my son or my father from scams or malware. Yes, I block all the ads that I can block.&lt;/p&gt;

&lt;p&gt;Blocking ads is immoral if you just want access to free shit.&lt;/p&gt;

&lt;p&gt;YouTube has a quite reasonably priced Premium option. If you’re not paying for YouTube Premium, and you’re blocking their ads, you’re just an entitled freeloader that wants to get other people’s work for free. I’d say the same thing for 𝕏, except that I think their Premium+ tier isn’t reasonably priced — OTOH, if you’re not paying at least for “Basic”, then you’re a freeloader, and with 𝕏 this is more problematic, as you could contribute content to the Fediverse; and instead you’re just giving 𝕏 your attention, while rambling about how Elon Musk is driving it into the ground.&lt;/p&gt;

&lt;p&gt;Many people just want to receive the hard labor of others for free. If you’re one of those people ranting about “late-stage capitalism”, I’m sorry to tell you comrade, but even if the revolution comes, you’ll still have to work for a living. If you’re one of those people that hates the business model, wanting to drive it into the ground, then why not go for the subscription-based alternatives? Why not encourage sustainable business models that aren’t ads-based?&lt;/p&gt;

&lt;p&gt;Indie developers or corporations are just people that have to work for a living, and by depriving them of revenue, you’re either contributing to their unemployment, or to a world of locked-down devices. Stealing from a corporation is still stealing from people that have to make ends-meet. As much as I hate DRM, or the walled gardens created by Apple, Google, Amazon, Spotify et al., it shouldn’t be difficult to see why creators have preferred the walled gardens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt; — blocking ads is recommended, with the industry certainly needing a wake-up call given current practices, but don’t be a freeloader because you’re contributing to the death of the open web, and to the disappearance of small creators, while growing existing monopolies.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2024/08/12/on-advertising-and-tracking/?pk_campaign=rss&quot;&gt;On Advertising and Tracking&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 12 Aug 2024 08:46:00 +0000</pubDate>
  <dc:modified>Tue, 13 Aug 2024 07:20:52 +0000</dc:modified>
  <atom:modified>Tue, 13 Aug 2024 07:20:52 +0000</atom:modified>
  <link>https://alexn.org/blog/2024/08/12/on-advertising-and-tracking/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2024/08/12/on-advertising-and-tracking/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Opinion</category>
  <category>Web</category>
  </item>


<item>
  <title>Scala&#39;s Future</title>
  <description>As software developers, we invest a lot in our tools. Time, energy, and feelings. We recommend tools to others; we build on top; we belong to a community; we contribute; hence we&apos;re eventually becoming stakeholders. And there&apos;s no other tool more clamored or risky in our belt than the programming language. Well, gather around, kids, let me tell you two stories from my past with the software industry…</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2024/01/10/scala-future/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2024-scala-hexa.png?202603060940&quot; alt=&quot;&quot; width=&quot;3555&quot; height=&quot;2000&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;The Scala logo, in the shape of a hexagon, meant to fit the logos of certain well known libraries, as a hint 😜&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
As software developers, we invest a lot in our tools. Time, energy, and feelings. We recommend tools to others; we build on top; we belong to a community; we contribute; hence we&apos;re eventually becoming stakeholders. And there&apos;s no other tool more clamored or risky in our belt than the programming language. Well, gather around, kids, let me tell you two stories from my past with the software industry…
&lt;/p&gt;

&lt;h2 id=&quot;the-dot-com-bubble&quot;&gt;The Dot-Com Bubble&lt;/h2&gt;

&lt;p&gt;I joined the workforce in the aftermath of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dot-com_bubble&quot;&gt;dot-com boom and bust&lt;/a&gt;. It was quite a bad time to be a rookie in the software industry, especially in Romania, a country still recovering from the dissolution of the Soviet Union. My first salary was $150 per month. And I remember a depressing article on &lt;a href=&quot;https://en.wikipedia.org/wiki/Java.net&quot;&gt;java.net&lt;/a&gt;, advising Java developers that were left without a job to go back to school. The general feeling was that Java was dying, but as times proved, news of its death are always greatly exaggerated. And this was during the time I was learning Java, hoping to replace PHP, which I deeply disliked, but paid the bills. PHP is still one of the most popular programming languages on the web. We’ll never get rid of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Déjà vu:&lt;/strong&gt; We just experienced a bubble bursting. The year 2023 was no longer an employee’s market. Have you noticed all the high-profile layoffs? In 2023, more than 260,000 people lost their job in tech, from over 1100 companies, surpassing the layoffs of 2022. The numbers are shocking because the industry seemed to be invincible during the pandemic. And these were just the numbers visible to Western media; e.g., countries from Eastern Europe don’t have good stats, and markets like China’s are opaque. Certainly, things aren’t as bad as in 2001, with cause for optimism due to the AI hype, but the big layoffs and the downsizing are hard facts you can’t ignore.&lt;/p&gt;

&lt;p&gt;When you compare the activity on job websites that most people ignore, or the activity on Reddit, or on X/Twitter, or elsewhere, the activity for most programming languages seems to be declining. On StackOverflow too, and this one is interesting because activity for mainstream languages is also going down due to most interesting questions being answered. It may not be just the tech bubble bursting, but also the pandemic-induced fatigue, with many people being tired of spending time online.&lt;/p&gt;

&lt;p&gt;In the Scala community, we sometimes talk of Rust or Kotlin as being shiny lights, but the proxies used for assessing a language’s popularity show that both Rust and Kotlin &lt;a href=&quot;https://redmonk.com/sogrady/2023/05/16/language-rankings-1-23/&quot;&gt;have stalled growth&lt;/a&gt;. It’s funny how perception works. Don’t get me wrong, I think Rust has had and will continue to have good growth and has a great future, and that’s because it’s positioned to compete with C++, which otherwise has no real competition. Rust is not a competitor of garbage-collected languages, because it’s more difficult to use. For instance, it makes FP hard, actually, never mind the interactive development people are used to in dynamic languages. And also, your average code has a better chance of having good throughput in a managed language like Java. Which is counterintuitive for people romanticizing about native code and “zero-cost abstractions”, and you can see how the hype cycles get fueled by people’s hopes and dreams instead of hard facts, which are missing (computer science is still not a science).&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
This is my personal experience which you should take with a grain of salt. There’s &lt;a href=&quot;https://opensource.googleblog.com/2023/06/rust-fact-vs-fiction-5-insights-from-googles-rust-journey-2022.html&quot;&gt;an observational study&lt;/a&gt; that disagrees with the point on productivity, from Google, which you should &lt;a href=&quot;https://examine.com/guides/how-to-read-a-study/&quot;&gt;also take with a grain of salt&lt;/a&gt;. The field is so devoid of data, that results of surveys from beginners are interpretted as rigurous research, but at least Google tries to have some data, and we should encourage companies to do more of this.
&lt;/p&gt;

&lt;p&gt;All languages are having setbacks in this climate. Another example is TypeScript, which had some noteworthy libraries that decided to drop it from their codebase, like Svelte, Drizzle, or Turbo. Time may prove that there’s more going on, but if we don’t put any observations we make in context, we may miss the confounders, and it’s a shame, given Scala’s awesome trajectory thus far.&lt;/p&gt;

&lt;h2 id=&quot;pythons-plateau-of-productivity&quot;&gt;Python’s Plateau of Productivity&lt;/h2&gt;

&lt;p&gt;I’ve also been a Python and a Ruby developer, and I remember well the onslaught of Ruby on Python’s seemingly fragile market share. Python (and Java) fans were actually afraid of Ruby burgeoning on the scene, and they had good reasons, because the languages seemed to be used for the same kind of problems, and are similar, despite the somewhat different philosophies. Ruby was fresh, Ruby seemed better for DSLs, and it has had “Ruby on Rails” as the killer app, which is a great showcase of what Ruby can do. At that time, Python fans were patting themselves on the back, reminding one another of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Gartner_hype_cycle&quot;&gt;hype cycle&lt;/a&gt;, hoping for the promised “plateau of productivity”. I’m pretty sure that’s where Li Haoyi &lt;a href=&quot;https://www.lihaoyi.com/post/TheDeathofHypeWhatsNextforScala.html&quot;&gt;got the idea for his Scala article&lt;/a&gt; on the same topic, since he’s also a Python developer and fan. And yes, the “plateau of productivity” folks were right.&lt;/p&gt;

&lt;p&gt;Python also went through a really slow and painful migration to Python 3 (AKA Python 3000). Version 3 came with a bunch of &lt;a href=&quot;https://docs.python.org/3.0/whatsnew/3.0.html&quot;&gt;breaking changes&lt;/a&gt;, and because the language is dynamic and dependent on C extensions, it took forever for libraries to migrate. My sore spot was &lt;a href=&quot;https://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt;. As a side note, Django was also tightly coupled with the native MySQL client, which also made it hard to introduce async I/O via monkey patching, but that’s another story. Python’s reliance on native libraries is both a blessing and a curse. Consider that the last official Python 2.7.x release was in 2020, 12 year after the Python 3 release. And in 2023 it finally reached EOL on Ubuntu, while many organizations still use Python 2, unable to migrate.&lt;/p&gt;

&lt;p&gt;In the meantime, Python became the world’s most popular programming language. It had to do with market fitness, of course, being the language of choice for data science, due to projects such as Numpy, Scipy, Matplotlib, TensorFlow, Jupyter, others. And note that Python was not targeted at data science, it just happened organically. And data science is not the only domain Python is good at. For many years, Python has been one of the languages recommended for developing Linux applications, being distributed by default in most Linux distros, with GUI bindings being well-maintained. Python is also very decent for doing web development, with the aforementioned Django also being a killer app, despite its limitations.&lt;/p&gt;

&lt;p&gt;Python had a BDFL, and was definitely designed with taste; however its direction went where the community wanted it, by open consensus, not committee. People just used Python because it solved their needs, and it grew from there. Do you know what &lt;a href=&quot;https://www.python.org/&quot;&gt;Python.org&lt;/a&gt;’s selling point is? That’s a rhetorical question because you didn’t know before I asked, and nobody cares. Nobody picks Python because of the official marketing brochure.&lt;/p&gt;

&lt;p&gt;Also, when Python 3 was released, it was ignored. But in time, more and more new features were added to Python 3, making migration more enticing, such as &lt;a href=&quot;https://docs.python.org/3/library/typing.html&quot;&gt;optional type hints&lt;/a&gt;, or &lt;a href=&quot;https://docs.python.org/3/library/asyncio-task.html&quot;&gt;couroutines/tasks for async I/O&lt;/a&gt;, thus removing the need for previous hacks. When you introduce breaking changes, you need carrots to entice people to migrate despite the pain. Sorry, I don’t make the rules 😉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Déjà vu:&lt;/strong&gt; Doesn’t the above story sound similar with Scala 3 and the fears some of you have regarding it? Of course, Python isn’t Scala, and the past doesn’t necessarily repeat itself.&lt;/p&gt;

&lt;p&gt;However, here are some lessons we can learn from Python’s history:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Community-driven direction, simply by people doing their thing, is good; you don’t need a committee to decide what people build with the language, and complaining that multiple options exist, or complaining about certain libraries or techniques being more popular than others is silly.&lt;/li&gt;
  &lt;li&gt;Having multiple choices is not bad — Python may pride itself on being a “batteries included” language with an “only one way of doing things” philosophy, but those are just aspirations, as in practice it couldn’t be further from the truth, Python having had multiple well-maintained libraries for doing the same thing, and non-orthogonal language features that were added to cope with the fact that the language can’t have multi-line anonymous functions.&lt;/li&gt;
  &lt;li&gt;We want good build tools, but build tools don’t make or break a language; here we should look at Python’s &lt;code&gt;easy_install&lt;/code&gt;, &lt;code&gt;pip&lt;/code&gt;, &lt;code&gt;pyenv&lt;/code&gt;, &lt;code&gt;virtualenv&lt;/code&gt;, &lt;code&gt;pyenv-virtualenv&lt;/code&gt;, &lt;code&gt;scons&lt;/code&gt;, etc. or how they haven’t solved yet the problem of depending on native libraries, therefore they need Docker for reproducible builds and deployments; the irony here being that Python needs a standard library with “batteries included” because depending on libraries turns out to be challenging for rookies. Having tools is great, but having fun and ways to get things done is more important.&lt;/li&gt;
  &lt;li&gt;Languages that break compatibility need new features to entice the community into migrating. When the migration isn’t painless, the greatest competition comes from older versions of the language (i.e., Scala 2.13.x is already quite good, just as Python 2.17 was already quite good). And we need to be open to new developments, while giving constructive feedback; otherwise we sound like a bunch of old farts complaining about the changing times and the kids these days. The FUD around new features may end up discouraging some &lt;a href=&quot;https://github.com/scala-native/scala-native/pull/3286&quot;&gt;really cool developments&lt;/a&gt; that may even help the status quo.&lt;/li&gt;
  &lt;li&gt;Migrations, given breaking changes, can take a really long time, but established languages with active projects can afford to wait. What are companies going to do? Throw everything in the bin? That would be silly, and for this reason, incumbents rarely wither away, with very few notable exceptions. Instead, well maintained programming languages age like fine wine, only growing in popularity.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To keep in mind, at least until AGI takes over 🤖&lt;/p&gt;

&lt;h2 id=&quot;hows-scala-doing&quot;&gt;How’s Scala doing?&lt;/h2&gt;

&lt;p&gt;YMMV, but here are my impressions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Scala 3 is objectively a better language, with much stronger compatibility guarantees.&lt;/li&gt;
  &lt;li&gt;Tooling can always improve, but it has some great tooling already that other languages can only dream of (Scala CLI, Metals, IntelliJ IDEA, Scalafmt, Scala.js, etc.).&lt;/li&gt;
  &lt;li&gt;It has several ecosystems of libraries that are mostly community-driven (Typelevel, com-lihaoyi, ZIO, etc.), distributing the risks; I mean, holy cow, the community may seem small, but it’s still super productive, and this isn’t a top-down cathedral (e.g., dotNET), it’s a bazaar.&lt;/li&gt;
  &lt;li&gt;Corporate support can be better, but we should also be thankful for Lightbend’s contributions, for VirtusLab stepping up, and other languages with their communities would be lucky to have Scala Center. If this is what an academic language looks like, I think I want more academic languages.&lt;/li&gt;
  &lt;li&gt;Scala is a mainstream language and was used in many projects that aren’t going away.&lt;/li&gt;
  &lt;li&gt;Scala is the most popular FP language, and it has some of the best resources for practicing and learning FP. It’s also one of the most Python-like languages I’ve used. There’s no doubt in my mind that it will continue to be in demand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s not all roses; tools could be improved, libraries could be more stable, jobs may be harder to find these days, but Scala developers are among the best paid on average, and the projects I see are quite exciting. I tried to jump ship just before the pandemic, to startups doing JavaScript, TypeScript, and Python. It was awful, and maybe I was just unlucky, but Scala jobs still have this je ne sais quoi that keeps me hooked. Perhaps it’s because we aren’t doing dumb web UIs to a database all the time, which also explains the attraction of some towards Rust 🤷‍♂️&lt;/p&gt;

&lt;p&gt;How do I feel about Scala? I feel quite good. You see, I get bored easily, and I have a track record of jumping from tech stack to tech stack, just because. On the job, I’ve used PHP, Java, C#, C++, Perl, Python, Ruby, JavaScript, TypeScript, and I’ve also learned and played in my free time with many others, including the darlings du jour. With Scala, I did not have time to be bored, either because of involvement in FOSS, or because of the awesome projects I was hired to work on. It’s a language that has grown with me, and the ecosystem always provides something new to learn, or some new library to get excited about, while matching my aspirations. And I’m not alone. If you take a look at the history of old-timers in the Scala community, you’ll notice a clear progression in their coding style, as it’s a language and ecosystem that grows with you. I always find it amazing how the same guy that worked on &lt;a href=&quot;https://scalatra.org/&quot;&gt;Scalatra&lt;/a&gt;, later worked on &lt;a href=&quot;https://http4s.org/&quot;&gt;Http4s&lt;/a&gt;, and that’s the kind of evolution you seldom see elsewhere. I’m confident Scala 3 will give us new opportunities to learn, grow and build.&lt;/p&gt;

&lt;p&gt;The “scalable” language, indeed 😍&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2024/01/10/scala-future/?pk_campaign=rss&quot;&gt;Scala&apos;s Future&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 10 Jan 2024 17:37:53 +0000</pubDate>
  <dc:modified>Thu, 11 Jan 2024 11:49:21 +0000</dc:modified>
  <atom:modified>Thu, 11 Jan 2024 11:49:21 +0000</atom:modified>
  <link>https://alexn.org/blog/2024/01/10/scala-future/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2024/01/10/scala-future/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  <category>Scala 3</category>
  <category>Programming</category>
  <category>Opinion</category>
  </item>


<item>
  <title>Update NextDNS with a Scala CLI script</title>
  <description>Today I was reminded how awesome Scala is for scripting, via Scala CLI. And it goes beyond having “batteries included”.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
    Today I was reminded how awesome &lt;a href=&quot;https://www.scala-lang.org/&quot;&gt;Scala&lt;/a&gt; is for scripting, via &lt;a href=&quot;https://scala-cli.virtuslab.org/&quot;&gt;Scala CLI&lt;/a&gt;. And it goes beyond having “batteries included”.
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; I have a &lt;a href=&quot;https://nextdns.io&quot;&gt;NextDNS account&lt;/a&gt;, as my DNS provider, for privacy and for blocking ads. My work computer has VPN software on it, that overrides the Wi-Fi’s DNS servers in order to access internal company resources. But I still want to configure NextDNS in my browser, and the problem is that my Chromium browser doesn’t fall back to the system DNS when I configure DNS-over-HTTPS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; a Scala script that updates the NextDNS configuration with overrides for the internal resources that I care about, as &lt;a href=&quot;https://nextdns.github.io/api/&quot;&gt;NextDNS has an HTTP API&lt;/a&gt; that I can use.&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
The following script uses &lt;a href=&quot;https://docs.scala-lang.org/scala3/book/introduction.html&quot;&gt;Scala 3&lt;/a&gt;, with &lt;a href=&quot;https://alexn.org/blog/2023/11/08/in-scala-3-use-4-spaces-for-indentation/&quot;&gt;4-spaces&lt;/a&gt; for &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/other-new-features/indentation.html&quot;&gt;significant indentation&lt;/a&gt;. It’s executable, and running it requires just having &lt;a href=&quot;https://scala-cli.virtuslab.org/install&quot;&gt;Scala CLI installed&lt;/a&gt;.
&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;#!/usr/bin/env -S scala-cli shebang

//&gt; using scala &quot;3.3.1&quot;
//&gt; using toolkit latest
//&gt; using lib &quot;com.monovore::decline:2.4.1&quot;

import cats.syntax.all.given
import com.monovore.decline.*
import sttp.client4.quick.*
import upickle.default.*
import java.net.InetAddress

val domainsToCleanUp = List(
    &quot;corporate.net&quot;
)

val toUpdate = List(
    &quot;confluence.corporate.net&quot;,
    &quot;kibana.corporate.net&quot;,
    &quot;elk.corporate.net&quot;,
    &quot;elk.uat.corporate.net&quot;,
    //...
)

def run(apiKey: String, profileId: String, dryRun: Boolean) =
    case class GetResponse(data: List[Map[String, String]])
        derives ReadWriter

    lazy val getProfile =
        val resp = quickRequest
            .get(uri&quot;https://api.nextdns.io/profiles/$profileId/rewrites&quot;)
            .header(&quot;X-Api-Key&quot;, apiKey)
            .send()
        upickle.default.read[GetResponse](resp.body.toString)

    def post(name: String, content: String) =
        println(s&quot;Adding $name (ip: $content)&quot;)
        if (!dryRun) then quickRequest
            .post(uri&quot;https://api.nextdns.io/profiles/$profileId/rewrites&quot;)
            .header(&quot;X-Api-Key&quot;, apiKey)
            .header(&quot;Content-Type&quot;, &quot;application/json&quot;)
            .body(upickle.default.write(
                Map(
                    &quot;name&quot; -&gt; name,
                    &quot;content&quot; -&gt; content
                )
            ))
            .send()

    def patch(id: String, name: String, content: String) =
        println(s&quot;Updating $name (ip: $content)&quot;)
        if dryRun then quickRequest
            .patch(uri&quot;https://api.nextdns.io/profiles/$profileId/rewrites/$id&quot;)
            .header(&quot;X-Api-Key&quot;, apiKey)
            .header(&quot;Content-Type&quot;, &quot;application/json&quot;)
            .body(upickle.default.write(
                Map(
                    &quot;content&quot; -&gt; content
                )
            ))
            .send()

    def delete(id: String, name: String) =
        println(s&quot;Deleting $name&quot;)
        if !dryRun then quickRequest
            .delete(uri&quot;https://api.nextdns.io/profiles/$profileId/rewrites/$id&quot;)
            .header(&quot;X-Api-Key&quot;, apiKey)
            .send()

    def skip(name: String, content: String) =
        println(s&quot;Skipping $name (ip: $content)&quot;)

    for name &lt;- toUpdate do
        val address = InetAddress.getByName(name)
        val ip = address.getHostAddress.nn

        getProfile.data.find: entry =&gt;
            entry.get(&quot;name&quot;).contains(name)
        match
        case None =&gt;
            post(name, ip)
        case Some(entry) if !entry.get(&quot;content&quot;).contains(ip) =&gt;
            patch(entry(&quot;id&quot;), name, ip)
        case Some(_) =&gt;
            skip(name, ip)

    for domain &lt;- domainsToCleanUp do
        val toDelete = getProfile.data.filter: entry =&gt;
            entry.getOrElse(&quot;name&quot;, &quot;&quot;).endsWith(domain) &amp;&amp;
            !toUpdate.contains(entry(&quot;name&quot;))
        for entry &lt;- toDelete do
            delete(entry(&quot;id&quot;), entry(&quot;name&quot;))

object Main extends CommandApp(
    name = &quot;nextdns-vpn-update&quot;,
    header = &quot;Update NextDNS&apos;s rewrites based on the current DNS (corporate VPN)&quot;,
    main =
        val apiKey = Opts
            .option[String](&quot;api-key&quot;, help = &quot;NextDNS API key&quot;)
            .orElse(Opts.env[String](&quot;NEXTDNS_API_KEY&quot;, help = &quot;NextDNS API key&quot;))
        val profileId = Opts
            .option[String](&quot;profile-id&quot;, help = &quot;NextDNS profile ID&quot;)
            .orElse(Opts.env[String](&quot;NEXTDNS_PROFILE_ID&quot;, help = &quot;NextDNS profile ID&quot;))
        val dryRun = Opts
            .flag(&quot;dry-run&quot;, help = &quot;Dry run&quot;).orFalse

        (apiKey, profileId, dryRun).mapN(run)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of note, the requirements for such a script:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Doing HTTP requests;&lt;/li&gt;
  &lt;li&gt;Composing and parsing JSON documents;&lt;/li&gt;
  &lt;li&gt;Parsing command-line arguments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My script depends on &lt;a href=&quot;https://docs.scala-lang.org/toolkit/introduction.html&quot;&gt;Scala Toolkit&lt;/a&gt;, which is a set of libraries that can take care of doing HTTP requests (via &lt;a href=&quot;https://sttp.softwaremill.com/en/stable/&quot;&gt;sttp&lt;/a&gt;) and parsing JSON (via &lt;a href=&quot;https://github.com/com-lihaoyi/upickle&quot;&gt;upickle&lt;/a&gt;). The script also depends on &lt;a href=&quot;https://github.com/bkirwi/decline&quot;&gt;decline&lt;/a&gt;, my favorite library for parsing command line arguments. I don’t need to install these separately, as Scala CLI takes care of managing these dependencies (unlike some of the popular scripting languages).&lt;/p&gt;

&lt;p&gt;The script can be executed directly, if you have &lt;a href=&quot;https://scala-cli.virtuslab.org/install&quot;&gt;Scala CLI installed&lt;/a&gt;, as it includes a &lt;a href=&quot;https://en.wikipedia.org/wiki/Shebang_(Unix)&quot;&gt;shebang&lt;/a&gt;. Just paste the above in a file on your PATH, like &lt;code&gt;~/bin/nextdns-vpn-update.scala&lt;/code&gt;. Then make it executable:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;chmod +x ~/bin/nextdns-vpn-update.scala
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And &lt;a href=&quot;https://scalameta.org/metals/&quot;&gt;Scala’s Metals&lt;/a&gt;, which I use with VS Code, is just wonderful for such scripts, with auto-completion, GH Copilot and everything. It took me at most 15 minutes to write and test this.&lt;/p&gt;

&lt;p&gt;Python and Ruby are definitely dethroned for all my future scripting needs.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2024/01/10/update-nextdns-with-a-scala-cli-script/?pk_campaign=rss&quot;&gt;Update NextDNS with a Scala CLI script&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 10 Jan 2024 11:14:14 +0000</pubDate>
  <dc:modified>Wed, 10 Jan 2024 16:04:09 +0000</dc:modified>
  <atom:modified>Wed, 10 Jan 2024 16:04:09 +0000</atom:modified>
  <link>https://alexn.org/blog/2024/01/10/update-nextdns-with-a-scala-cli-script/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2024/01/10/update-nextdns-with-a-scala-cli-script/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>CLI</category>
  <category>Scala</category>
  <category>Shell</category>
  <category>Snippet</category>
  </item>


<item>
  <title>New Year Resolutions</title>
  <description>A new year is upon us, and it’s customary to make resolutions. The problem with new year resolutions is that we tend to forget them in about a week. So, how to make resolutions that stick?</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2024/01/01/new-year-resolutions/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2024-new-year.png?202603060940&quot; alt=&quot;&quot; width=&quot;2304&quot; height=&quot;1440&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
A new year is upon us, and it&apos;s customary to make resolutions. The problem with new year resolutions is that we tend to forget them in about a week. So, how to make resolutions that stick?
&lt;/p&gt;

&lt;p&gt;For example, I’d like to lose weight and be stronger. You may not have the same goals, but you probably have similar ones, and the same thought process applies.&lt;/p&gt;

&lt;p&gt;In summary:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Focus on habits, not goals, consistency is key;&lt;/li&gt;
  &lt;li&gt;Pick easy to achieve daily habits;&lt;/li&gt;
  &lt;li&gt;Use “habit stacking”;&lt;/li&gt;
  &lt;li&gt;Have clarity about what you’re doing by measurement;&lt;/li&gt;
  &lt;li&gt;Control your environment;&lt;/li&gt;
  &lt;li&gt;Look for the root cause of bad habits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;focus-on-habits&quot;&gt;Focus on habits&lt;/h2&gt;

&lt;p&gt;While goals are useful for thinking about a destination, for one, they are too abstract and not actionable. “Losing weight” is too abstract, because you end up focusing on a measurement given by the scale, however, that number is just a proxy for things you want. I gained more than 20 Kg (44 pounds) since the pandemic, and I personally want to lose weight because my belly fat is making it uncomfortable for me to tie my shoes, I also snore loudly since gaining weight, and I fear sleep apnea, my allergic asthma has gotten worse, I’m uncomfortable when doing activities that I liked, such as riding my bike, and finding clothes that fit has gotten harder. And all of these side effects are having a negative impact on interactions with my family and friends.&lt;/p&gt;

&lt;p&gt;Note that I went through multiple episodes of losing weight and gaining it back, because my genetics work against me, as I have an increased appetite. I’m also not a professional. Therefore, take this advice with a grain of salt.&lt;/p&gt;

&lt;p&gt;One of the reasons for why diets fail is because the measurement of success is the weight itself, as seen on the scale, and not the habits that lead to losing weight and then maintaining it via a healthy lifestyle. If you set a goal like, “by this date I want to be 70 Kg (154 pounds)”, you’re setting yourself up for failure. Crash diets are terrible because they don’t lead to healthy habits, quite the contrary, the implementation resembles an eating disorder, and you can’t wait to get it over with and return to your old habits. And then you regain all the weight, the infamous yo-yo effect.&lt;/p&gt;

&lt;p&gt;Focusing on habits is harder, because you need some knowledge, however, people underestimate the impact of small periodic investments that pay dividends. You don’t need to change much about your daily routine, and having smaller daily goals makes it easier to achieve them consistently. Consistency is key.&lt;/p&gt;

&lt;h2 id=&quot;make-habits-easy&quot;&gt;Make habits easy&lt;/h2&gt;

&lt;p&gt;I want to be more active. Setting a daily goal of 10,000 steps isn’t always achievable, and is also relying on technology, even if it’s the ideal, but setting a daily goal of going for at least one walk, or doing more house chores, is doable. When working from home, you could even walk around the room while on a call, which is how many managed to stay active during the pandemic. You can also look for opportunities to walk more. If you drive a car for your daily commute, then you may be able to park further from your destination.&lt;/p&gt;

&lt;p&gt;I want to be stronger, to grow my muscle mass. A cheap way to get started is calisthenics, i.e., using your own body weight for strength training. Push-ups are a great exercise. Committing to 20 push-ups per day may be too much, either due to lack of time or strength. The habit should be something so easily achievable that you’re left with no excuse for not doing it daily. You can commit to 2 push-ups per day. And if you lack the strength for push-ups, you can do wall push-ups. You can do more than 2 push-ups per day, but anything extra is a bonus. Your daily goal should be to do at least 2 push-ups per day, with no progression, until the end of time.&lt;/p&gt;

&lt;h2 id=&quot;stack-habits&quot;&gt;Stack habits&lt;/h2&gt;

&lt;p&gt;You can have a habit of doing a couple of push-ups whenever you pour a glass of water or a cup of coffee. Drinking more water is a good habit, that may need some effort on its own, but it’s a great excuse to get up from your desk regularly, which prevents back pain. Or you could do some push-ups after you brush your teeth, or after some other daily habits that you have.&lt;/p&gt;

&lt;p&gt;I’d also like to learn to swim better and have that as a weekly practice. I already have a habit of driving my son to his swimming lessons, which he practices 2 times per week, for an hour per session. During that time, I can also hit the nearby gym’s swimming pool. The expended effort doesn’t matter, I’ll be happy if I can get in 10 minutes of swimming, but do so consistently.&lt;/p&gt;

&lt;p&gt;The above are examples of &lt;em&gt;habit stacking&lt;/em&gt;. If you already have a habit, you can use that as the prompt for a new habit.&lt;/p&gt;

&lt;h2 id=&quot;measure&quot;&gt;Measure&lt;/h2&gt;

&lt;p&gt;As any professional worth their salt will tell you, regular exercise doesn’t really help with losing weight, although it helps in managing it. You still need to eat fewer calories than you expend, and regular exercise can increase your appetite. Our body has evolved to adapt to higher energy expenditure, either via appetite, or via slowing down our metabolism at rest (e.g., less fidgeting, less body heat), which is also why crash diets are terrible, because the experience is terrible and motivation is fleeting. Strength training may help, in time, by increasing your BMR, but that too isn’t enough. A good diet is about getting away with a modest daily caloric deficit, fooling the body into thinking that it got enough, making the whole experience bearable long term.&lt;/p&gt;

&lt;p&gt;There are multiple ways of achieving modest caloric deficits. One way is to restrict the food groups you eat. In the past, I tried the “ketogenic diet”, which works because you increase the protein, while decreasing palatability. It was a terrible experience for me. I no longer have the strength to do anything like it, even if I’d like to focus more on protein, and vegetables.&lt;/p&gt;

&lt;p&gt;We need &lt;em&gt;clarity&lt;/em&gt; about what we are doing on a daily basis, in order to break bad habits.&lt;/p&gt;

&lt;p&gt;For dieting, what I’m doing right now is to track my daily caloric intake. This may not be a long-term habit, or an easy one, however, I need to calibrate my intuition of what to prefer eating, while ensuring that I eat enough. People struggling with obesity tend to underestimate the calories they eat, and that eating impulse needs to be more rational, as &lt;em&gt;“eating when hungry, stopping when full”&lt;/em&gt; doesn’t work well for us. AFAIK, most people that are overweight are often puzzled by how they got there, attributing it to a “slow metabolism” instead of their own behavior, like eating highly-processed, highly-palatable food that’s high in calories and salt. Personally, I’m under no illusions. Also, whenever I go on a diet, my motivation being really high, I tend to eat too little, until real hunger kicks in, the brain going into panic mode, and then it’s game over, as my brain won’t be satisfied until it regains that weight. Contrary to common wisdom, tracking calories is best for bringing insight into my behavior and for ensuring that I eat enough, and less for restricting calories.&lt;/p&gt;

&lt;p&gt;Actual caloric restriction is easier with simpler rules like: eat 2 or 3 meals per day, at approximately the same time; only one plate of food per meal, plus salad; include plenty of protein and vegetables in each meal; if you’re going to snack, snack on fruits.&lt;/p&gt;

&lt;p&gt;Note that measurement is all fine and dandy, unless it’s stressful. For this reason, I don’t weigh myself. And it’s probably a bad idea to track calories if you’re recovering from an eating disorder. But if you can take the emotions out of measuring and analyzing data, then it can be a great tool for understanding your behavior and for spotting trends.&lt;/p&gt;

&lt;h2 id=&quot;control-your-environment&quot;&gt;Control your environment&lt;/h2&gt;

&lt;p&gt;For dieting, once you figure out that you snack too much, you can remove those snacks from your vicinity, replacing them with a bowl of fruits. If you feel hungry, and an apple isn’t appeasing, that’s a cue that you’re just bored, and not hungry.&lt;/p&gt;

&lt;p&gt;This isn’t to say that you should never eat those delicious snacks you like, but &lt;em&gt;we need to do the right thing easier, and the unhealthy thing harder&lt;/em&gt;. This goes for other bad habits, like browsing social media, which can be useful, but maybe you’re doing it too much, and you don’t really need to have social media available on your phone, as you’re not losing anything by delaying it until you’re in front of your computer.&lt;/p&gt;

&lt;h2 id=&quot;look-for-root-causes&quot;&gt;Look for root causes&lt;/h2&gt;

&lt;p&gt;Unhealthy snacking is a good opportunity to think about other problems we may have, emotional or otherwise. Maybe food is a coping mechanism for stress.&lt;/p&gt;

&lt;p&gt;If stress is the prompt for snacking, we’re in trouble. We need to find other ways of coping with stress, like meditation, decluttering our lives, changing our job, etc. The pandemic and war at our borders have been huge sources of stress for me, and I’m only now recovering from their emotional impact. A great way to cope with stress seems to be exercise, and in the future I hope to be the kind of person that picks exercise and meditation over food when stressed.&lt;/p&gt;

&lt;p&gt;Stress may be hard to avoid, but understanding that it’s the cause of your bad habits is great, because you can then look for ways of coping with it that doesn’t involve food, or doom-scrolling social media, bad habits that are a feedback loop leading to more stress.&lt;/p&gt;

&lt;h2 id=&quot;happy-new-year&quot;&gt;Happy New Year!&lt;/h2&gt;

&lt;p&gt;For this year, my wish for us is to achieve our resolutions. And we’ll start by making them achievable, by focusing on long-lasting behavior changes 💪&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2024/01/01/new-year-resolutions/?pk_campaign=rss&quot;&gt;New Year Resolutions&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 01 Jan 2024 09:21:44 +0000</pubDate>
  <dc:modified>Mon, 01 Jan 2024 09:21:44 +0000</dc:modified>
  <atom:modified>Mon, 01 Jan 2024 09:21:44 +0000</atom:modified>
  <link>https://alexn.org/blog/2024/01/01/new-year-resolutions/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2024/01/01/new-year-resolutions/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Personal</category>
  </item>


<item>
  <title>December Adventure update, thoughts on Rust</title>
  <description>This is an update to my december adventure, in which I took it upon myself to learn the Rust programming langauge.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2023/12/12/december-adventure-rust/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2023-december-adventure-2.png?202603060940&quot; alt=&quot;&quot; width=&quot;1638&quot; height=&quot;1024&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  This is an update to my &lt;a href=&quot;https://alexn.org/blog/2023/12/04/december-adventure/&quot;&gt;december adventure&lt;/a&gt;, in which I took it upon myself to learn the Rust programming langauge.
&lt;/p&gt;

&lt;p&gt;First, I’ve participated in the &lt;a href=&quot;https://adventofcode.com/&quot;&gt;Advent of Code&lt;/a&gt; for the first 10 days, solving problems in Scala, then translating them to Rust. Unfortunately, &lt;a href=&quot;https://adventofcode.com/2023/day/10&quot;&gt;day 10&lt;/a&gt; got too complicated. I solved part 2 via “ray casting,” an idea that I got early in my thinking, but detecting line intersections is easier said than done. What happened is that I had to detect patterns in the map’s corners, in order to do correct counting, and this happened by debugging on the large input file, which is very impractical. This isn’t unlike other days in which the full specs or corner cases are visible only in the large input file, with the problems being underspecified. Day 10 took 4 hours of my time, and because the problems are increasing in difficulty, I’m finding it harder and harder to find time for a Scala to Rust translation.&lt;/p&gt;

&lt;p&gt;My December Adventure, to learn Rust, is progressing well. I’ve made little progress on the books, but solving AoC issues turbocharged my learning for simple tasks related to data structures. Translating AoC solutions made me somewhat familiar with vectors, iterators, hash-maps, plus some useful small libraries, like &lt;a href=&quot;https://docs.rs/regex/latest/regex/&quot;&gt;regex&lt;/a&gt; or &lt;a href=&quot;https://docs.rs/itertools/latest/itertools/&quot;&gt;itertools&lt;/a&gt;. I also got a recommendation to use &lt;a href=&quot;https://github.com/rust-lang/rust-clippy&quot;&gt;rust-clippy&lt;/a&gt;, a linter for Rust that can make some very useful recommendations. I wish we had something like it for Scala, too.&lt;/p&gt;

&lt;h2 id=&quot;more-impressions-on-rust&quot;&gt;More impressions on Rust&lt;/h2&gt;

&lt;p&gt;Compared with Scala, Rust has been annoying to work with, the former being more productive for AoC’s problems. However, the point of reference for Rust aren’t garbage collected languages like Scala, but rather C/C++. From that point of view, Rust seems surprisingly productive. It’s not a managed language, and that’s what makes it interesting.&lt;/p&gt;

&lt;p&gt;Rust is not an FP language, either. One source of confusion is that Rust’s immutability is a (transitive) property of variables, not of data structures. You can mutate any data structure in Rust by taking ownership. E.g., strings can be mutated, even ones that were previously owned by immutable variables. This is very unlike (impure) FP languages like Scala, F#, OCaml, others, where &lt;code&gt;var&lt;/code&gt; or &lt;code&gt;let mutable&lt;/code&gt; doesn’t allow you to change the stored data structure. A string in these languages is immutable, regardless of what the variable holding it says. This is required for correctness, as mutability of strings would break the implementation of hash-maps &amp; others.&lt;/p&gt;

&lt;p&gt;Rust is a language built for mutability. The borrow checker makes mutation much safer, by disallowing read-only references to exist while the data structure is being mutated. For instance, you’re not allowed to mutate a string while it’s being used as a key in a hash-map. But that’s all there is to its supposed “immutability by default”, a way to control who has read and write access.&lt;/p&gt;

&lt;p&gt;Persistent/immutable collections, in Rust, don’t make much sense, for example. Sharing structure, to avoid cloning, is inefficient without a good garbage collector (as you basically have to work with reference counting), and it’s also not in the language’s character.&lt;/p&gt;

&lt;p&gt;I do wonder how productive Rust is for real projects. For now, I don’t have any good ideas of where to apply it. I still have much to learn for building simple web services, as that requires async stuff, plus I’d like some problems for which Rust is particularly good at. Maybe I’ll start with some basic CLI tools.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/12/12/december-adventure-rust/?pk_campaign=rss&quot;&gt;December Adventure update, thoughts on Rust&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 12 Dec 2023 10:00:00 +0000</pubDate>
  <dc:modified>Tue, 12 Dec 2023 13:53:13 +0000</dc:modified>
  <atom:modified>Tue, 12 Dec 2023 13:53:13 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/12/12/december-adventure-rust/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/12/12/december-adventure-rust/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Programming</category>
  <category>Languages</category>
  <category>Rust</category>
  <category>Scala</category>
  </item>


<item>
  <title>December Adventure: Learning Rust</title>
  <description>This December I’m off to a great personal adventure in programming. Everyone can have their own fun December Adventure. You pick something you want to do, or maybe learn, and you do a little of it everyday, as long as it involves some coding.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2023/12/04/december-adventure/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2023-december.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;2560&quot; height=&quot;1812&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Postcard by publisher Brück &amp; Sohn in Meißen.
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  This December I’m off to a great personal adventure in programming. Everyone can have their own fun &lt;a href=&quot;https://eli.li/december-adventure&quot;&gt;December Adventure&lt;/a&gt;. You pick something you want to do, or maybe learn, and you do a little of it everyday, as long as it involves some coding.
&lt;/p&gt;

&lt;p&gt;The idea is related to the &lt;a href=&quot;https://adventofcode.com/&quot;&gt;Advent of Code (AoC)&lt;/a&gt;, which can be a bit much for many. You can, instead, have your own adventure. &lt;a href=&quot;https://github.com/alexandru/advent-of-code&quot;&gt;I am participating in AoC&lt;/a&gt; this year, for now, as long as it is easy, mostly because it feels like good fun. And doing it as a group, with the &lt;a href=&quot;https://discord.gg/scala&quot;&gt;Scala community on Discord&lt;/a&gt;, helps. But my real goal for December is &lt;strong&gt;to learn Rust&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;why-rust&quot;&gt;Why Rust?&lt;/h2&gt;

&lt;p&gt;Rust is an interesting programming language. It will never replace Scala for me, because it’s not as productive, but the truth is, managed languages (with a heap managed by a garbage collector) will never replace C/C++, and that’s the niche Rust falls into:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Cross-language reusable libraries. C is king here, due to its stable ABI, e.g., libraries for cryptography, a field for which wheel reinvention is a terrible idea. C is also the secret to Python’s popularity, since many libraries have parts implemented with C under the hood (e.g., Numpy/Scipy).&lt;/li&gt;
  &lt;li&gt;Real-time systems; the JVM is great at throughput, but like all GC platforms, it can have unpredictable pauses that make it unsuitable for real-time systems (despite the awesome low-latency GC implementations, like ZGC); you probably don’t want a GC-managed language for operating the brakes on your car, and even soft-real-time systems, like high-frequency trading or game engines, may be better served by C/C++/Rust.&lt;/li&gt;
  &lt;li&gt;High-performance CLI utilities. We’ll probably not see projects like &lt;a href=&quot;https://github.com/BurntSushi/ripgrep&quot;&gt;ripgrep&lt;/a&gt; built on top of the JVM, due to the binary size and the startup time. I also bumped into &lt;a href=&quot;https://helix-editor.com/&quot;&gt;Helix&lt;/a&gt;, a really cool vim replacement. This may change, with GraalVM or Scala/Kotlin Native, but Rust is already used for some pretty kick-ass utilities, and it makes me want to also have some fun.&lt;/li&gt;
  &lt;li&gt;Projects like the Linux kernel, Firefox, or &lt;a href=&quot;https://github.com/servo&quot;&gt;Servo&lt;/a&gt;; these projects are lower-level, and will never accept contributions in your favorite JVM language (or .NET or Go or OCaml) for obvious reasons.&lt;/li&gt;
  &lt;li&gt;Rust is seemingly embeddable everywhere, because it has the advantage of a small runtime and easy integration with C. For example, it’s the first choice for WebAssembly, you can build &lt;a href=&quot;https://neon-bindings.com/&quot;&gt;Node.js plugins&lt;/a&gt; with it, the Godot game engine has &lt;a href=&quot;https://godot-rust.github.io/&quot;&gt;unofficial Rust bindings&lt;/a&gt;, and it may not shine for building GUIs, but it does have usable &lt;a href=&quot;https://gtk-rs.org/&quot;&gt;GTK&lt;/a&gt; and &lt;a href=&quot;https://github.com/ryanmcgrath/cacao&quot;&gt;Cocoa&lt;/a&gt; bindings (beta quality, but active), which is more than Java can say (in fairness, JavaFX is pretty cool, and Swing is still a workhorse, but it always leaves something to be desired).&lt;/li&gt;
  &lt;li&gt;Rust has a blog dedicated to &lt;a href=&quot;https://os.phil-opp.com/&quot;&gt;building an operating-system&lt;/a&gt;, as it’s that kind of language, and I don’t know what other use cases are cooler than that.&lt;/li&gt;
  &lt;li&gt;The community is seemingly very productive, with many fun projects, resembling that of Scala. For example, if a language doesn’t have its own community-driven game engines, even if immature, it’s not the kind of language that people use for fun. Fortunately, Rust passes (see &lt;a href=&quot;https://amethyst.rs/&quot;&gt;Amethyst&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This doesn’t mean that I’m giving up on Scala. I predict that it will remain my favorite programming language, by far, but I’ve always been a polyglot, and I prefer not being tied down by the tools that I’m using.&lt;/p&gt;

&lt;h2 id=&quot;dec-1-4&quot;&gt;Dec 1-4&lt;/h2&gt;

&lt;p&gt;On Friday, we had a national holiday, so we had a prolonged weekend. In addition to visiting relatives, or participating in the first days of AoC challenges, I managed to sit down and go through the &lt;a href=&quot;https://doc.rust-lang.org/stable/book/&quot;&gt;official Rust book&lt;/a&gt;. I’m now at Chapter 7, which gave me the confidence to solve Advent of Code exercises with it. What I’m doing is that I first use Scala, because I think well in it, then translate the code to Rust.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/alexandru/advent-of-code&quot;&gt;My AoC repository&lt;/a&gt; has both Scala and Rust samples, and it’s interesting, because you can compare how my Scala looks and feels, compared with Rust. As an initial impression, Rust is more verbose and awkward. I still don’t fully master its memory ownership system. And this language prefers (safe) mutation. Working with persistent data structures is not idiomatic or comfortable, you’re better off embracing mutation where needed. But for a language with manual memory management, it’s actually quite usable, high-level and safe.&lt;/p&gt;

&lt;p&gt;I’ve also started reading &lt;a href=&quot;https://rust-unofficial.github.io/too-many-lists/index.html&quot;&gt;“Learn Rust with Entirely Too Many Linked Lists”&lt;/a&gt;. I feel confident in saying that if I go through this book, I’ll grok Rust’s memory management. But, it gave me brain damage straight from the first chapter, so it doesn’t look like an easy book for beginners.&lt;/p&gt;

&lt;h2 id=&quot;on-blogging&quot;&gt;On Blogging&lt;/h2&gt;

&lt;p&gt;I want to write more on this blog, because I have thoughts, and social media is still bad. I want to publish at least once per week, preferably more. For example, I’m going to publish more articles about how my December adventure is going.&lt;/p&gt;

&lt;p&gt;This means that I may publish articles that may be shorter, or lower quality.&lt;/p&gt;

&lt;p&gt;Let the fun begin~&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/12/04/december-adventure/?pk_campaign=rss&quot;&gt;December Adventure: Learning Rust&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 04 Dec 2023 11:04:09 +0000</pubDate>
  <dc:modified>Mon, 04 Dec 2023 16:59:29 +0000</dc:modified>
  <atom:modified>Mon, 04 Dec 2023 16:59:29 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/12/04/december-adventure/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/12/04/december-adventure/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Blogging</category>
  <category>Books</category>
  <category>Languages</category>
  <category>Personal</category>
  <category>Programming</category>
  <category>Rust</category>
  <category>Scala</category>
  </item>


<item>
  <title>In Scala 3, use 4 Spaces for Indentation</title>
  <description>Scala’s coding style advised to use 2 spaces of indentation, but that was before Scala 3’s optional braces, which introduces significant indentation. It’s time for an upgrade of the coding style.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2023/11/08/in-scala-3-use-4-spaces-for-indentation/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2023-scala3-indentation-4-spaces.png?202603060940&quot; alt=&quot;&quot; width=&quot;1786&quot; height=&quot;1116&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Scala’s coding style advised to &lt;a href=&quot;https://docs.scala-lang.org/style/indentation.html&quot;&gt;use 2 spaces of indentation&lt;/a&gt;, but that was before Scala 3’s &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/other-new-features/indentation.html&quot;&gt;optional braces&lt;/a&gt;, which introduces significant indentation. It’s time for an upgrade of the coding style.
&lt;/p&gt;

&lt;h2 id=&quot;wisdom&quot;&gt;Wisdom&lt;/h2&gt;

&lt;p&gt;The Linux kernel uses &lt;a href=&quot;https://www.kernel.org/doc/html/v6.6/process/coding-style.html#indentation&quot;&gt;indentation with 8 characters&lt;/a&gt;, the reasoning being readability and keeping &lt;a href=&quot;https://en.wikipedia.org/wiki/Cyclomatic_complexity&quot;&gt;cyclomatic complexity&lt;/a&gt; low. And I quote:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Rationale: The whole idea behind indentation is to clearly define where a block of control starts and ends. Especially when you’ve been looking at your screen for 20 straight hours, you’ll find it a lot easier to see how the indentation works if you have large indentations.&lt;/p&gt;

  &lt;p&gt;Now, some people will claim that having 8-character indentations makes the code move too far to the right, and makes it hard to read on an 80-character terminal screen. The answer to that is that if you need more than 3 levels of indentation, you’re screwed anyway, and should fix your program.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Using 2-spaces of indentation, in Scala, wasn’t terrible despite the high cyclomatic complexity. This is because Scala is very expression-oriented, very type safe, and very functional. This means that the compiler can catch a lot of errors, and due to tools such as exhaustive pattern matching, tail-recursive or higher-order functions, we rarely miss branches. Using 2-spaces for indentation was already in a gray area, however. And with significant indentation, it definitely moved into the red zone.&lt;/p&gt;

&lt;p&gt;You may think this isn’t serious. I’m seeing indentation errors in blog articles, which weren’t there before. And I’ve made a couple of mistakes myself. Sometimes, the compiler &lt;a href=&quot;https://alexn.org/blog/2023/06/06/scala-3-significant-indentation-woes-sample/&quot;&gt;catches it&lt;/a&gt;, but that may not happen in case of effectful expressions with an irrelevant &lt;code&gt;Unit&lt;/code&gt; result. And for it to be human-readable, it has to be in your face, unambiguous, even after 10 hours of looking at your screen.&lt;/p&gt;

&lt;h2 id=&quot;faq&quot;&gt;FAQ&lt;/h2&gt;

&lt;h3 id=&quot;why-not-use-tabs&quot;&gt;Why not use tabs?&lt;/h3&gt;

&lt;p&gt;That battle is already lost:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A vast majority of style guides advise against tabs;&lt;/li&gt;
  &lt;li&gt;For some forsaken reason, people like vertical alignment in Scala, which won’t work with tabs (ASCII-art, goddamn);&lt;/li&gt;
  &lt;li&gt;People who use spaces &lt;a href=&quot;https://stackoverflow.blog/2017/06/15/developers-use-spaces-make-money-use-tabs/&quot;&gt;make more money&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;I’m not even sure if Scalafmt supports tabs, can’t find the setting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BONUS — using spaces will piss off the tabs-people:&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=oRva7UxGQDw&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/oRva7UxGQDw/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=oRva7UxGQDw&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Tabs versus Spaces
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id=&quot;what-are-similar-languages-doing&quot;&gt;What are similar languages doing?&lt;/h3&gt;

&lt;p&gt;Here is the style guide for other languages with &lt;a href=&quot;https://en.wikipedia.org/wiki/Off-side_rule&quot;&gt;the off-side rule&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Make: tabs (8 characters);&lt;/li&gt;
  &lt;li&gt;Python: 4 spaces;&lt;/li&gt;
  &lt;li&gt;F#: 4 spaces;&lt;/li&gt;
  &lt;li&gt;Elm: 4 spaces;&lt;/li&gt;
  &lt;li&gt;Haskell: 2–4 spaces;&lt;/li&gt;
  &lt;li&gt;YAML: 2 spaces;&lt;/li&gt;
  &lt;li&gt;CoffeeScript: 2 spaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This may be my selection bias, but based on these numbers, I could draw a graph with how much people like these languages 😜&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
  &lt;strong&gt;NOTE:&lt;/strong&gt; Python is different from Scala, as it has the &lt;em&gt;“only one way of doing things”&lt;/em&gt; philosophy, it’s statement oriented, and it doesn’t allow significant indentation in the middle of expressions. This is the reason for why Python never got multi-line lambdas. Python is conservative, and the average cyclomatic complexity is lower.
&lt;/p&gt;

&lt;h2 id=&quot;tooling--configuration&quot;&gt;Tooling &amp; Configuration&lt;/h2&gt;

&lt;p&gt;Add an &lt;a href=&quot;https://editorconfig.org&quot;&gt;EditorConfig&lt;/a&gt; file, in the root of your project, like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

[*.{scala,sbt,sc}]
indent_style = space
indent_size = 4
max_line_length = 100
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Configure the &lt;a href=&quot;https://scalameta.org/scalafmt/&quot;&gt;Scalafmt&lt;/a&gt; plugin, with the following settings in &lt;code&gt;.scalafmt.conf&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;runner.dialect = scala3

maxColumn = 100
indent.main = 4

# Recommended, to not penalize `match` statements
indent.matchSite = 0

newlines.source = keep
rewrite.scala3.convertToNewSyntax = true
rewrite.scala3.removeOptionalBraces = yes
rewrite.scala3.insertEndMarkerMinLines = 5
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For your IDE, you should also install extensions for doing syntax coloring for indentation level:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow&quot;&gt;Indent-rainbow for VS Code&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://plugins.jetbrains.com/plugin/13308-indent-rainbow&quot;&gt;Indent-rainbow for IntelliJ&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When significant indentation enters your life, add some rainbow coloring 🌈&lt;/p&gt;

&lt;h2 id=&quot;sample&quot;&gt;Sample&lt;/h2&gt;

&lt;p&gt;This is a sample from one of my personal/small projects, integrating directly with JDBC. Your mileage may vary, and going from 2-spaces to 4-spaces requires adjustments, but your eyes will thank you for it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.IO
import cats.effect.kernel.Resource
import com.zaxxer.hikari.HikariDataSource
import com.zaxxer.hikari.HikariConfig
import cats.effect.kernel.Resource.ExitCase
import java.sql.Connection
import java.sql.PreparedStatement

final case class Database(
    config: JdbcConnectionConfig,
    pool: HikariDataSource
):
    def connection: Resource[IO, Connection] =
        Resource.make:
            IO.blocking:
                pool.getConnection().nn
            .flatTap: c =&gt;
                IO(c.setAutoCommit(true))
        .apply: c =&gt;
            IO.blocking(c.close())

    def transaction: Resource[IO, Connection] =
        for
            conn &lt;- connection
            _ = conn.setAutoCommit(false)
            _ &lt;- Resource.makeCase(IO.unit):
                case ((), ExitCase.Succeeded) =&gt;
                    IO.blocking:
                        conn.commit()
                        conn.setAutoCommit(true)
                case ((), ExitCase.Canceled | ExitCase.Errored(_)) =&gt;
                    IO.blocking:
                        conn.rollback()
                        conn.setAutoCommit(true)
        yield conn

    def withConnection[A](block: Connection ?=&gt; IO[A]): IO[A] =
        connection.use(ref =&gt; block(using ref))

    def withTransaction[A](block: Connection ?=&gt; IO[A]): IO[A] =
        transaction.use(ref =&gt; block(using ref))

    def query[A](sql: String)(block: PreparedStatement =&gt; A)(using Connection): IO[A] =
        IO.blocking:
            summon[Connection].prepareStatement(sql).nn
        .bracket: stm =&gt;
            IO.interruptible:
                block(stm)
            .cancelable:
                IO.blocking(stm.cancel())
        .apply: stm =&gt;
            IO.blocking(stm.close())

end Database

object Database:
    def connect(config: JdbcConnectionConfig): Resource[IO, Database] =
        for
            pool &lt;- createPool(config)
        yield Database(config, pool)

    def createPool(config: JdbcConnectionConfig): Resource[IO, HikariDataSource] =
        Resource.apply(IO.blocking:
            val cfg = HikariConfig().tap: it =&gt;
                it.setDriverClassName(config.driver)
                it.setJdbcUrl(config.url)
                for
                    u &lt;- config.user
                    p &lt;- config.password
                do
                    it.setUsername(u)
                    it.setPassword(p)
                end for
                it.addDataSourceProperty(&quot;cachePrepStmts&quot;, &quot;true&quot;)
                it.addDataSourceProperty(&quot;prepStmtCacheSize&quot;, &quot;250&quot;)
                it.addDataSourceProperty(&quot;prepStmtCacheSqlLimit&quot;, &quot;2048&quot;)
                // Instructs HikariCP to not throw if the pool cannot be seeded
                // with an initial connection
                it.setInitializationFailTimeout(0)

            val res = HikariDataSource(cfg)
            val cancel = IO.blocking(res.close())
            (res, cancel)
        )
end Database
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Go forth and spread the word! 📢
This stuff matters 💪&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/11/08/in-scala-3-use-4-spaces-for-indentation/?pk_campaign=rss&quot;&gt;In Scala 3, use 4 Spaces for Indentation&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 08 Nov 2023 18:17:04 +0000</pubDate>
  <dc:modified>Sun, 19 Oct 2025 06:46:28 +0000</dc:modified>
  <atom:modified>Sun, 19 Oct 2025 06:46:28 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/11/08/in-scala-3-use-4-spaces-for-indentation/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/11/08/in-scala-3-use-4-spaces-for-indentation/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Programming</category>
  <category>Programming Rant</category>
  <category>Scala</category>
  <category>Scala 3</category>
  </item>


<item>
  <title>OOP classes vs Higher-order Functions (HOFs)</title>
  <description>What’s the difference?</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2023/09/25/oop-classes-vs-higher-order-functions-hofs/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2023-oop-hof.png?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;996&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  What&apos;s the difference between OOP classes and Higher-order Function (HOF)?
&lt;/p&gt;

&lt;p&gt;Here’s an abstract OOP class:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;abstract class MyComponent[I, O] {
  // Abstract methods
  def foo(input: I): I
  def bar(input: I): O

  // Inherited implementation
  final def apply(input: I): O = {
    // Implementation doesn&apos;t matter
    val i = foo(input)
    bar(i)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s an equivalent “final” OOP class:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;final class MyComponent[I, O](
  foo: I =&gt; I,
  bar: I =&gt; O
) {
  def apply(input: I): O = {
    // Same implementation as above
    val i = foo(input)
    bar(i)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And here’s an equivalent Higher-order Function (HOF):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def process[I, O](foo: I =&gt; I, bar: I =&gt; O)(input: I): O = {
  // Same implementation as above
  val i = foo(input)
  bar(i)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There is no difference between these 3 implementations, conceptually they are the same thing, exposing the same complexity. Maybe you heard that OOP inheritance is bad, but if you’re implementing a HOF, or a final class like the above, it’s the same thing.&lt;/p&gt;

&lt;p&gt;Well, OK, the &lt;code&gt;abstract class&lt;/code&gt; has some gotchas, and all of them are about breaking the &lt;a href=&quot;https://en.wikipedia.org/wiki/Liskov_substitution_principle&quot;&gt;Liskov Substitution Principle&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;gotcha-1-overriding-of-non-final-methods&quot;&gt;Gotcha 1: Overriding of non-final methods&lt;/h2&gt;

&lt;p&gt;Let’s say that our &lt;code&gt;process&lt;/code&gt; method is non-final. And we override it such that &lt;code&gt;foo&lt;/code&gt; is never called:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class Blah[I, O] extends MyComponent[I, O] {
  def foo(input: I): I = ???
  def bar(input: I): O = ???

  override def process(input: I): O =
    bar(i)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, this would break an implicit, possibly undocumented contract that clients may rely on. Imagine that this class generates pseudo-random numbers, and overriding &lt;code&gt;process&lt;/code&gt; would make the output non-random.&lt;/p&gt;

&lt;p&gt;This breaks the “Liskov substitution principle” because the derived class no longer behaves like the inherited class. This is why methods should be non-final with intention. So &lt;em&gt;make methods final by default&lt;/em&gt;. C++, C# and Kotlin actually &lt;a href=&quot;https://www.artima.com/articles/versioning-virtual-and-override&quot;&gt;got this right&lt;/a&gt;, as in these langauges you have to be explicit about which methods can be overriden (e.g., &lt;code&gt;virtual&lt;/code&gt; in C++/C#, &lt;code&gt;open&lt;/code&gt; in Kotlin).&lt;/p&gt;

&lt;h2 id=&quot;gotcha-2-discrimination-based-on-runtime-type-instanceof&quot;&gt;Gotcha 2: Discrimination based on runtime type (instanceOf)&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;instanceOf&lt;/code&gt; checks and OOP &lt;a href=&quot;https://en.wikipedia.org/wiki/Downcasting&quot;&gt;downcasting&lt;/a&gt; makes it possible to break encapsulation and discriminate, client-side, based on what “type of component” you have. &lt;code&gt;instanceOf&lt;/code&gt; on open OOP classes (non-sealed) is an antipattern that’s going to come back to haunt you. Imagine we have this real-world example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class ParsingException(message: String) extends Exception(message)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But we need to add information to caught exceptions, like an &lt;code&gt;operationName: String&lt;/code&gt;, so we define this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class ExceptionWithDetails(
  operationName: String,
  cause: Throwable,
) extends Exception(cause.getMessage, cause)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, what happens if another part of our code does something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def clasifyException(e: Throwable): ExceptionType =
  e match {
    case _: ParsingException =&gt; Input
    case _: TimeoutException =&gt; ServiceNotAvailable
    case _                   =&gt; Unknown
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case, wrapping &lt;code&gt;ParsingException&lt;/code&gt; in &lt;code&gt;ExceptionWithDetails&lt;/code&gt; would break the logic of &lt;code&gt;clasifyException&lt;/code&gt;. Using &lt;code&gt;instanceOf&lt;/code&gt; checks on &lt;code&gt;Throwable&lt;/code&gt; clearly means that you know something about the implementation. And this is an &lt;a href=&quot;https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)&quot;&gt;encapsulation&lt;/a&gt; violation. I’m not being entirely fair here, because Java’s Exceptions are meant to be used like this, and at least they have a standard &lt;code&gt;cause&lt;/code&gt; in their API that you can use for wrapping and unwrapping exceptions.&lt;/p&gt;

&lt;p&gt;Here’s another example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait ExecutionContext {
  def execute(r: Runnable): Unit
  def reportFailure(e: Throwable): Unit
}

final class SafeExecutionContext(ec: ExecutionContext) {
  def execute(r: Runnable): Unit =
    try ec.execute(r)
    catch { case e: Throwable =&gt; ec.reportFailure(e) }

  def reportFailure(e: Throwable): Unit =
    ec.reportFailure(e)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way of adding behavior by wrapping classes is actually a best practice (composition over inheritance!). But clearly, by wrapping any &lt;code&gt;ExecutionContext&lt;/code&gt; into a &lt;code&gt;SafeExecutionContext&lt;/code&gt;, access to the runtime type of the wrapped implementation becomes inaccessible, so any discrimination you make via &lt;code&gt;instanceOf&lt;/code&gt; is error-prone. The “composition over inheritance” principle makes &lt;code&gt;instanceOf&lt;/code&gt; checks error-prone.&lt;/p&gt;

&lt;p&gt;It would have been great if Scala had a linting option that banned &lt;code&gt;instanceOf&lt;/code&gt; checks (pattern matching included) on open types (with the possibility to override, of course).&lt;/p&gt;

&lt;h2 id=&quot;so-hofs-versus-oop-classes&quot;&gt;So, HOFs versus OOP classes?&lt;/h2&gt;

&lt;p&gt;I haven’t talked about side effects. Classes are great at encapsulating shared mutable state. But capturing mutable state in closures is trivial, so that’s not an argument.&lt;/p&gt;

&lt;p&gt;On what to choose … it doesn’t matter.&lt;/p&gt;

&lt;p&gt;The problem all of them have is one of complexity. Those functions, taken as parameters, need clearly defined contracts, otherwise the user can unknowingly break such implicit contract. Which is why in code-bases that do this, people basically copy-paste the original call-site. Defining a set of functions with a clearly defined contract can clearly be done … with better types, with a provided TCK, or via documentation. Having some algebraic reasoning in there would be great. But it’s not trivial.&lt;/p&gt;

&lt;p&gt;Passing functions as arguments, or implementing them while inheriting from an abstract class, is most often done for &lt;em&gt;implementation reuse&lt;/em&gt;. I prefer the reuse of well encapsulated components with APIs that make them usable in multiple scenarios, instead of the reuse of implementation details. Or in other words, if we are talking of OOP, I prefer the reuse of &lt;code&gt;final&lt;/code&gt; classes that don’t take functions as parameters. And when functions take functions as parameters, well, they need clearly defined laws. But granted, this isn’t an easy thing to do, as it’s like telling people to design good microservices.&lt;/p&gt;

&lt;p&gt;Of course, many times, you just gotta do what you gotta do. Implementation reuse is better than no reuse.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/09/25/oop-classes-vs-higher-order-functions-hofs/?pk_campaign=rss&quot;&gt;OOP classes vs Higher-order Functions (HOFs)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 25 Sep 2023 07:30:22 +0000</pubDate>
  <dc:modified>Mon, 25 Sep 2023 07:30:32 +0000</dc:modified>
  <atom:modified>Mon, 25 Sep 2023 07:30:32 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/09/25/oop-classes-vs-higher-order-functions-hofs/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/09/25/oop-classes-vs-higher-order-functions-hofs/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>OOP</category>
  <category>Scala</category>
  </item>


<item>
  <title>Post Once, Syndicate Everywhere (POSSE)</title>
  <description>I’m a geek, and a software developer. I want to be close to my peers, wherever they meet online. If this means reactivating former social media accounts, so be it. Therefore, I’m implementing POSSE, again 😕</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2023/09/21/post-once-syndicate-everywhere-pose/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/zuzi-1.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;1000&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;This is my cat, Zuzi. She&apos;s completely black with green eyes. A rescued girl. My sweetheart.
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I’m a geek, and a software developer. I want to be close to my peers, wherever they meet online. If this means reactivating former social media accounts, so be it. Therefore, I’m implementing POSSE, again 😕
&lt;/p&gt;

&lt;p&gt;In January, I made the decision to &lt;a href=&quot;https://alexn.org/blog/2023/01/15/delete-twitter/&quot;&gt;delete my Twitter account&lt;/a&gt;. Prior to this, I also &lt;a href=&quot;https://alexn.org/blog/2022/09/12/delete-facebook/&quot;&gt;deleted my Facebook account&lt;/a&gt;. I remained on &lt;a href=&quot;https://www.linkedin.com/in/alexelcu/&quot; target=&quot;_blank&quot;&gt;LinkedIn&lt;/a&gt; and on &lt;a href=&quot;https://mastodon.social/@alexelcu&quot; target=&quot;_blank&quot;&gt;Mastodon&lt;/a&gt;. Note that I still have a &lt;a href=&quot;https://x.com/alexelcu&quot; target=&quot;_blank&quot;&gt;Twitter/X account&lt;/a&gt;, but it’s been there only to prevent username squatting, and all my followers and posts are gone.&lt;/p&gt;

&lt;p&gt;Now, 9 months later, I have to reconsider. My Mastodon experience has been good, actually, except for the tiny little problem that many from the Scala community aren’t there, or from the Java or Kotlin community for that mater. And, for example, I really wanted to see &lt;a href=&quot;https://x.com/scaladays&quot;&gt;Scala Days&lt;/a&gt; news. I missed the conference, sadly, but I can still tune online. In fairness, engagement has been going down across the board, communities now being fragmented. The age of centralized social media is over, people going back to Internet silos. Which is probably good, but this means more effort to connect.&lt;/p&gt;

&lt;p&gt;I also dislike my Mastodon presence for some of the same reasons I disliked Twitter and Facebook, although at a much smaller scale: I still see triggering posts, making me worry about shit that doesn’t matter. It’s still a waste of time. It’s still dumb and angry. Maybe the real problem is me, and being “extremely online” isn’t good.&lt;/p&gt;

&lt;p&gt;What I really want to do is to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Work on interesting stuff;&lt;/li&gt;
  &lt;li&gt;Write on my blog about it (which is making me less stupid, not more);&lt;/li&gt;
  &lt;li&gt;Connect to people that I like, and that share my interests, regardless of their chosen platform;&lt;/li&gt;
  &lt;li&gt;Always link to my website for anything that I want to communicate into the void.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This strategy is called “&lt;a href=&quot;https://indieweb.org/POSSE&quot;&gt;POSSE: Publish on your Own Website, Syndicate Everywhere&lt;/a&gt;” (&lt;a href=&quot;https://web.archive.org/web/20230914181257/https://indieweb.org/POSSE&quot;&gt;archive&lt;/a&gt;). I hope it works this time, as it wouldn’t be the first time I try it. Unfortunately, I often have weak moral principles or the attention span and the strong will of a child 🤷‍♂️&lt;/p&gt;

&lt;p&gt;Cheers,&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/09/21/post-once-syndicate-everywhere-pose/?pk_campaign=rss&quot;&gt;Post Once, Syndicate Everywhere (POSSE)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 21 Sep 2023 09:42:45 +0000</pubDate>
  <dc:modified>Sat, 18 May 2024 07:19:29 +0000</dc:modified>
  <atom:modified>Sat, 18 May 2024 07:19:29 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/09/21/post-once-syndicate-everywhere-pose/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/09/21/post-once-syndicate-everywhere-pose/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Blogging</category>
  <category>Opinion</category>
  <category>Personal</category>
  <category>Web</category>
  </item>


<item>
  <title>Java Volatiles</title>
  <description>In Java and other JVM languages, “volatile” reads and writes are part of the concurrency toolbox. But adding volatile on variables can be a mistake. This is a poorly understood concept. Let’s gain a better understanding.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
In Java and other JVM languages, “volatile” reads and writes are part of the concurrency toolbox. But adding &lt;code&gt;volatile&lt;/code&gt; on variables can be a mistake. This is a poorly understood concept. Let’s gain a better understanding.
&lt;/p&gt;

&lt;h2 id=&quot;misconceptions&quot;&gt;Misconceptions&lt;/h2&gt;

&lt;p&gt;Some common ones:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;em&gt;Volatile variables ensure “visibility”&lt;/em&gt; — but the notion is misleading, because it’s not about visibility per se, as all updates to variables are eventually seen by all other threads, and marking a variable as &lt;code&gt;volatile&lt;/code&gt; doesn’t necessarily publish changes to that variable any sooner (although in fairness, x86 CPUs have stronger ordering guarantees than ARM CPUs in this regard, so there may be differences of behavior for normal variables, depending on what you’re doing);&lt;/li&gt;
  &lt;li&gt;
&lt;em&gt;Volatile variables are not for “synchronization”&lt;/em&gt; — which is false, as volatile reads and writes are a form of synchronization, even if the guarantees are weaker than when using locks or when using &lt;code&gt;compare-and-set&lt;/code&gt; (CAS).&lt;/li&gt;
  &lt;li&gt;
&lt;em&gt;Volatile variables prevent CPU caching&lt;/em&gt; — depending on the JVM, their use may or may not reduce caching, the problem being that CPU caching is complex, and also the JVM is free to optimize away volatile semantics, the guarantees of the &lt;em&gt;JMM&lt;/em&gt;&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; are higher-level than that, and if you’re thinking of CPU caching, you’re probably doing it wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a somewhat more advanced mental model, volatile variables introduce &lt;em&gt;memory barriers&lt;/em&gt;&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, however:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Memory barriers are only introduced when the JVM writes, and then reads from the same volatile variable (in a pair, just like you must synchronize on the same lock/monitor for synchronization to work);&lt;/li&gt;
  &lt;li&gt;The JVM is free to optimize away memory barriers, as long as the ordering guarantees are preserved; for example, that’s what the JVM’s &lt;em&gt;escape analysis&lt;/em&gt;&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; is for.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;guaranteed-ordering&quot;&gt;Guaranteed Ordering&lt;/h2&gt;

&lt;p&gt;What volatile reads and writes give us are happens-before relationships&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, AKA guaranteed &lt;em&gt;ordering&lt;/em&gt;. Say, for example, we have the following declaration:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;class State {
  public String value1 = null;
  public String value2 = null;
  public volatile boolean hasValues = false;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The producer could do this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;state.value1 = &quot;Hello&quot;;
state.value2 = &quot;World&quot;;
state.hasValues = true;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the point of view of the producer, &lt;code&gt;value1&lt;/code&gt; and &lt;code&gt;value2&lt;/code&gt; are always updated before &lt;code&gt;hasValues&lt;/code&gt;. The question is, what happens when we look at the evolution of these variables from another thread? If &lt;code&gt;hasValues&lt;/code&gt; wouldn’t be &lt;code&gt;volatile&lt;/code&gt;, we could see &lt;code&gt;value1&lt;/code&gt; or &lt;code&gt;value2&lt;/code&gt; as &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The consumer could do this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Waits until the volatile write is seen
while (!state.hasValues) {
  // spin
}
// We are now guaranteed that `value1` and `value2` are set:
System.out.println(
  &quot;Got values: &quot; + state.value1 + &quot; &quot; + state.value2
);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;q-why-does-this-work&quot;&gt;Q: Why does this work?&lt;/h3&gt;

&lt;p&gt;This works because the JVM guarantees that once the update to our volatile variable is seen on the consumer thread (&lt;code&gt;hasValues == true&lt;/code&gt;), then all previous updates are also seen. It’s a happens-before relationship, the updates to &lt;code&gt;value1&lt;/code&gt; and &lt;code&gt;value2&lt;/code&gt; being guaranteed to happen before &lt;code&gt;hasValue = true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At the hardware level, this means that a “memory barrier” could be introduced, which prevents the CPU from reordering instructions, but thinking of memory barriers in this case would be error-prone.&lt;/p&gt;

&lt;h3 id=&quot;q-could-we-see-those-values-updated-before-the-volatile-update&quot;&gt;Q: Could we see those values updated before the volatile update?&lt;/h3&gt;

&lt;p&gt;Of course. Worth noting that unless we wait for &lt;code&gt;hasValue&lt;/code&gt;, we get no guarantees on what we’ll see to all updates prior to it. We could see &lt;code&gt;value1&lt;/code&gt; and/or &lt;code&gt;value2&lt;/code&gt; as &lt;code&gt;null&lt;/code&gt;, randomly. This is why thinking about “&lt;em&gt;CPU caching&lt;/em&gt;” is entirely misleading.&lt;/p&gt;

&lt;h3 id=&quot;q-dont-we-need-to-mark-as-volatile-all-variables&quot;&gt;Q: Don’t we need to mark as &lt;code&gt;volatile&lt;/code&gt; all variables?&lt;/h3&gt;

&lt;p&gt;No, making &lt;code&gt;value1&lt;/code&gt; and &lt;code&gt;value2&lt;/code&gt; to be &lt;code&gt;volatile&lt;/code&gt; can be worse than useless, at it may lead to poorer performance, due to extra memory barriers (forced orderings). The JVM may try to understand what you’re trying to do, but it’s not that smart. And adding &lt;code&gt;volatile&lt;/code&gt; all over the place does not make your code thread-safe. Volatile variables only make your code thread-safe if you can reason about the ordering.&lt;/p&gt;

&lt;h2 id=&quot;synchronization-sample&quot;&gt;Synchronization sample&lt;/h2&gt;

&lt;p&gt;You may think that we can’t make code thread-safe just via volatile reads and writes, but you’d be wrong, as there are cases in which we can. Which can be very useful for performance or predictability (lock-free algorithms).&lt;/p&gt;

&lt;p&gt;The following is an inefficient (SPSC) queue, see the comments. If you can understand why this sample is correct, you understand volatile variables:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.Objects;

/**
 * This is a &quot;single-producer, single-consumer&quot; (SPSC) queue.
 * &lt;p&gt;
 * SPSC means that we can have a single producer (a thread using `push`),
 * working concurrently with a single consumer
 * (another thread using `pop`).
 * &lt;p&gt;
 * This queue is not thread-safe if we have multiple concurrent
 * producers, or multiple concurrent consumers.
 */
public class SPSCRiskyQueue&lt;A&gt; {
  /**
   * State machine with possible states:
   * wait-for-producer | wait-for-consumer
   *
   * The state is &quot;volatile&quot; because it is used to order updates.
   * Remove &quot;volatile&quot; and witness the test fail.
   */
  private volatile String state = &quot;wait-for-producer&quot;;
  private int pushedCount = 0;
  private A value = null;

  public void push(A value) throws InterruptedException {
    while (!Objects.equals(state, &quot;wait-for-producer&quot;)) {
      spin();
    }
    this.value = value;
    pushedCount++;
    state = &quot;wait-for-consumer&quot;;
  }

  public A pop() throws InterruptedException {
    while (!Objects.equals(state, &quot;wait-for-consumer&quot;)) {
      spin();
    }
    // System.out.println(&quot;Read elements: &quot; + pushedCount);
    final var value = this.value;
    state = &quot;wait-for-producer&quot;;
    return value;
  }

  public long getPushedCount() {
    return pushedCount;
  }

  private void spin() throws InterruptedException {
    // For some reason this piece of logic introduces more ordering,
    // which makes the test more non-deterministic (it takes longer to
    // see it fail).
    Thread.onSpinWait();
    if (Thread.interrupted())
      throw new InterruptedException();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Try removing the &lt;code&gt;volatile&lt;/code&gt; annotation from &lt;code&gt;hasValues&lt;/code&gt;, see how this test works:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.concurrent.CountDownLatch;

/**
 * Code for TESTING...
 */
class Main {
  public static void runTest() throws InterruptedException {
    final var queue = new SPSCRiskyQueue&lt;Integer&gt;();
    final var count = 10000;
    final var state = new long[] { 0L };

    final var prepareLatch = new CountDownLatch(2);
    final var concurrentStartLatch = new CountDownLatch(1);

    final var producer = new Thread(() -&gt; {
      try {
        prepareLatch.countDown();
        concurrentStartLatch.await();
        for (int i = 0; i &lt; count; i++) {
          queue.push(i);
        }
      } catch (InterruptedException ignored) {}
    });

    final var consumer = new Thread(() -&gt; {
      try {
        prepareLatch.countDown();
        concurrentStartLatch.await();
        for (int i = 0; i &lt; count; i++) {
          state[0] += queue.pop();
        }
      } catch (InterruptedException ignored) {}
    });

    producer.setDaemon(true);
    producer.start();
    consumer.setDaemon(true);
    consumer.start();
    // Ready, set, go!
    prepareLatch.await();
    concurrentStartLatch.countDown();

    producer.join(3000);
    consumer.join(3000);

    final var sum = state[0];
    final var pushed = queue.getPushedCount();
    System.out.println(&quot;Sum: &quot; + sum + &quot;; pushed: &quot; + pushed);
    if (sum != (count * (count - 1)) / 2 || pushed != count) {
      throw new IllegalStateException(&quot;Concurrency test failed&quot;);
    }
  }

  public static void main(String[] args) throws InterruptedException {
    for (int i = 0; i &lt; 10000; i++) {
      runTest();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;hr&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Java_memory_model&quot;&gt;Java Memory Model&lt;/a&gt; is the set of multi-platform guarantees that Java makes for multithreaded code. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_barrier&quot;&gt;Memory barriers&lt;/a&gt; are CPU instructions that can force the ordering of updates. The &lt;a href=&quot;https://gee.cs.oswego.edu/dl/jmm/cookbook.html&quot;&gt;JSR-133 Cookbook&lt;/a&gt; can be good for gaining an understanding, but take it with a grain of salt. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Escape_analysis&quot;&gt;Escape analysis&lt;/a&gt; is a method for determining the scope of objects, in order to enable subtle optimizations. If the lifetime of an object is limited to the current method or thread, then Java may avoid intrinsic synchronization, or heap allocations. Java’s capabilities have been more limited than what’s possible. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;Reasoning about concurrency can be in terms of &lt;a href=&quot;https://en.wikipedia.org/wiki/Happened-before&quot;&gt;happens-before relationships&lt;/a&gt;, i.e., the order in which events are observed. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/06/19/java-volatiles/?pk_campaign=rss&quot;&gt;Java Volatiles&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 19 Jun 2023 10:57:50 +0000</pubDate>
  <dc:modified>Tue, 20 Jun 2023 05:31:48 +0000</dc:modified>
  <atom:modified>Tue, 20 Jun 2023 05:31:48 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/06/19/java-volatiles/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/06/19/java-volatiles/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Programming</category>
  <category>Concurrency</category>
  <category>Java</category>
  <category>Scala</category>
  <category>JVM</category>
  </item>


<item>
  <title>Scala 3 Significant Indentation Woes: Sample</title>
  <description>Here’s a fairly straightforward Scala 3 sample, using significant indentation. Can you spot the compilation error?</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
Here&apos;s a fairly straightforward Scala 3 sample, using significant indentation. Can you spot the compilation error?
&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//&gt; using scala &quot;3.3.0&quot;

def sequence[A](list: List[Option[A]]): Option[List[A]] =
  list.foldLeft(Option(List.newBuilder[A])):
    (acc, a) =&gt;
      acc.flatMap: xs =&gt;
        a.map: x =&gt;
          xs.addOne(x)
    .map(_.result())
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s the compilation error:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;[error] ./sample.scala:9:10
[error] Found:    List[A]
[error] Required: scala.collection.mutable.Builder[A, List[A]]
[error]     .map(_.result())
[error]          ^^^^^^^^^^
Error compiling project (Scala 3.3.0, JVM)
Compilation failed
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s the corrected code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//&gt; using scala &quot;3.3.0&quot;

def sequence[A](list: List[Option[A]]): Option[List[A]] =
  list.foldLeft(Option(List.newBuilder[A])):
    (acc, a) =&gt;
      acc.flatMap: xs =&gt;
        a.map: x =&gt;
          xs.addOne(x)
  .map(_.result())
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;FYI, this cannot happen in Python, because Python does not allow breaking expressions on multiple lines like that:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class MyList:
  def __init__(self, list):
    self.list = list
  def map(self, f):
    return MyList([f(x) for x in self.list])

# Doesn&apos;t parse
MyList([1, 2, 3])
  .map(lambda x: x + 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The error is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;  File &quot;/tmp/sample.py&quot;, line 9
    .map(lambda x: x + 1)
IndentationError: unexpected indent
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Maybe no indentation?&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Doesn&apos;t parse
MyList([1, 2, 3])
.map(lambda x: x + 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;  File &quot;/tmp/sample.py&quot;, line 9
    .map(lambda x: x + 1)
    ^
SyntaxError: invalid syntax
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yikes! What Python does is to make expressions unambiguous by requiring the escaping of line endings via a backslash:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;MyList([1, 2, 3]) \
  .map(lambda x: x + 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Scala’s syntax keeps being compared with Python’s, however, they couldn’t be more different, as Python has had a very strict policy to avoid ambiguity, and even rejected multi-line lambdas for this reason.&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
I’m also begining to feel that 2 spaces for indentation are not enough 🙊
&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/06/06/scala-3-significant-indentation-woes-sample/?pk_campaign=rss&quot;&gt;Scala 3 Significant Indentation Woes: Sample&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 06 Jun 2023 11:48:10 +0000</pubDate>
  <dc:modified>Sun, 26 Oct 2025 10:08:59 +0000</dc:modified>
  <atom:modified>Sun, 26 Oct 2025 10:08:59 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/06/06/scala-3-significant-indentation-woes-sample/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/06/06/scala-3-significant-indentation-woes-sample/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Languages</category>
  <category>Programming</category>
  <category>Programming Rant</category>
  <category>Python</category>
  <category>Scala</category>
  <category>Scala 3</category>
  </item>


<item>
  <title>Scala 3 Enums</title>
  <description>In Scala, how do we model enumerations of values? What are the possible issues? How does Scala compare with Java? What are the changes in Scala 3?</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  In Scala, how do we model enumerations of values? What are the possible issues? How does Scala compare with Java? What are the changes in Scala 3?
&lt;/p&gt;

&lt;p&gt;Here’s a simple enumeration in Java:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Java code
enum Colors {
  Red, Green, Blue
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Adding keys as strings is also possible:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Java code
enum Colors {
  Red(&quot;RED&quot;), Green(&quot;GREEN&quot;), Blue(&quot;BLUE&quot;);

  private final String value;

  Colors(String value) {
    this.value = value;
  }

  public String getValue() {
    return value;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Java should also do exhaustiveness checks in its new &lt;code&gt;switch&lt;/code&gt; statement (&lt;a href=&quot;https://openjdk.org/jeps/354&quot;&gt;JEP 354&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;//JAVA 17+

Colors myColor = Colors.Green;
String label = switch (myColor) {
  case Red -&gt; Colors.Red.getValue();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which should fail to compile with the following error:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;error: the switch expression does not cover all possible input values
  String label = switch (myColor) {
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The equivalent in Scala 2.x was supposed to be the &lt;a href=&quot;https://www.scala-lang.org/api/2.13.10/scala/Enumeration.html&quot;&gt;Enumeration&lt;/a&gt; class:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala 2.x code
object Colors extends Enumeration {
  val Red, Green, Blue = Value
}

// Or you can assign custom keys to each value:
object Colors extends Enumeration {
  val Red = Value(&quot;RED&quot;)
  val Green = Value(&quot;GREEN&quot;)
  val Blue = Value(&quot;BLUE&quot;)
}

// The created type is `Colors.Value`
val myColor: Colors.Value = Colors.Green
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The generated type is &lt;code&gt;Colors.Value&lt;/code&gt;. This can create issues, because it’s an inner type of &lt;code&gt;Enumeration&lt;/code&gt; that’s being erased at runtime, therefore it’s not the equivalent of a Java &lt;code&gt;enum&lt;/code&gt; (think of doing serialization with Jackson):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;classOf[Colors.Value]
// val res: Class[Colors.Value] = class scala.Enumeration$Value

object Size extends Enumeration {
  val S, M, L, XL, XXL = Value
}

// Yikes!
classOf[Size.Value] == classOf[Colors.Value]
// =&gt; true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Importantly, &lt;code&gt;Enumeration&lt;/code&gt; provides &lt;code&gt;values&lt;/code&gt; and &lt;code&gt;withName&lt;/code&gt; as utilities:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;Colors.values // List(Red, Green, Blue)
Colors.withName(&quot;Red&quot;) // Colors.Value = Red
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another big problem with &lt;code&gt;Enumeration&lt;/code&gt; is that it’s incapable of doing exhaustiveness checks when pattern matching. Nowadays, this is less safety than what Java provides. The following code compiles without warnings:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;myColor match {
  case Colors.Red =&gt; println(&quot;Red&quot;)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The replacement that almost everyone used was “sealed” traits/classes, which can encode tagged union types:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala 2.x code

// The `extends Product with Serializable` boilerplate
// is needed to eliminate type-inference junk
sealed abstract class Color(val value: String)
  extends Product with Serializable

object Color {
  case object Red extends Color(&quot;RED&quot;)
  case object Green extends Color(&quot;GREEN&quot;)
  case object Blue extends Color(&quot;BLUE&quot;)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a bit more verbose, but we can do exhaustiveness checks:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val myColor: Color = Color.Green
myColor match {
  case Color.Red =&gt; println(&quot;Red&quot;)
}
// myColor match {
// ^
// On line 2: warning: match may not be exhaustive.
// It would fail on the following inputs: Blue, Green
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is super useful, especially with &lt;a href=&quot;https://alexn.org/blog/2020/05/26/scala-fatal-warnings/&quot;&gt;-Xfatal-warnings enabled&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One problem here is that we no longer have an enumeration of all available values, and this can make things difficult:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object Color {
  // ...

  // Error-prone, since we need to ensure that
  // we list them all:
  val values: Set[Color] = Set(
    Red,
    Green,
    Blue
  )

  def apply(value: String): Option[Color] =
    values.find(_.value == value)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are libraries that can help, such as &lt;a href=&quot;https://github.com/lloydmeta/enumeratum/&quot;&gt;Enumeratum&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;#!/usr/bin/env -S scala-cli shebang -q

//&gt; using scala &quot;2.13.10&quot;
//&gt; using lib &quot;com.beachape::enumeratum:1.7.2&quot;

import enumeratum._
import enumeratum.values._

sealed abstract class Color(val value: String)
  extends StringEnumEntry

object Color extends StringEnum[Color] {
  case object Red extends Color(&quot;RED&quot;)
  case object Green extends Color(&quot;GREEN&quot;)
  case object Blue extends Color(&quot;BLUE&quot;)

  val values: IndexedSeq[Color] = findValues
}

println(Color.values) // Vector(Red, Green, Blue)
println(Color.withValueOpt(&quot;Red&quot;)) // Some(Red)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Thankfully, Enumeratum is compatible with Scala 3. However, I found a flaw. The following code compiles without warnings:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import enumeratum.values._

sealed abstract class Color(val value: String)
  extends StringEnumEntry

object Color extends StringEnum[Color] {
  case object Red extends Color(&quot;RED&quot;)
  case object Green extends Color(&quot;GREEN&quot;)
  case object Blue extends Color(&quot;BLUE&quot;)

  // Yikes! This is most likely a bug.
  final case class Other(r: Int, g: Int, b: Int)
    extends Color(s&quot;OTHER($r,$g,$b)&quot;)

  val values: IndexedSeq[Color] = findValues
}

// No `Other` in this list:
println(Color.values) // Vector(Red, Green, Blue)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The problem is, of course, that it invalidates our assumptions about how to serialize and deserialize this. Let’s say we’ve been using Circe, and we already had the codecs defined:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//&gt; using lib &quot;io.circe::circe-core:0.14.5&quot;
//&gt; using lib &quot;io.circe::circe-parser:0.14.5&quot;

import io.circe._
import io.circe.parser._
import io.circe.syntax._

implicit val colorEncoder: Encoder[Color] =
  Encoder[String].contramap(_.value)

implicit val colorDecoder: Decoder[Color] =
  Decoder[String].emap(Color.withValueOpt(_).toRight(&quot;Invalid color&quot;))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When we add our &lt;code&gt;case class&lt;/code&gt;, this obviously doesn’t work:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;(Color.Other(1,2,3): Color).asJson() // &quot;OTHER(1,2,3)&quot;

decode[Color](&quot;\&quot;OTHER(1,2,3)\&quot;&quot;) // Left(DecodingFailure at : Invalid color)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;People don’t necessarily realize that an enumeration is powered by Enumeratum, or what the limitations are.&lt;/p&gt;

&lt;p&gt;To fix this, we could find another library, or we could write our own macro. But I dislike macros, I think we’d do just fine with a runtime error:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;#!/usr/bin/env -S scala-cli shebang -q

//&gt; using scala &quot;2.13.10&quot;
//&gt; using lib &quot;org.scala-lang:scala-reflect:2.13.10&quot;

import scala.reflect.runtime.{universe =&gt; ru}
import scala.reflect.runtime.{currentMirror =&gt; cm}

def findValues[T: ru.TypeTag]: Set[T] = {
  val tpe = ru.typeOf[T]
  val clazz = tpe.typeSymbol.asClass
  if (!clazz.isSealed) {
    throw new AssertionError(s&quot;Type $tpe is not sealed&quot;)
  }
  clazz.knownDirectSubclasses.map { sym =&gt;
    if (sym.isModule)
      cm.reflectModule(sym.asModule)
        .instance
        .asInstanceOf[T]
    else if (sym.isModuleClass)
      cm.reflectModule(sym.asClass.module.asModule)
        .instance
        .asInstanceOf[T]
    else
      throw new AssertionError(
        s&quot;Direct subtype of $tpe is not an object: $sym&quot;
      )
  }
}

sealed abstract class Color(val value: String)
  extends Product with Serializable

object Color {
  case object Red extends Color(&quot;RED&quot;)
  case object Green extends Color(&quot;GREEN&quot;)
  case object Blue extends Color(&quot;BLUE&quot;)

  val values = findValues[Color]

  def apply(value: String): Option[Color] =
    values.find(_.value == value)
}

println(Color.values) // Set(Red, Green, Blue)
println(Color(&quot;RED&quot;)) // Some(Red)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, if you try to add a new case class, you’ll get a runtime error when trying to access the &lt;code&gt;object Color&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object Color {
  // ...
  case class Other(r: Int, g: Int, b: Int)
    extends Color(s&quot;OTHER($r,$g,$b)&quot;)
}
// This will now throw a java.lang.AssertionError:
// &apos;Direct subtype of Color is not an object: class Other&apos;
Color.values
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;This is not a macro&lt;/strong&gt;. You can write a macro, if you want, using mostly the same logic. Like all things with Scala 2’s compile-time reflection, and macros, the &lt;code&gt;knownDirectSubclasses&lt;/code&gt; is buggy, and this code breaks in some instances, like when defining &lt;code&gt;Color&lt;/code&gt; as an inner class. Also, the macro may be error-prone in other ways. See this &lt;a href=&quot;https://stackoverflow.com/questions/13671734/iteration-over-a-sealed-trait-in-scala&quot;&gt;StackOverflow answer&lt;/a&gt; for a hint on how to do that.&lt;/p&gt;

&lt;p&gt;In Scala 3, we can easily define a macro:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;#!/usr/bin/env -S scala-cli shebang -q

//&gt; using scala &quot;3.2.2&quot;

inline def findValues[T](using
  m: scala.deriving.Mirror.SumOf[T]
): Set[T] =
  allInstances[m.MirroredElemTypes, m.MirroredType].toSet

inline def allInstances[ET &lt;: Tuple, T]: List[T] =
  import scala.compiletime.*

  inline erasedValue[ET] match
    case _: EmptyTuple =&gt; Nil
    case _: (t *: ts)  =&gt;
      summonInline[ValueOf[t]].value.asInstanceOf[T] :: allInstances[ts, T]

//-------------------------------------------------------------------------
//...
  
sealed abstract class Color(val value: String)
  extends Product with Serializable

object Color:
  case object Red extends Color(&quot;RED&quot;)
  case object Green extends Color(&quot;GREEN&quot;)
  case object Blue extends Color(&quot;BLUE&quot;)

  // Uncomment this to get a compile-time error:
  // case class Other(r: Int, g: Int, b: Int)
  //   extends Color(s&quot;OTHER($r,$g,$b)&quot;)

  val values = findValues[Color]

  def apply(value: String): Option[Color] =
    values.find(_.value == value)

println(Color.values) // Set(Red, Green, Blue)
println(Color(&quot;RED&quot;)) // Some(Red)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is an actual macro, and it will throw a compile-time error if &lt;code&gt;Color&lt;/code&gt; is not a sealed trait, or if we try to define a &lt;code&gt;case class Other&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Of course, in Scala 3, we already have the new &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/enums/enums.html&quot;&gt;enums&lt;/a&gt;, so the above code is only necessary if we want to port our Scala 2 code to Scala 3. In Scala 3, we can just write:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;enum Color(val value: String):
  case Red extends Color(&quot;RED&quot;)
  case Green extends Color(&quot;GREEN&quot;)
  case Blue extends Color(&quot;BLUE&quot;)

object Color:
  def apply(value: String): Option[Color] =
    values.find(_.value == value)

println(Color.values.toSet) // Set(Red, Green, Blue)
Color(&quot;RED&quot;) // Some(Red)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we try to add a case class to our enumeration, we can, but &lt;code&gt;values&lt;/code&gt; will no longer be available:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// BROKEN CODE
enum Color(val value: String):
  case Red extends Color(&quot;RED&quot;)
  case Green extends Color(&quot;GREEN&quot;)
  case Blue extends Color(&quot;BLUE&quot;)
  case Other(r: Int, g: Int, b: Int)
    extends Color(s&quot;OTHER($r,$g,$b)&quot;)

object Color:
  def apply(value: String): Option[Color] =
    values.find(_.value == value)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our Scala 3 compiler will then throw this error:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;-- [E006] Not Found Error: -----------------------------------------------------
11 |    values.find(_.value == value)
   |    ^^^^^^
   |    Not found: values
   |
   | longer explanation available when compiling with `-explain`
1 error found
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Furthermore, in Scala 3 we can easily define enums that are compatible with Java, by extending &lt;a href=&quot;https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Enum.html&quot;&gt;java.lang.Enum&lt;/a&gt;, making them compatible with Java libraries:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala 3

enum Color extends java.lang.Enum[Color]:
  case Red, Green, Blue
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;
&lt;strong&gt;TLDR:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;Scala 2&lt;/code&gt; involves a lot of error-prone boilerplate.&lt;br&gt;
&lt;code&gt;Scala 3&lt;/code&gt; is pretty cool in its handling of enums and macros ❤️
&lt;/p&gt;

&lt;p&gt;It doesn’t seem like much, but we have A LOT of enumerations in our codebase. The new &lt;code&gt;enum&lt;/code&gt; is one of my favorite Scala 3 features, as it removes the error-prone boilerplate.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/05/25/scala-enums/?pk_campaign=rss&quot;&gt;Scala 3 Enums&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 25 May 2023 11:15:29 +0000</pubDate>
  <dc:modified>Tue, 06 Jun 2023 12:19:54 +0000</dc:modified>
  <atom:modified>Tue, 06 Jun 2023 12:19:54 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/05/25/scala-enums/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/05/25/scala-enums/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Java</category>
  <category>Scala</category>
  <category>Scala 3</category>
  <category>Programming</category>
  </item>


<item>
  <title>Managing Database Migrations in Kotlin</title>
  <description>The database schema should be described as code, in your repository. And you should be able to semi-automatically update your database schema on new deployments. Now in Kotlin, with Gradle and Flyway.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2023/05/02/managing-database-migrations-kotlin/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2023-kotlin-db-migrations.png?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;1000&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  The database schema should be described as code, in your repository. And you should be able to semi-automatically update your database schema on new deployments. Now in Kotlin, with Gradle and Flyway.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  This article is a rewrite of my &lt;a href=&quot;https://alexn.org/blog/2020/11/15/managing-database-migrations-scala/&quot;&gt;previous article&lt;/a&gt; on the same topic, that was showing code snippets meant for &lt;a href=&quot;https://www.scala-lang.org/&quot;&gt;Scala&lt;/a&gt; and the &lt;a href=&quot;https://www.scala-sbt.org/&quot;&gt;sbt&lt;/a&gt; build tool. This article is meant for Kotlin (or Java), with Gradle integration, but also making use of Flyway.
&lt;/p&gt;

&lt;p&gt;We’re going to use &lt;a href=&quot;https://flywaydb.org/&quot;&gt;Flyway&lt;/a&gt; to manage our database migrations, a Java library that’s useful enough.&lt;/p&gt;

&lt;p&gt;Before we start, note that Flyway has a &lt;a href=&quot;https://plugins.gradle.org/plugin/org.flywaydb.flyway&quot;&gt;Gradle plugin&lt;/a&gt;, just like it has an &lt;a href=&quot;https://github.com/flyway/flyway-sbt&quot;&gt;sbt plugin&lt;/a&gt; or a Maven plugin. And with something like Spring Boot or Quarkus, you can get out of the box configuration for Flyway / Liquidbase, possibly using those plugins. We are not going to look at such integrations in this article, because they force you into a rigid configuration, project structure, or deployment possibilities. Here are some potential issues with such integrations:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Reusing your database connection settings, specified somewhere else;&lt;/li&gt;
  &lt;li&gt;Creating an executable JAR that can execute those migrations;&lt;/li&gt;
  &lt;li&gt;Executing the migrations at application startup (not recommended for serious™️ apps, but always an option);&lt;/li&gt;
  &lt;li&gt;Running different migration files for different database types, depending on configuration;&lt;/li&gt;
  &lt;li&gt;Having subprojects, that may be independent, each with their own set of database migrations.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We gain all of this flexibility with some manual wiring that’s only a couple of lines of code.&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
  This article will depend just on Flyway’s API, or in other words, just on &lt;code&gt;flyway-core&lt;/code&gt;. We are not using any available integrations with the build tools.
&lt;/p&gt;

&lt;h2 id=&quot;1-postgresql-setup&quot;&gt;1. PostgreSQL setup&lt;/h2&gt;

&lt;p&gt;We are going to use PostgreSQL as our sample database. To start an instance, you could use Docker. Here’s a sample &lt;code&gt;docker-compose.yaml&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;version: &apos;3.3&apos;

services:
  postgresdb:
    container_name: postgresdb
    image: &apos;postgres:15-alpine&apos;
    ports:
      - &quot;5432:5432&quot;
    healthcheck:
      test: [&apos;CMD&apos;, &apos;pg_isready&apos;, &apos;-U&apos;, &apos;postgres&apos;]
    volumes:
      - &apos;postgresdb-volume:/var/lib/postgresql/data&apos;
    restart: always
    environment:
      POSTGRES_PASSWORD: pass

volumes:
  postgresdb-volume:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Start this instance:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;docker-compose -f ./docker-compose.yaml up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And create your initial database named &lt;code&gt;my_sample_db&lt;/code&gt; (this step is pretty hard to add as part of your migration files, so might as well not do it):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;docker exec -it postgresdb /usr/local/bin/psql \
  -U postgres \
  -c &quot;CREATE DATABASE my_sample_db&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;2-initial-project-setup&quot;&gt;2. Initial project setup&lt;/h2&gt;

&lt;p&gt;Create a new directory and switch to it from the shell:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;mkdir migrations-sample
cd migrations-sample/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To start your new Kotlin project (accept all defaults):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;gradle init --type kotlin-application --dsl kotlin
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to specify a configuration file, and it’s going to be our own configuration file, because why not? One way of doing that is to use the &lt;a href=&quot;https://github.com/Kotlin/kotlinx.serialization&quot;&gt;Kotlinx Serialization&lt;/a&gt; plugin and library, so we’ll need to add it as a dependency.&lt;/p&gt;

&lt;p&gt;Edit the file &lt;code&gt;app/build.gradle.kts&lt;/code&gt;, and make sure the &lt;code&gt;plugins&lt;/code&gt; section looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;plugins {
  kotlin(&quot;jvm&quot;) version &quot;1.8.21&quot;
  kotlin(&quot;plugin.serialization&quot;) version &quot;1.8.21&quot;
  application
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we’ll need these library dependencies:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;dependencies {
  // For managing our database migrations
  // https://github.com/flyway/flyway
  implementation(&quot;org.flywaydb:flyway-core:9.17.0&quot;)

  // For parsing CLI arguments
  // https://github.com/Kotlin/kotlinx-cli
  implementation(&quot;org.jetbrains.kotlinx:kotlinx-cli:0.3.5&quot;)

  // For couroutines support; not strictly needed, but it&apos;s nice to
  // indicate when blocking I/O needs the thread-pool meant for blocking stuff.
  // https://github.com/Kotlin/kotlinx.coroutines
  implementation(&quot;org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.0-RC&quot;)

  // For parsing our configuration file. Using:
  //  - https://github.com/Kotlin/kotlinx.serialization
  //  - https://github.com/lightbend/config (HOCON as the format)
  implementation(&quot;org.jetbrains.kotlinx:kotlinx-serialization-hocon:1.5.0&quot;)

  // Database driver (JDBC)
  implementation(&quot;org.postgresql:postgresql:42.6.0&quot;)

  // Flyway has built-in logging, which we can expose via SLF4J/Logback
  implementation(&quot;ch.qos.logback:logback-classic:1.4.7&quot;)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We’re adding logging (via slf4j/logback), and we might want to silence Flyway’s logging for anything that’s unimportant. Let’s also add a &lt;code&gt;logback.xml&lt;/code&gt; file to the &lt;code&gt;app/src/main/resources&lt;/code&gt; directory:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;configuration debug=&quot;false&quot;&gt;
  &lt;statusListener class=&quot;ch.qos.logback.core.status.NopStatusListener&quot; /&gt;
  &lt;appender name=&quot;STDOUT&quot; class=&quot;ch.qos.logback.core.ConsoleAppender&quot;&gt;
    &lt;withJansi&gt;true&lt;/withJansi&gt;
    &lt;encoder&gt;
      &lt;pattern&gt;[%date{ISO8601}] [%highlight(%level)] [%boldYellow(%marker)] [%logger] [%thread] %cyan([%mdc]) — %msg%n&lt;/pattern&gt;
    &lt;/encoder&gt;
  &lt;/appender&gt;

  &lt;logger name=&quot;org.flywaydb.core&quot; level=&quot;WARN&quot; /&gt;

  &lt;root level=&quot;info&quot;&gt;
    &lt;appender-ref ref=&quot;STDOUT&quot; /&gt;
  &lt;/root&gt;
&lt;/configuration&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;3-configuration&quot;&gt;3. Configuration&lt;/h2&gt;

&lt;p&gt;Create a new file &lt;code&gt;app/src/main/resources/database.conf&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;jdbc-connection.main {
  driver = &quot;org.postgresql.Driver&quot;

  url = &quot;jdbc:postgresql://localhost:5432/my_sample_db&quot;
  url = ${?JDBC_CONNECTION_MAIN_URL}

  username = &quot;sample_user&quot;
  username = ${?JDBC_CONNECTION_MAIN_USERNAME}

  password = ${JDBC_CONNECTION_MAIN_PASSWORD}

  migrationsTable = &quot;main_migrations&quot;
  migrationsLocations = [
    &quot;classpath:db/migrations/main/psql&quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are several things to unpack here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;This is our own format, you can define your own, or reuse whatever configuration file you have; in this case the file is using HOCON (a JSON superset), it’s included as a “resource” in the final artefact, and it is allowing for environment variables to override the values;&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;migrationsTable&lt;/code&gt; and &lt;code&gt;migrationsLocations&lt;/code&gt; are needed because we may have multiple sub-projects, each with their own (independent) migrations, and we want to execute them all;&lt;/li&gt;
  &lt;li&gt;We specify the username and the password, but these are the app’s credentials, and are not the user and password used when migrating the DB; I think it’s a security vulnerability to allow the app’s user to modify tables, or create triggers on its own, so this “MAIN” user should have limited permisisons (but you can ignore this “best practice”);&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And then, using the &lt;code&gt;kotlinx-serialization-hocon&lt;/code&gt; dependency, we can model this as a type-safe data class, and read this file in our own code. Add this file in &lt;code&gt;app/src/main/kotlin/&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;package migrations.sample

import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.hocon.Hocon

@Serializable
data class JdbcConnectionConfig(
  val url: String,
  val driver: String,
  val username: String,
  val password: String,
  val migrationsTable: String,
  val migrationsLocations: List&lt;String&gt;,
  val migrationsPlaceholders: Map&lt;String, String&gt; = emptyMap()
) {
  companion object {
    @OptIn(ExperimentalSerializationApi::class)
    suspend fun loadFromGlobal(
      configNamespace: String,
      config: Config? = null
    ): JdbcConnectionConfig =
      withContext(Dispatchers.IO) {
        val rawCfg = config ?: ConfigFactory.load().resolve()
        val cfg = rawCfg.getConfig(configNamespace)
        Hocon.decodeFromConfig(serializer(), cfg)
      }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Modeling your app’s configuration in such a type-safe way isn’t necessarily required, and it’s certainly not a very common practice in Java projects. But it’s a pity, as it makes APIs clearer, being a great way to document your configuration in the code itself.&lt;/p&gt;

&lt;h2 id=&quot;4-flyway-api-library-integration&quot;&gt;4. Flyway API library integration&lt;/h2&gt;

&lt;p&gt;Create a new file &lt;code&gt;RunMigrations.kt&lt;/code&gt; in &lt;code&gt;app/src/main/kotlin/&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;package migrations.sample

import com.typesafe.config.ConfigFactory
import kotlinx.cli.ArgParser
import kotlinx.cli.ArgType
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.flywaydb.core.Flyway
import org.flywaydb.core.api.configuration.FluentConfiguration
import org.flywaydb.core.api.output.MigrateResult
import org.slf4j.LoggerFactory
import kotlin.system.exitProcess

/**
 * Given a JDBC configuration, run the associated DB migrations.
 *
 * NOTE: `adminUsername` and `adminPassword` are different from the
 * credentials specified in `JdbcConnectionConfig`. That&apos;s because the
 * &quot;admin&quot; user may be different from the app&apos;s user. So if an
 * `adminUsername` and an `adminPassword` are provided, Flyway will
 * use that admin user to execute migrations.
 *
 * Flyway uses &quot;placeholders&quot; that can be used in the SQL migrations.
 * These can be specified in `JdbcConnectionConfig`, but this code
 * also sets 2 special placeholders to use from the
 * `JdbcConnectionConfig` itself: `dbUsername` and `dbPassword`. These
 * can be used to create the app&apos;s user as part of the defined
 * migrations.
 */
suspend fun dbMigrate(
  config: JdbcConnectionConfig,
  adminUsername: String?,
  adminPassword: String?
): MigrateResult =
  withContext(Dispatchers.IO) {
    val m: FluentConfiguration = Flyway.configure()
      .dataSource(
        config.url,
        adminUsername ?: config.username,
        if (adminUsername != null) adminPassword else config.password,
      )
      .group(true)
      .outOfOrder(false)
      .table(config.migrationsTable)
      .locations(*config.migrationsLocations.toTypedArray())
      .baselineOnMigrate(true)
      .loggers(&quot;slf4j&quot;)
      .placeholders(
        config.migrationsPlaceholders +
            mapOf(
              &quot;dbUsername&quot; to config.username,
              &quot;dbPassword&quot; to config.password
            ).filterValues { it != null }
      )

    val validated = m
      .ignoreMigrationPatterns(&quot;*:pending&quot;)
      .load()
      .validateWithResult()

    if (!validated.validationSuccessful) {
      val logger = LoggerFactory.getLogger(&quot;RunMigrations&quot;)
      for (error in validated.invalidMigrations) {
        logger.warn(
          &quot;&quot;&quot;
            |Failed to validate migration:
            |  - version: ${error.version}
            |  - path: ${error.filepath}
            |  - description: ${error.description}
            |  - error code: ${error.errorDetails.errorCode}
            |  - error message: ${error.errorDetails.errorMessage}
          &quot;&quot;&quot;.trimMargin(&quot;|&quot;).trim()
        )
      }
    }
    m.load().migrate()
  }

object RunMigrations {
  private suspend fun migrateNamespace(
    label: String,
    config: JdbcConnectionConfig,
    adminUsername: String,
    adminPassword: String
  ): Unit = withContext(Dispatchers.IO) {
    val result = dbMigrate(
      config,
      adminUsername,
      adminPassword
    )
    println(&quot;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=&quot;)
    println(&quot;Migrating: $label&quot;)
    println(&quot;------------------------------------&quot;)
    println(&quot;Initial schema version: ${result.initialSchemaVersion}&quot;)
    println(&quot;Target schema version: ${result.targetSchemaVersion}&quot;)
    if (result.migrations.isNotEmpty()) {
      println(&quot;------------------------------------&quot;)
      println(&quot;Executed migrations:&quot;)
      for (migration in result.migrations) {
        println(&quot; - ${migration.version} ${migration.type} ${migration.description}&quot;)
      }
    }
    if (result.warnings.isNotEmpty()) {
      println(&quot;------------------------------------&quot;)
      System.err.println(&quot;WARNINGS:&quot;)
      for (warning in result.warnings) {
        System.err.println(&quot; - $warning&quot;)
      }
    }
    println(&quot;------------------------------------&quot;)
    if (result.success) {
      println(&quot;Successfully migrated: $label!&quot;)
    } else {
      System.err.println(&quot;ERROR: Failed to migrate $label!&quot;)
      exitProcess(1)
    }
  }

  @JvmStatic
  fun main(args: Array&lt;String&gt;) {
    val parser = ArgParser(&quot;RunMigrations&quot;)
    val adminUsername by parser.argument(
      ArgType.String,
      fullName = &quot;admin-username&quot;,
      description = &quot;Admin username for the database. Example: postgres&quot;
    )
    val adminPassword by parser.argument(
      ArgType.String,
      fullName = &quot;admin-password&quot;,
      description = &quot;Admin password for the database.&quot;
    )
    parser.parse(args)

    runBlocking {
      val config =
        ConfigFactory.load(&quot;database.conf&quot;).resolve()
      val mainConfig =
        JdbcConnectionConfig.loadFromGlobal(
          &quot;jdbc-connection.main&quot;,
          config
        )
      migrateNamespace(
        &quot;main&quot;,
        mainConfig,
        adminUsername,
        adminPassword
      )
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this code, we only deal with a single database configuration and its associated migrations. But note that we can have multiple database configurations, each with their own migrations, corresponding to different subprojects. You simply add multiple &lt;code&gt;migrateNamespace&lt;/code&gt; calls.&lt;/p&gt;

&lt;h2 id=&quot;5-adding-the-sql-migrations&quot;&gt;5. Adding the SQL migrations&lt;/h2&gt;

&lt;p&gt;We are going to create files in &lt;code&gt;app/src/main/resources/db/migrations/main/psql&lt;/code&gt;. This matches the &lt;code&gt;migrationsLocations&lt;/code&gt; defined in the &lt;code&gt;database.conf&lt;/code&gt; above (which gets parsed in &lt;code&gt;JdbcConnectionConfig&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Create a new file named &lt;code&gt;V0010__create-user.sql&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE USER &quot;${dbUsername}&quot; WITH PASSWORD &apos;${dbPassword}&apos;;
CREATE SCHEMA IF NOT EXISTS sample
  AUTHORIZATION &quot;${dbUsername}&quot;;

GRANT
  CONNECT,
  TEMPORARY
ON DATABASE &quot;my_sample_db&quot;
TO &quot;${dbUsername}&quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then create another file named &lt;code&gt;V0020__create-tables.sql&lt;/code&gt; and add some nice tables to it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE sample.users
(
  id bigint not null generated always as identity primary key,
  email varchar(255) not null,
  password varchar(255) default null,
  timezone varchar(30) not null,
  created_at timestamp with time zone not null,
  updated_at timestamp with time zone not null
);

CREATE TABLE sample.stuff
(
  id bigint not null generated always as identity primary key,
  user_id bigint not null,
  json_data jsonb not null,
  created_at timestamp with time zone not null,
  updated_at timestamp with time zone not null,
  foreign key (user_id) references sample.users(id)
    on delete cascade
    on update cascade
);

GRANT
  SELECT,
  INSERT,
  UPDATE,
  DELETE,
  TRUNCATE
ON ALL TABLES IN SCHEMA sample
TO &quot;${dbUsername}&quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;6-gradle-configuration&quot;&gt;6. Gradle configuration&lt;/h2&gt;

&lt;p&gt;We need the following in &lt;code&gt;build.gradle.kts&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;tasks.register&lt;JavaExec&gt;(&quot;migrate&quot;) {
  group = &quot;Execution&quot;
  description = &quot;Migrates the database to the latest version&quot;
  classpath = sourceSets.getByName(&quot;main&quot;).runtimeClasspath
  mainClass.set(&quot;migrations.sample.RunMigrations&quot;)

  val user = System.getenv(&quot;POSTGRES_ADMIN_USER&quot;)
    ?: &quot;postgres&quot;
  val pass = System.getenv(&quot;POSTGRES_ADMIN_PASSWORD&quot;)
    ?: throw GradleException(
      &quot;POSTGRES_ADMIN_PASSWORD environment variable must be set&quot;
    )
  args = listOf(user, pass)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;7-running-the-migrations&quot;&gt;7. Running the migrations&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;# Needed by the Gradle task
export POSTGRES_ADMIN_PASSWORD=&quot;pass&quot;
# Needed by the application (HOCON) config
export JDBC_CONNECTION_MAIN_PASSWORD=&quot;pass&quot;

./gradlew migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which will output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&gt; Task :app:migrate
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Migrating: main
------------------------------------
Initial schema version: 0020
Target schema version: null
------------------------------------
Successfully migrated: main!

BUILD SUCCESSFUL in 2s
3 actionable tasks: 2 executed, 1 up-to-date
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;8-pro-tip-unit-test-migrations-with-hsqldb&quot;&gt;8. Pro-tip: unit-test migrations with HSQLDB&lt;/h2&gt;

&lt;p&gt;You can use something like HSQLDB to unit-test your JDBC-based code. HSQLDB is an in-memory database perfect for tests.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;dependencies {
  //...
  testImplementation(&quot;org.hsqldb:hsqldb:2.5.1&quot;)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In your &lt;code&gt;src/test/resources&lt;/code&gt; you could have a &lt;code&gt;test.database.conf&lt;/code&gt; with a setup like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;include &quot;database.conf&quot;

// Overrides PostgreSQL connection with in-memory HSQLDB
jdbc-connection.main {
  url = &quot;jdbc:hsqldb:mem:MyTestDB;sql.syntax_pgs=true&quot;
  driver = &quot;org.hsqldb.jdbc.JDBCDriver&quot;
  username = null
  password = null
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we are using the &lt;a href=&quot;https://hsqldb.org/doc/2.0/guide/compatibility-chapt.html#coc_compatibility_postgres&quot;&gt;PostgreSQL compatibility mode&lt;/a&gt;, which isn’t perfect, as it only supports standard RDBMS stuff. Depending on your SQL code, it might be enough. Note that it probably doesn’t work with &lt;code&gt;jsonb&lt;/code&gt; columns 🙂 but for simpler schemas it might be enough. Or you could have code specific for HSQLDB by manipulating the &lt;code&gt;migrationsLocations&lt;/code&gt; setting to point to a different path:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;include &quot;database.conf&quot;

jdbc-connection.main {
  //...
  migrationsLocations = [
    &quot;classpath:db/migrations/main/hsqldb&quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then in your tests you can run those migrations by simply calling that &lt;code&gt;dbMigrate&lt;/code&gt; function, and then profit! 🤑&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;class MyTest {
  @Test fun something() =
    runBlocking {
      val rawConfig =
        ConfigFactory.load(&quot;test.database.conf&quot;).resolve()
      val jdbcConfig =
        JdbcConnectionConfig.loadFromGlobal(
          &quot;jdbc-connection.main&quot;,
          rawConfig
        )
      // Ta da!
      dbMigrate(jdbcConfig)
      //...
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Your DB API mocks will never be the same again! 😎&lt;/p&gt;

&lt;h2 id=&quot;epilogue&quot;&gt;Epilogue&lt;/h2&gt;

&lt;p&gt;For a sample project, checkout this GitHub repository:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/alexandru/sample-projects/tree/main/kotlin-db-migrations&quot;&gt;sample-projects/kotlin-db-migrations&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enjoy~&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/05/02/managing-database-migrations-kotlin/?pk_campaign=rss&quot;&gt;Managing Database Migrations in Kotlin&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 02 May 2023 07:32:06 +0000</pubDate>
  <dc:modified>Thu, 25 May 2023 07:30:16 +0000</dc:modified>
  <atom:modified>Thu, 25 May 2023 07:30:16 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/05/02/managing-database-migrations-kotlin/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/05/02/managing-database-migrations-kotlin/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Kotlin</category>
  <category>SQL</category>
  </item>


<item>
  <title>Kotlin Coroutines to Cats-Effect</title>
  <description>Kotlin Coroutines are usually integrated in Java code via Java’s CompletableFuture, but a tighter integration might be possible with Cats-Effect.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  Kotlin &lt;a href=&quot;https://kotlinlang.org/docs/coroutines-overview.html&quot;&gt;Coroutines&lt;/a&gt; are usually integrated in Java code via Java’s &lt;code&gt;CompletableFuture&lt;/code&gt;, but a tighter integration might be possible with &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats-Effect&lt;/a&gt;. I played around to see if I can convert Kotlin’s coroutines, built via suspended functions straight to &lt;code&gt;cats.effect.IO&lt;/code&gt;. Turns out I could.
&lt;/p&gt;

&lt;p&gt;The following snippet is an executable script via &lt;a href=&quot;https://scala-cli.virtuslab.org/&quot;&gt;Scala-CLI&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//#!/usr/bin/env -S scala-cli shebang -q

//&gt; using scala &quot;2.13.10&quot;
//&gt; using lib &quot;org.typelevel::cats-effect::3.4.9&quot;
//&gt; using lib &quot;org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4&quot;

import cats.effect._
import kotlin.coroutines.{Continuation, CoroutineContext}
import kotlinx.coroutines.{Deferred, _}

import java.util.Collections
import java.util.concurrent.{AbstractExecutorService, CancellationException, TimeUnit}
import scala.concurrent.ExecutionContextExecutorService
import scala.concurrent.duration._
import scala.util.control.{NoStackTrace, NonFatal}

object Main extends IOApp {
  // Sleeping via Kotlin&apos;s coroutines
  def kotlinSleep(duration: FiniteDuration): IO[Unit] =
    KotlinCoroutines.runCancelable_ { (_, cont) =&gt;
      // Kotlin suspended function calls...
      kotlinx.coroutines.DelayKt.delay(duration.toMillis, cont)
    }

  override def run(args: List[String]): IO[ExitCode] =
    for {
      _ &lt;- IO.println(&quot;Running...&quot;)
      fiber &lt;- kotlinSleep(10.seconds).start
      _ &lt;- IO.sleep(1000.millis)
      _ &lt;- fiber.cancel
      _ &lt;- fiber.joinWithUnit
      _ &lt;- IO.println(&quot;Done!&quot;)
    } yield ExitCode.Success
}

object KotlinCoroutines {
  def runCancelable_(
    block: (CoroutineScope, Continuation[_ &gt;: kotlin.Unit]) =&gt; Any
  ): IO[Unit] = {
    runCancelable(block).void
  }

  def runCancelable[A](
    block: (CoroutineScope, Continuation[_ &gt;: A]) =&gt; Any
  ): IO[A] = {
    coroutineToIOFactory[A](block, buildCancelToken)
  }

  private def dispatcher: IO[CoroutineDispatcher] =
    IO.executionContext.map { other =&gt;
      kotlinx.coroutines.ExecutorsKt.from(
        new AbstractExecutorService with ExecutionContextExecutorService {
          override def isShutdown = false
          override def isTerminated = false
          override def shutdown() = ()
          override def shutdownNow() = Collections.emptyList[Runnable]
          override def execute(runnable: Runnable): Unit = other.execute(runnable)
          override def reportFailure(t: Throwable): Unit = other.reportFailure(t)
          override def awaitTermination(length: Long, unit: TimeUnit): Boolean = false
        }
      )
    }

  private def coroutineToIOFactory[A](
    block: (CoroutineScope, Continuation[_ &gt;: A]) =&gt; Any,
    buildCancelToken: (Deferred[_], DisposableHandle) =&gt; Option[IO[Unit]]
  ): IO[A] = {
    dispatcher.flatMap { dispatcher =&gt;
      IO.async[A] { cb =&gt;
        IO {
          try {
            val context = CoroutineContextKt.newCoroutineContext(
              GlobalScope.INSTANCE,
              dispatcher.asInstanceOf[CoroutineContext],
            )
            val deferred = kotlinx.coroutines.BuildersKt.async(
              GlobalScope.INSTANCE,
              context,
              CoroutineStart.DEFAULT,
              (p1: CoroutineScope, p2: Continuation[_ &gt;: A]) =&gt; block(p1, p2)
            )
            try {
              val dispose = deferred.invokeOnCompletion(
                (e: Throwable) =&gt; {
                  e match {
                    case e: Throwable =&gt; cb(Left(e))
                    case _ =&gt; cb(Right(deferred.getCompleted))
                  }
                  kotlin.Unit.INSTANCE
                })
              buildCancelToken(deferred, dispose)
            } catch {
              case NonFatal(e) =&gt;
                deferred.cancel(null)
                throw e
            }
          } catch {
            case NonFatal(e) =&gt;
              cb(Left(e))
              None
          }
        }
      }
    }.recoverWith {
      case PleaseCancel =&gt;
        // This branch actually never happens, but it might
        // prevent leaks in case of a bug
        IO.canceled *&gt; IO.never
    }
  }

  private def buildCancelToken(deferred: Deferred[_], dispose: DisposableHandle): Option[IO[Unit]] =
    Some(IO.defer {
      deferred.cancel(PleaseCancel)
      dispose.dispose()
      // Await for completion or cancellation
      coroutineToIOFactory[kotlin.Unit](
        (_, cont) =&gt; deferred.join(cont),
        (_, _) =&gt; None
      ).void
    })

  private object PleaseCancel
    extends CancellationException with NoStackTrace
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/04/24/kotlin-suspended-functions-to-cats-effect-io/?pk_campaign=rss&quot;&gt;Kotlin Coroutines to Cats-Effect&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 24 Apr 2023 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2023/04/24/kotlin-suspended-functions-to-cats-effect-io/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/04/24/kotlin-suspended-functions-to-cats-effect-io/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Kotlin</category>
  <category>Programming</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Integrating Akka with Cats-Effect 3</title>
  <description>We are using a combination of Akka and Cats-Effect (ver. 3) for building payment processors. This post describes some solutions we’ve discovered.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2023/04/17/integrating-akka-with-cats-effect-3/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2023-akka-plus-cats-effect.png?202603060940&quot; alt=&quot;&quot; width=&quot;2376&quot; height=&quot;864&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  We are using a combination of &lt;a href=&quot;https://akka.io/&quot;&gt;Akka&lt;/a&gt; and &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats-Effect&lt;/a&gt; (ver. 3) for building payment processors. Integrating them isn’t without challenges. This post describes some solutions we’ve discovered.
&lt;/p&gt;

&lt;p&gt;We’ve been using Akka because &lt;a href=&quot;https://doc.akka.io/docs/akka/2.6.20/typed/index-cluster.html&quot;&gt;Akka Cluster&lt;/a&gt; and &lt;a href=&quot;https://doc.akka.io/docs/akka/2.6.20/typed/persistence.html&quot;&gt;Akka Persistence&lt;/a&gt; fitted our needs for data persistence. We’re also using &lt;a href=&quot;https://doc.akka.io/docs/akka/2.6.20/stream/index.html&quot;&gt;Akka Stream&lt;/a&gt;, because our flows are complicated graphs, even though at times it felt overkill and &lt;a href=&quot;https://fs2.io/&quot;&gt;fs2&lt;/a&gt; might have been a better fit. Note that &lt;a href=&quot;https://alexn.org/blog/2022/09/07/akka-is-moving-away-from-open-source/&quot;&gt;Akka has gone proprietary&lt;/a&gt;, and we’re still on the last FOSS version (&lt;code&gt;2.6.20&lt;/code&gt;). We might pay up to upgrade to the proprietary license, although I’m rooting for &lt;a href=&quot;https://pekko.apache.org/&quot;&gt;Apache Pekko&lt;/a&gt; to become stable.&lt;/p&gt;

&lt;h2 id=&quot;starting-actor-systems-as-a-resource&quot;&gt;Starting Actor Systems as a Resource&lt;/h2&gt;

&lt;p&gt;Cats-Effect’s &lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/resource&quot;&gt;Resource&lt;/a&gt; is one of the secret weapons of Scala. When you have Cats-Effect in your project, it’s best to manage the lifecycle of resources via &lt;code&gt;Resource&lt;/code&gt;. Akka also provides its own &lt;a href=&quot;https://doc.akka.io/docs/akka/current/coordinated-shutdown.html&quot;&gt;coordinated-shutdown&lt;/a&gt; mechanism, but I recommend going with &lt;code&gt;Resource&lt;/code&gt;, due to the ease of use, and the reasoning capabilities.&lt;/p&gt;

&lt;p&gt;First, let’s get the dependencies out of the way:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// sbt syntax
libraryDependencies ++= Seq(
  &quot;com.typesafe.akka&quot; %% &quot;akka-actor&quot; % &quot;2.6.20&quot;,
  &quot;com.typesafe.akka&quot; %% &quot;akka-actor-typed&quot; % &quot;2.6.20&quot;,
  &quot;ch.qos.logback&quot; % &quot;logback-classic&quot; % &quot;1.4.6&quot;,
  // FP awesomeness!!!
  &quot;org.typelevel&quot; %% &quot;cats-effect&quot; % &quot;3.4.9&quot;,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the imports:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import akka.Done
import akka.actor.{CoordinatedShutdown, ActorSystem =&gt; UntypedActorSystem}
import cats.effect.kernel.Resource
import cats.effect.std.Dispatcher
import cats.effect.{Deferred, IO}
import cats.syntax.all._
import com.typesafe.config.Config
import org.slf4j.LoggerFactory
import scala.concurrent.TimeoutException
import scala.concurrent.duration._
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To create an actor system in the context of a &lt;code&gt;Resource&lt;/code&gt;, a naive approach would be this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Version 1 of 3: DO NOT USE THIS
def startActorSystemUntyped(
  systemName: String,
  config: Option[Config],
): Resource[IO, UntypedActorSystem] =
  Resource(IO {
    val system = UntypedActorSystem(
      systemName.trim.replaceAll(&quot;\\W+&quot;, &quot;-&quot;),
      config = config
    )
    // Here, system.terminate() returns a `Future[Terminated]`
    val cancel = IO.fromFuture(IO(system.terminate())).void
    (system, cancel)
  })
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first problem with this approach is that both Akka and Cats-Effect 3 are creating their own thread-pool. Having too many thread-pools meant for CPU-bound tasks can decrease performance and make problems harder to investigate. Cats-Effect’s thread-pool is optimized for &lt;code&gt;IO&lt;/code&gt; and it would be a pity if we wouldn’t use it. Akka’s thread-pool is the old and reliable &lt;code&gt;ForkJoinPool&lt;/code&gt;, that’s also used by Scala’s &lt;code&gt;global&lt;/code&gt;, but CE’s thread-pool is perfectly adequate for use with Akka as well, due to properly implementing &lt;a href=&quot;https://www.scala-lang.org/api/2.13.10/scala/concurrent/BlockContext.html&quot;&gt;BlockContext&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that it’s best if this would be configurable. So here’s version 2:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Version 2 out of 3: DO NOT USE THIS
def startActorSystemUntyped(
  systemName: String,
  config: Option[Config],
  useIOExecutionContext: Boolean,
): Resource[IO, UntypedActorSystem] =
  Resource(
    for {
      // Fishing IO&apos;s `ExecutionContext`
      ec &lt;- Option
        .when(useIOExecutionContext) { IO.executionContext }
        .sequence
      system &lt;- IO {
        UntypedActorSystem(
          systemName.trim.replaceAll(&quot;\\W+&quot;, &quot;-&quot;),
          config = config,
          defaultExecutionContext = ec,
        )
      }
    } yield {
      // Here, system.terminate() returns a `Future[Terminated]`
      val cancel = IO.fromFuture(IO(system.terminate())).void
      (system, cancel)
    }
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There is one more problem, best described as a setting that you’ll often see in an &lt;code&gt;application.conf&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;akka.coordinated-shutdown.exit-jvm = on
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This setting tells Akka to forcefully stop the JVM as part of the coordinated shutdown process. And &lt;em&gt;this setting is good&lt;/em&gt;, you should have this on. And that’s because &lt;strong&gt;Akka can decide to shut down on its own&lt;/strong&gt;, and afterward it’s probably best to shut down the process, too. One example is when using Akka Cluster, with a &lt;a href=&quot;https://doc.akka.io/docs/akka-enhancements/current/split-brain-resolver.html&quot;&gt;split-brain resolver&lt;/a&gt;, in which case Akka should shut down the application in case the node is removed from the cluster. If it doesn’t, then the app could be left in a zombie state.&lt;/p&gt;

&lt;p&gt;Both Akka and Cats-Effect can add a shut-down hook to the JVM, via &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)&quot;&gt;Runtime.addShutdownHook&lt;/a&gt;. Cats-Effect can do it via its &lt;code&gt;IOApp&lt;/code&gt; implementation. Akka does it as part of its coordinated-shutdown mechanism. This triggers the disposal process on &lt;code&gt;System.exit&lt;/code&gt;, no matter the reason it happened. And one problem is that both will start to dispose of resources, concurrently. In other words, Akka can shut down the actor system before Cats-Effect has had a chance to shut down all resources depending on that actor system. Which is usually bad.&lt;/p&gt;

&lt;p&gt;Another problem I discovered in testing is that in certain scenarios, Akka, on &lt;code&gt;system.terminate()&lt;/code&gt;, seems to return a &lt;code&gt;Future[Done]&lt;/code&gt; that never completes. Seems to be some sort of race condition, and it’s bad, as it can indefinitely block Cats-Effect’s resource disposal process. In my testing, this seemed to be alleviated if I first waited on a promise completed via a task registered with Akka’s coordinated-shutdown (see below). I don’t know if this code solves it or not, but a “timeout” on &lt;code&gt;system.whenTerminated&lt;/code&gt; seems to be a good idea.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Version 3 out of 3: USE THIS

/** Starts an (untyped) Akka actor system in the
  * context of a Cats-Effect `Resource`, and integrating
  * with its cancellation abilities.
  *
  * HINT: for apps (in `main`), it&apos;s best if
  * `akka.coordinated-shutdown.exit-jvm` is set to `on`,
  * because Akka can decide to shutdown on its own. And
  * having this setting interacts well with Cats-Effect.
  *
  * @param systemName is the identifying name of the system.
  * @param config is an optional, parsed HOCON configuration;
  *        if None, then Akka will read its own, possibly
  *        from `application.conf`; this parameter is
  *        provided in order to control the source of
  *        the application&apos;s configuration.
  * @param useIOExecutionContext if true, then Cats-Effect&apos;s
  *        default thread-pool will get used by Akka, as well.
  *        This is needed in order to avoid having too many
  *        thread-pools.
  * @param timeoutAwaitCatsEffect is the maximum amount of time
  *        Akka&apos;s coordinated-shutdown is allowed to wait for
  *        Cats-Effect to finish. This is needed, as Cats-Effect
  *        could have a faulty stack of disposables, or because
  *        Akka could decide to shutdown on its own.
  * @param timeoutAwaitAkkaTermination is the maximum amount of
  *        time to wait for the actor system to terminate, after
  *        `terminate()` was called. We need the timeout, because
  *        `terminate()` proved to return a `Future` that never
  *        completes in certain scenarios (could be a bug, or a
  *        race condition).
  */
def startActorSystemUntyped(
  systemName: String,
  config: Option[Config],
  useIOExecutionContext: Boolean,
  timeoutAwaitCatsEffect: Duration,
  timeoutAwaitAkkaTermination: Duration,
): Resource[IO, UntypedActorSystem] = {
  // Needed to turn IO into Future
  // https://typelevel.org/cats-effect/docs/std/dispatcher
  Dispatcher.parallel[IO](await = true).flatMap { dispatcher =&gt;
    Resource[IO, UntypedActorSystem](
      for {
        // Fishing IO&apos;s `ExecutionContext`
        ec &lt;- Option
          .when(useIOExecutionContext)(IO.executionContext)
          .sequence
        // For synchronizing Cats-Effect with Akka
        awaitCancel &lt;- Deferred[IO, Unit]
        // For awaiting termination via coordinated-shutdown,
        // needed as `terminate()` is unreliable
        awaitTermination &lt;- Deferred[IO, Unit]
        logger = LoggerFactory.getLogger(getClass)
        system &lt;- IO {
          logger.info(&quot;Creating actor system...&quot;)
          val system = UntypedActorSystem(
            systemName.trim.replaceAll(&quot;\\W+&quot;, &quot;-&quot;),
            config = config,
            defaultExecutionContext = ec,
          )
          // Registering task in Akka&apos;s CoordinatedShutdown
          // that will wait for Cats-Effect to catch up,
          // blocking Akka from terminating, see:
          // https://doc.akka.io/docs/akka/current/coordinated-shutdown.html
          CoordinatedShutdown(system).addTask(
            CoordinatedShutdown.PhaseBeforeServiceUnbind,
            &quot;sync-with-cats-effect&quot;,
          ) { () =&gt;
            dispatcher.unsafeToFuture(
              // WARN: this may not happen, if Akka decided
              // to terminate, and `coordinated-shutdown.exit-jvm`
              // isn&apos;t `on`, hence the timeout:
              awaitCancel.get
                .timeout(timeoutAwaitCatsEffect)
                .recoverWith {
                  case ex: TimeoutException =&gt;
                    IO(logger.error(
                      &quot;Timed out waiting for Cats-Effect to catch up! &quot; +
                        &quot;This might indicate either a non-terminating &quot; +
                        &quot;cancellation logic, or a misconfiguration of Akka.&quot;
                    ))
                }
                .as(Done)
            )
          }
          CoordinatedShutdown(system).addTask(
            CoordinatedShutdown.PhaseActorSystemTerminate,
            &quot;signal-actor-system-terminated&quot;,
          ) { () =&gt;
            dispatcher.unsafeToFuture(
              awaitTermination.complete(()).as(Done)
            )
          }
          system
        }
      } yield {
        val cancel =
          for {
            // Signals that Cats-Effect has caught up with Akka
            _ &lt;- awaitCancel.complete(())
            _ &lt;- IO(logger.warn(&quot;Shutting down actor system!&quot;))
            // Shuts down Akka, and waits for its termination
            // Here, system.terminate() returns a `Future[Terminated]`,
            // but we are ignoring it, as it could be non-terminating
            _ &lt;- IO(system.terminate())
            // Waiting for Akka to terminate via coordinated-shutdown
            _ &lt;- awaitTermination.get
            // WARN: `whenTerminated` is unreliable, hence the timeout
            _ &lt;- IO.fromFuture(IO(system.whenTerminated))
              .void
              .timeoutAndForget(timeoutAwaitAkkaTermination)
              .handleErrorWith(_ =&gt;
                IO(logger.warn(
                  &quot;Timed-out waiting for Akka to terminate!&quot;
                ))
              )
          } yield ()
        (system, cancel)
      }
    )
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that the correctness of complicated apps relies on &lt;code&gt;akka.coordinated-shutdown.exit-jvm&lt;/code&gt; being set to &lt;code&gt;on&lt;/code&gt; in &lt;code&gt;application.conf&lt;/code&gt;. If you feel uneasy about this, note that this can be accomplished programmatically, by doing a manual &lt;code&gt;System.exit&lt;/code&gt; in that &lt;code&gt;CoordinateShutdown&lt;/code&gt; task:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// NOT NEEDED, prefer to use `application.conf`
CoordinatedShutdown(system).addTask(
  CoordinatedShutdown.PhaseBeforeServiceUnbind,
  &quot;shutdown-actor-system&quot;,
) { () =&gt;
  // System.exit will block the thread, so best to
  // run it async, in a fire-and-forget fashion
  val triggerShutdown =
    IO.blocking(System.exit(255))
      .start
      .void

  dispatcher.unsafeToFuture(
    (triggerShutdown *&gt; awaitCancel.get)
      .timeout(timoutAwaitCatsEffect)
      .recoverWith { ... }
      .as(Done)
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you do this, it will work OK, as both Cats-Effect and Akka install shutdown hooks. But I feel that this is duplicating the functionality of &lt;code&gt;akka.coordinated-shutdown.exit-jvm&lt;/code&gt;, making behavior unclear for those familiar with Akka and its configuration.&lt;/p&gt;

&lt;p&gt;On a final note, you can work with Akka’s &lt;a href=&quot;https://doc.akka.io/docs/akka/2.6.20/typed/from-classic.html&quot;&gt;typed actor systems&lt;/a&gt;, it’s the same thing. For simplicity, you could initialize it as a classic actor system (like we are doing above), and then convert it into a typed one:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import akka.actor.typed.scaladsl.adapter.ClassicActorSystemOps
system.toTyped
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;using-io-with-akka-stream&quot;&gt;Using IO with Akka Stream&lt;/h2&gt;

&lt;p&gt;For this section we need to depend on &lt;a href=&quot;https://doc.akka.io/docs/akka/2.6.20/stream/index.html&quot;&gt;Akka Stream&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// sbt syntax
libraryDependencies ++= Seq(
  &quot;com.typesafe.akka&quot; %% &quot;akka-stream&quot; % &quot;2.6.20&quot;,
  &quot;com.typesafe.akka&quot; %% &quot;akka-stream-typed&quot; % &quot;2.6.20&quot;,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;turning-an-io-into-a-flow&quot;&gt;Turning an IO into a Flow&lt;/h3&gt;

&lt;p&gt;An obvious solution for working with &lt;code&gt;IO&lt;/code&gt; in Akka Stream is via
&lt;a href=&quot;https://doc.akka.io/docs/akka/2.6.20/stream/operators/Source-or-Flow/mapAsync.html&quot;&gt;mapAsync&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import akka.NotUsed
import akka.stream.scaladsl.Flow
import cats.effect.IO
import cats.effect.std.Dispatcher

def uncancelableIOToFlow[A, B](parallelism: Int)(
  f: A =&gt; IO[B]
)(implicit d: Dispatcher[IO]): Flow[A, B, NotUsed] =
  Flow[A].mapAsync(parallelism)(a =&gt; d.unsafeToFuture(f(a)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need a &lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/dispatcher&quot;&gt;Dispatcher&lt;/a&gt; for turning &lt;code&gt;IO&lt;/code&gt; values into &lt;code&gt;Future&lt;/code&gt; values, as &lt;code&gt;mapAsync&lt;/code&gt; works with &lt;code&gt;Future&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is one glaring problem: &lt;code&gt;Future&lt;/code&gt; isn’t cancelable, and these &lt;code&gt;IO&lt;/code&gt; tasks may be long-running ones. And the code above will not cancel the running &lt;code&gt;IO&lt;/code&gt; when the stream is getting cancelled. Most often this isn’t a problem, and can be in fact desirable.&lt;/p&gt;

&lt;p&gt;In the context of Akka Stream, to execute &lt;code&gt;IO&lt;/code&gt; tasks as cancelable tasks, we need to work with &lt;code&gt;Publisher&lt;/code&gt; from the &lt;a href=&quot;https://github.com/reactive-streams/reactive-streams-jvm&quot;&gt;Reactive Streams&lt;/a&gt; specification. Implementation is low-level, as it has to synchronize concurrent calls:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import org.reactivestreams.{Publisher, Subscriber, Subscription}

/** Converts a Cats-Effect `IO` into a Reactive Streams `Publisher`.
  *
  * [[https://github.com/reactive-streams/reactive-streams-jvm]]
  */
def toPublisher[A](io: IO[A])(implicit d: Dispatcher[IO]): Publisher[A] =
  (s: Subscriber[_ &gt;: A]) =&gt; s.onSubscribe(new Subscription {
    type CancelToken = () =&gt; Future[Unit]

    private[this] val NOT_STARTED: Null = null
    private[this] val LOCKED = Left(false)
    private[this] val COMPLETED = Left(true)

    // State machine for managing the active subscription
    private[this] val ref =
      new AtomicReference[Either[Boolean, CancelToken]](NOT_STARTED)

    override def request(n: Long): Unit =
      ref.get() match {
        case NOT_STARTED =&gt;
          if (n &lt;= 0) {
            if (ref.compareAndSet(NOT_STARTED, COMPLETED))
              s.onError(new IllegalArgumentException(
                &quot;non-positive request signals are illegal&quot;
              ))
          } else {
            if (ref.compareAndSet(NOT_STARTED, LOCKED)) {
              val cancelToken = d.unsafeRunCancelable(
                io.attempt.flatMap { r =&gt;
                  IO {
                    r match {
                      case Right(value) =&gt;
                        s.onNext(value)
                        s.onComplete()
                      case Left(e) =&gt;
                        s.onError(e)
                    }
                    // GC purposes
                    ref.lazySet(COMPLETED)
                  }
                }
              )
              // Race condition with lazySet(COMPLETED), but it&apos;s fine
              ref.set(Right(cancelToken))
            }
          }
        case Right(_) | Left(_) =&gt;
          // Already active, or completed
          ()
      }

    @tailrec
    override def cancel(): Unit =
      ref.get() match {
        case NOT_STARTED =&gt;
          if (!ref.compareAndSet(NOT_STARTED, COMPLETED))
            cancel() // retry
        case LOCKED =&gt;
          Thread.onSpinWait()
          cancel() // retry
        case Left(_) =&gt;
          ()
        case current@Right(token) =&gt;
          // No retries necessary; if state changes from Right(token),
          // it means that the stream is already completed or canceled
          if (ref.compareAndSet(current, COMPLETED))
            token()
      }
  })
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we can turn &lt;code&gt;Publisher&lt;/code&gt; into a &lt;code&gt;Source&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import akka.stream.scaladsl.Source

def toSource[A](io: IO[A])(implicit d: Dispatcher[IO]): Source[A, NotUsed] =
  Source.fromPublisher(toPublisher(io))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And finally, we can use &lt;a href=&quot;https://doc.akka.io/docs/akka/2.6.20/stream/operators/Source-or-Flow/flatMapMerge.html&quot;&gt;flatMapMerge&lt;/a&gt; to get the desired behavior of having a &lt;code&gt;Flow&lt;/code&gt; that executes cancelable &lt;code&gt;IO&lt;/code&gt; tasks:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import akka.stream.scaladsl.Flow

def cancelableIOToFlow[A, B](parallelism: Int)(
  f: A =&gt; IO[B]
)(implicit d: Dispatcher[IO]): Flow[A, B, NotUsed] =
  Flow[A].flatMapMerge(
    breadth = parallelism,
    a =&gt; toSource(f(a))
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
  &lt;strong&gt;Warning:&lt;/strong&gt; &lt;code&gt;mapAsync&lt;/code&gt; is much more efficient than &lt;code&gt;flatMapMerge&lt;/code&gt; or &lt;code&gt;flatMapConcat&lt;/code&gt;. Unfortunately, Akka Stream isn’t optimized for flat-mapping on streams that emit a single event. Also, depending on how your streams are structured, you may actually want uncancelable execution. Apply good judgement!
&lt;/p&gt;

&lt;h3 id=&quot;repeated-execution-fixed-delay&quot;&gt;Repeated execution (fixed delay)&lt;/h3&gt;

&lt;p&gt;Your challenge, should you choose to accept it, is to turn this into a stream:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def tryPoll: IO[Option[Result]]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we want to describe a function that turns that into a stream, which is a common pattern:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def poll0[A](
  tryPoll: IO[Option[A]],
  sleepDelay: FiniteDuration,
)(implicit d: Dispatcher[IO]): Source[A, NotUsed] = {
  val logger = LoggerFactory.getLogger(getClass)
  Source.repeat(())
    .via(cancelableIOToFlow(1) { _ =&gt;
      tryPoll.handleError { e =&gt;
        logger.error(&quot;Unhandled error in poll&quot;, e)
        None
      }.flatTap {
        case None =&gt; IO.sleep(sleepDelay)
        case Some(_) =&gt; IO.unit
      }
    })
    .collect { case Some(a) =&gt; a }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The sleep itself could be managed by Akka Stream. At some point, our function looked like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def poll1[A](
  tryPoll: IO[Option[A]],
  interval: FiniteDuration,
)(implicit d: Dispatcher[IO]): Source[A, NotUsed] = {
  val logger = LoggerFactory.getLogger(getClass)
  // Notice the `takeWhile`. This is a child stream that gets
  // composed via `flatMapConcat`.
  val drain =
    Source.repeat(())
      .via(uncancelableIOToFlow(1) { _ =&gt;
        tryPoll.handleError { e =&gt;
          logger.error(&quot;Unhandled error in poll&quot;, e)
          None
        }
      })
      .takeWhile(_.nonEmpty)
      .collect { case Some(a) =&gt; a }

  // Main stream, managing the sleep intervals via Akka
  Source
    .tick(initialDelay = Duration.Zero, interval = interval, tick = ())
    .flatMapConcat(_ =&gt; drain)
    .mapMaterializedValue(_ =&gt; NotUsed)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This has the virtue of being fast, since the sleep is managed by Akka, and for draining our queue, we can manage to work with &lt;code&gt;mapAsync&lt;/code&gt; (and thus, uncancellable IO tasks). However, this had awkward behavior due to the buffering, and isn’t flexible enough. For instance, we wanted to specify a custom sleep duration for when exceptions are being thrown.&lt;/p&gt;

&lt;p&gt;Last, but not least, in this particular case you can simply use &lt;a href=&quot;https://fs2.io/&quot;&gt;fs2&lt;/a&gt;. This has the downside of introducing yet another dependency, and thus the area for potential issues is bigger. Extra dependencies on the classpath add risk. On the other hand, fs2 is designed to work with streams of IO tasks, being meant for precisely this use-case. And you can convert an &lt;code&gt;fs2.Stream&lt;/code&gt; via the Reactive Streams interoperability.&lt;/p&gt;

&lt;p&gt;You’ll need these dependencies:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// sbt syntax
libraryDependencies ++= Seq(
  &quot;co.fs2&quot; %% &quot;fs2-core&quot; % &quot;3.6.1&quot;,
  &quot;co.fs2&quot; %% &quot;fs2-reactive-streams&quot; % &quot;3.6.1&quot;,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the implementation:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def poll2[A](
  tryPoll: IO[Option[A]],
  interval: FiniteDuration,
)(implicit d: Dispatcher[IO]): Source[A, NotUsed] = {
  val logger = LoggerFactory.getLogger(getClass)
  val repeatedTask = tryPoll.handleError { e =&gt;
    logger.error(&quot;Unhandled error in poll&quot;, e)
    None
  }.flatTap {
    case None =&gt; IO.sleep(interval)
    case Some(_) =&gt; IO.unit
  }

  val stream = fs2.Stream
    .repeatEval(repeatedTask)
    .collect { case Some(a) =&gt; a }

  import fs2.interop.reactivestreams._
  Source.fromPublisher(new StreamUnicastPublisher(stream, d))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note, however, that using &lt;code&gt;fs2&lt;/code&gt; for use-cases like this isn’t without peril. For example, the cancellation model of Cats-Effect (and that of fs2) is incompatible with the Reactive Streams API when managing resources. You can’t turn a &lt;code&gt;Resource&lt;/code&gt; into a &lt;code&gt;Publisher&lt;/code&gt;. You can turn a &lt;code&gt;Resource&lt;/code&gt; into an &lt;code&gt;fs2.Stream&lt;/code&gt;, and if you then try to turn that &lt;code&gt;fs2.Stream&lt;/code&gt; into a &lt;code&gt;Publisher&lt;/code&gt;, you’ll end up with a &lt;code&gt;Publisher&lt;/code&gt; that doesn’t manage the resource correctly. Simply put, an &lt;code&gt;fs2.Stream&lt;/code&gt; is more powerful than a &lt;code&gt;Publisher&lt;/code&gt; (from the Reactive Streams spec), and so the conversion from fs2 to Reactive Streams can be problematic.&lt;/p&gt;

&lt;h2 id=&quot;akka-stream-graphs&quot;&gt;Akka Stream Graphs&lt;/h2&gt;

&lt;p&gt;When running graphs with Akka Stream, if the processing of individual events is critical (like in our case), the question is what happens when the process is being shut down, as there will be some transactions that will be in-flight, with a process shutdown interrupting them.&lt;/p&gt;

&lt;p&gt;We want to wait (with a timeout) for the processing of in-flight transactions, before the process is terminated. To achieve that, there are 2 elements to it:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The use of &lt;a href=&quot;https://doc.akka.io/docs/akka/2.6.20/stream/stream-dynamic.html#controlling-stream-completion-with-killswitch&quot;&gt;kill switches&lt;/a&gt;, to stop all inputs in your graph;&lt;/li&gt;
  &lt;li&gt;The detection of the completion signal, giving a chance for in-flight transactions to complete;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A &lt;code&gt;KillSwitch&lt;/code&gt; can be managed via &lt;code&gt;Resource&lt;/code&gt;, although, as you shall see, we may need to trigger the kill signal outside the context of this &lt;code&gt;Resource&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import akka.stream.{SharedKillSwitch, KillSwitches}

def sharedKillSwitch(name: String): Resource[IO, SharedKillSwitch] =
  Resource(IO {
    val ks = KillSwitches.shared(name)
    (ks, IO(ks.shutdown()))
  })
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another piece of the puzzle is that we may like to add logic to Cats-Effect’s cancellations stack:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def resourceFinalizer(effect: IO[Unit]): Resource[IO, Unit] =
  Resource(IO { ((), effect) })
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The method for starting the processing graph can look like this, and note that &lt;code&gt;IO[Done]&lt;/code&gt; should signal when the processing is complete (all inputs are completed):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def startProcessor(
  killSwitch: SharedKillSwitch
)(implicit
  system: ActorSystem[_],
): Resource[IO, IO[Done]]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can then use the &lt;code&gt;KillSwitch&lt;/code&gt; to kill all inputs, and then wait for processing to complete:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;for {
  ks &lt;- sharedKillSwitch(&quot;my-kill-switch&quot;)
  // We want to wait for `Done` during cancellation (below)
  awaitDone &lt;- startProcessor(ks)(system)
  // The magic we&apos;ve been waiting for
  _ &lt;- resourceFinalizer(
    for {
      // Kill all inputs first
      _ &lt;- IO(ks.shutdown())
      // Waits for processor to stop before proceeding;
      // Timeout is required, or this could be non-terminating
      _ &lt;- awaitDone.timeoutAndForget(10.seconds).attempt.void
    } yield ()
  )
} yield awaitDone
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we have this on our hands, we can easily describe a reusable app logic meant for executing Akka Stream graphs, which can take care of most things. And we base it on &lt;a href=&quot;https://typelevel.org/cats-effect/api/3.x/cats/effect/IOApp.html&quot;&gt;IOApp&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait ProcessorApp extends IOApp {
  /** Abstract method to implement... */
  def startProcessor(
    killSwitch: SharedKillSwitch
  )(implicit
    system: ActorSystem[_],
    dispatcher: Dispatcher[IO]
  ): Resource[IO, IO[Done]]

  override final def run(args: List[String]): IO[ExitCode] = {
    val startWithResources = for {
      d &lt;- Dispatcher.parallel[IO]
      system &lt;- startActorSystemTyped(
        systemName = &quot;my-actor-system&quot;,
        config = None,
        useIOExecutionContext = true,
        timeoutAwaitCatsEffect = 10.seconds,
        timeoutAwaitAkkaTermination = 10.seconds,
      )
      killSwitch &lt;- sharedKillSwitch(&quot;my-kill-switch&quot;)
      awaitDone &lt;- startProcessor(killSwitch)(system, d)
      _ &lt;- resourceFinalizer(
        for {
          // Kill all inputs
          _ &lt;- IO(killSwitch.shutdown())
          // Waits the for processor to stop before proceeding;
          // Timeout is required, or this could be non-terminating
          _ &lt;- awaitDone.timeoutAndForget(10.seconds).attempt.void
          _ &lt;- IO(logger.info(
            &quot;Awaited processor to stop, proceeding with shutdown...&quot;
          ))
        } yield ()
      )
    } yield awaitDone

    startWithResources.use { awaitDone =&gt;
      // Blocking on `awaitDone` makes sense, as the processor
      // could finish without the app receiving a termination signal
      awaitDone.as(ExitCode.Success)
    }
  }

  protected lazy val logger =
    LoggerFactory.getLogger(getClass)

  // It&apos;s a good idea to set a timeout on shutdown;
  // we need to take faulty cancellation logic into account
  override protected def runtimeConfig =
    super.runtimeConfig.copy(
      shutdownHookTimeout = 30.seconds
    )

  // We want to log uncaught exceptions in the thread pool,
  // via slf4j, otherwise they&apos;ll go to STDERR
  override protected def reportFailure(err: Throwable) =
    IO(logger.error(&quot;Unexpected error in thread-pool&quot;, err))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
&lt;strong&gt;WARNING:&lt;/strong&gt; when waiting for things to shut down, it’s important to have timeouts all over the place, to avoid non-terminating logic. The last thing you want is a zombie process that can’t shut down without a &lt;code&gt;kill -9&lt;/code&gt;, because that requires external monitoring and intervention (e.g., systemd, docker, monit), and you can’t trust that to be correctly configured. The less you trust, the more reliable your process will be.
&lt;/p&gt;

&lt;p&gt;As mentioned before, that &lt;code&gt;IO[Done]&lt;/code&gt; is the completion signal, which we’ll use in our main logic. This is easily accomplished via a &lt;a href=&quot;https://doc.akka.io/api/akka/2.6/akka/stream/scaladsl/Sink.html&quot;&gt;Sink&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import akka.stream.scaladsl.Sink

def ignoreSink[A]: Sink[A, IO[Done]] =
  Sink.ignore.mapMaterializedValue(f =&gt; IO.fromFuture(IO.pure(f)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can now give an actual &lt;code&gt;Main&lt;/code&gt; as an example. When running it, try killing it via SIGHUP/SIGINT/SIGTERM, see how it waits for processing to stop before shutting down resources:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object Main extends ProcessorApp {
  override def startProcessor(killSwitch: SharedKillSwitch)(implicit
    system: ActorSystem[_],
    dispatcher: Dispatcher[IO]
  ): Resource[IO, IO[Done]] = {
    Resource.eval {
      for {
        mySource &lt;- IO {
          val counter = new AtomicInteger(0)
          val tryPoll = IO {
            val cnt = counter.incrementAndGet()
            if (cnt % 2 == 0) Some(cnt) else None
          }
          poll0(tryPoll, 1.second)
            // Installing killSwitch on this source
            .via(killSwitch.flow)
        }
        awaitDone &lt;- IO {
          val sink = ignoreSink[Any]
          val graph = RunnableGraph.fromGraph(
            GraphDSL.createGraph(sink) { implicit builder =&gt; s =&gt;
              import GraphDSL.Implicits._

              val ints = builder.add(mySource)
              val logEvents = builder.add(
                Flow[Int].map(i =&gt; logger.info(s&quot;Received event: $i&quot;))
              )

              // w00t, here&apos;s our very complicated graph!
              ints ~&gt; logEvents ~&gt; s
              ClosedShape
            }
          )
          graph.run()
        }
      } yield awaitDone
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;full-example-scala-cli&quot;&gt;Full Example (Scala CLI)&lt;/h2&gt;

&lt;p&gt;The full example below can be executed directly via &lt;a href=&quot;https://scala-cli.virtuslab.org/&quot;&gt;Scala CLI&lt;/a&gt;. On macOS, you can install it with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;brew install Virtuslab/scala-cli/scala-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then you can run it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;scala-cli run ./sample.scala

# Or make the script executable; works due to the included &apos;shebang&apos;
# (https://en.wikipedia.org/wiki/Shebang_(Unix))
chmod +x ./sample.scala

# And then run it directly
./sample.scala
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Copy/paste this script into &lt;code&gt;sample.scala&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;#!/usr/bin/env -S scala-cli shebang -q

//&gt; using scala &quot;2.13.10&quot;
//&gt; using lib &quot;ch.qos.logback:logback-classic:1.4.6&quot;
//&gt; using lib &quot;co.fs2::fs2-core::3.6.1&quot;
//&gt; using lib &quot;co.fs2::fs2-reactive-streams::3.6.1&quot;
//&gt; using lib &quot;com.typesafe.akka::akka-actor-typed::2.6.20&quot;
//&gt; using lib &quot;com.typesafe.akka::akka-actor::2.6.20&quot;
//&gt; using lib &quot;com.typesafe.akka::akka-stream-typed::2.6.20&quot;
//&gt; using lib &quot;com.typesafe.akka::akka-stream::2.6.20&quot;
//&gt; using lib &quot;org.typelevel::cats-effect::3.4.9&quot;

import akka.actor.typed.ActorSystem
import akka.actor.typed.{ActorSystem =&gt; TypedActorSystem}
import akka.actor.{CoordinatedShutdown, ActorSystem =&gt; UntypedActorSystem}
import akka.stream.scaladsl.{Flow, GraphDSL, RunnableGraph}
import akka.stream.scaladsl.{Flow, Sink, Source}
import akka.stream.{ClosedShape, KillSwitches, SharedKillSwitch}
import akka.{Done, NotUsed}
import cats.effect.kernel.Resource
import cats.effect.std.Dispatcher
import cats.effect.{Deferred, ExitCode, IO, IOApp}
import cats.syntax.all._
import com.typesafe.config.Config
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicReference
import org.reactivestreams.{Publisher, Subscriber, Subscription}
import org.slf4j.LoggerFactory
import scala.annotation.tailrec
import scala.concurrent.duration._
import scala.concurrent.{Future, TimeoutException}

object Main extends ProcessorApp {
  import AkkaUtils._

  override def startProcessor(killSwitch: SharedKillSwitch)(implicit
    system: ActorSystem[_],
    dispatcher: Dispatcher[IO]
  ): Resource[IO, IO[Done]] = {
    Resource.eval {
      for {
        mySource &lt;- IO {
          val counter = new AtomicInteger(0)
          val tryPoll = IO {
            val cnt = counter.incrementAndGet()
            if (cnt % 2 == 0) Some(cnt) else None
          }
          poll0(tryPoll, 1.second)
            // Installing killSwitch on this source
            .via(killSwitch.flow)
        }
        awaitDone &lt;- IO {
          val sink = ignoreSink[Any]
          val graph = RunnableGraph.fromGraph(
            GraphDSL.createGraph(sink) { implicit builder =&gt; s =&gt;
              import GraphDSL.Implicits._

              val ints = builder.add(mySource)
              val logEvents = builder.add(
                Flow[Int].map(i =&gt; logger.info(s&quot;Received event: $i&quot;))
              )

              // w00t, here&apos;s our very complicated graph!
              ints ~&gt; logEvents ~&gt; s
              ClosedShape
            }
          )
          graph.run()
        }
      } yield awaitDone
    }
  }
}

trait ProcessorApp extends IOApp {
  import AkkaUtils._

  /** Abstract method to implement... */
  def startProcessor(killSwitch: SharedKillSwitch)(implicit
    system: ActorSystem[_],
    dispatcher: Dispatcher[IO]
  ): Resource[IO, IO[Done]]

  override final def run(args: List[String]): IO[ExitCode] = {
    val startWithResources = for {
      d &lt;- Dispatcher.parallel[IO]
      system &lt;- startActorSystemTyped(
        systemName = &quot;my-actor-system&quot;,
        config = None,
        useIOExecutionContext = true,
        timeoutAwaitCatsEffect = 10.seconds,
        timeoutAwaitAkkaTermination = 10.seconds,
      )
      killSwitch &lt;- sharedKillSwitch(&quot;my-kill-switch&quot;)
      awaitDone &lt;- startProcessor(killSwitch)(system, d)
      _ &lt;- resourceFinalizer(
        for {
          // Kill all inputs
          _ &lt;- IO(killSwitch.shutdown())
          // Waits the for processor to stop before proceeding;
          // Timeout is required, or this could be non-terminating
          _ &lt;- awaitDone.timeoutAndForget(10.seconds).attempt.void
          _ &lt;- IO(logger.info(
            &quot;Awaited processor to stop, proceeding with shutdown...&quot;
          ))
        } yield ()
      )
    } yield awaitDone

    startWithResources.use { awaitDone =&gt;
      // Blocking on `awaitDone` makes sense, as the processor
      // could finish without the app receiving a termination signal
      awaitDone.as(ExitCode.Success)
    }
  }

  protected lazy val logger =
    LoggerFactory.getLogger(getClass)

  // It&apos;s a good idea to set a timeout on shutdown;
  // we need to take faulty cancellation logic into account
  override protected def runtimeConfig =
    super.runtimeConfig.copy(
      shutdownHookTimeout = 30.seconds
    )

  // We want to log uncaught exceptions in the thread pool,
  // via slf4j, otherwise they&apos;ll go to STDERR
  override protected def reportFailure(err: Throwable) =
    IO(logger.error(&quot;Unexpected error in thread-pool&quot;, err))
}

object AkkaUtils {
  /** Starts an (untyped) Akka actor system in the
    * context of a Cats-Effect `Resource`, and integrating
    * with its cancellation abilities.
    *
    * HINT: for apps (in `main`), it&apos;s best if
    * `akka.coordinated-shutdown.exit-jvm` is set to `on`,
    * because Akka can decide to shutdown on its own. And
    * having this setting interacts well with Cats-Effect.
    *
    * @param systemName is the identifying name of the system.
    * @param config is an optional, parsed HOCON configuration;
    *        if None, then Akka will read its own, possibly
    *        from `application.conf`; this parameter is
    *        provided in order to control the source of
    *        the application&apos;s configuration.
    * @param useIOExecutionContext if true, then Cats-Effect&apos;s
    *        default thread-pool will get used by Akka, as well.
    *        This is needed in order to avoid having too many
    *        thread-pools.
    * @param timeoutAwaitCatsEffect is the maximum amount of time
    *        Akka&apos;s coordinated-shutdown is allowed to wait for
    *        Cats-Effect to finish. This is needed, as Cats-Effect
    *        could have a faulty stack of disposables, or because
    *        Akka could decide to shutdown on its own.
    * @param timeoutAwaitAkkaTermination is the maximum amount of
    *        time to wait for the actor system to terminate, after
    *        `terminate()` was called. We need the timeout, because
    *        `terminate()` proved to return a `Future` that never
    *        completes in certain scenarios (could be a bug, or a
    *        race condition).
    */
  def startActorSystemUntyped(
    systemName: String,
    config: Option[Config],
    useIOExecutionContext: Boolean,
    timeoutAwaitCatsEffect: Duration,
    timeoutAwaitAkkaTermination: Duration,
  ): Resource[IO, UntypedActorSystem] = {
    // Needed to turn IO into Future
    // https://typelevel.org/cats-effect/docs/std/dispatcher
    Dispatcher.parallel[IO](await = true).flatMap { dispatcher =&gt;
      Resource[IO, UntypedActorSystem](
        for {
          // Fishing IO&apos;s `ExecutionContext`
          ec &lt;- Option
            .when(useIOExecutionContext)(IO.executionContext)
            .sequence
          // For synchronizing Cats-Effect with Akka
          awaitCancel &lt;- Deferred[IO, Unit]
          // For awaiting termination, as `terminate()` is unreliable
          awaitTermination &lt;- Deferred[IO, Unit]
          logger = LoggerFactory.getLogger(getClass)
          system &lt;- IO {
            logger.info(&quot;Creating actor system...&quot;)
            val system = UntypedActorSystem(
              systemName.trim.replaceAll(&quot;\\W+&quot;, &quot;-&quot;),
              config = config,
              defaultExecutionContext = ec,
            )
            // Registering task in Akka&apos;s CoordinatedShutdown
            // that will wait for Cats-Effect to catch up,
            // blocking Akka from terminating, see:
            // https://doc.akka.io/docs/akka/current/coordinated-shutdown.html
            CoordinatedShutdown(system).addTask(
              CoordinatedShutdown.PhaseBeforeServiceUnbind,
              &quot;sync-with-cats-effect&quot;,
            ) { () =&gt;
              dispatcher.unsafeToFuture(
                // WARN: this may not happen, if Akka decided
                // to terminate, and `coordinated-shutdown.exit-jvm`
                // isn&apos;t `on`, hence the timeout:
                awaitCancel.get
                  .timeout(timeoutAwaitCatsEffect)
                  .recoverWith {
                    case ex: TimeoutException =&gt;
                      IO(logger.error(
                        &quot;Timed out waiting for Cats-Effect to catch up! &quot; +
                          &quot;This might indicate either a non-terminating &quot; +
                          &quot;cancellation logic, or a misconfiguration of Akka.&quot;
                      ))
                  }
                  .as(Done)
              )
            }
            CoordinatedShutdown(system).addTask(
              CoordinatedShutdown.PhaseActorSystemTerminate,
              &quot;signal-terminated&quot;,
            ) { () =&gt;
              dispatcher.unsafeToFuture(
                awaitTermination.complete(()).as(Done)
              )
            }
            system
          }
        } yield {
          val cancel =
            for {
              // Signals that Cats-Effect has caught up with Akka
              _ &lt;- awaitCancel.complete(())
              _ &lt;- IO(logger.warn(&quot;Shutting down actor system!&quot;))
              // Shuts down Akka, and waits for its termination
              // Here, system.terminate() returns a `Future[Terminated]`,
              // but we are ignoring it, as it could be non-terminating
              _ &lt;- IO(system.terminate())
              // Waiting for Akka to terminate via its CoordinatedShutdown
              _ &lt;- awaitTermination.get
              // WARN: `whenTerminated` is unreliable
              _ &lt;- IO.fromFuture(IO(system.whenTerminated)).void
                .timeoutAndForget(timeoutAwaitAkkaTermination)
                .handleErrorWith(_ =&gt;
                  IO(logger.warn(
                    &quot;Timed-out waiting for Akka to terminate!&quot;
                  ))
                )
            } yield ()
          (system, cancel)
        }
      )
    }
  }

  /** Starts a (typed) Akka actor system.
    *
    * @see [[startActorSystemUntyped]] for more details on params.
    */
  def startActorSystemTyped(
    systemName: String,
    config: Option[Config],
    useIOExecutionContext: Boolean,
    timeoutAwaitCatsEffect: FiniteDuration,
    timeoutAwaitAkkaTermination: FiniteDuration,
  ): Resource[IO, TypedActorSystem[Nothing]] =
    startActorSystemUntyped(
      systemName,
      config,
      useIOExecutionContext,
      timeoutAwaitCatsEffect,
      timeoutAwaitAkkaTermination,
    ).map { system =&gt;
      import akka.actor.typed.scaladsl.adapter.ClassicActorSystemOps
      system.toTyped
    }

  /** Converts a Cats-Effect `IO` into a Reactive Streams `Publisher`.
    *
    * [[https://github.com/reactive-streams/reactive-streams-jvm]]
    */
  def toPublisher[A](io: IO[A])(implicit d: Dispatcher[IO]): Publisher[A] =
    (s: Subscriber[_ &gt;: A]) =&gt; s.onSubscribe(new Subscription {
      type CancelToken = () =&gt; Future[Unit]

      private[this] val NOT_STARTED: Null = null
      private[this] val LOCKED = Left(false)
      private[this] val COMPLETED = Left(true)

      // State machine for managing the active subscription
      private[this] val ref =
        new AtomicReference[Either[Boolean, CancelToken]](NOT_STARTED)

      override def request(n: Long): Unit =
        ref.get() match {
          case NOT_STARTED =&gt;
            if (n &lt;= 0) {
              if (ref.compareAndSet(NOT_STARTED, COMPLETED))
                s.onError(new IllegalArgumentException(
                  &quot;non-positive request signals are illegal&quot;
                ))
            } else {
              if (ref.compareAndSet(NOT_STARTED, LOCKED)) {
                val cancelToken = d.unsafeRunCancelable(
                  io.attempt.flatMap { r =&gt;
                    IO {
                      r match {
                        case Right(value) =&gt;
                          s.onNext(value)
                          s.onComplete()
                        case Left(e) =&gt;
                          s.onError(e)
                      }
                      // GC purposes
                      ref.lazySet(COMPLETED)
                    }
                  }
                )
                // Race condition with lazySet(COMPLETED), but it&apos;s fine
                ref.set(Right(cancelToken))
              }
            }
          case Right(_) | Left(_) =&gt;
            // Already active, or completed
            ()
        }

      @tailrec
      override def cancel(): Unit =
        ref.get() match {
          case NOT_STARTED =&gt;
            if (!ref.compareAndSet(NOT_STARTED, COMPLETED))
              cancel() // retry
          case LOCKED =&gt;
            Thread.onSpinWait()
            cancel() // retry
          case Left(_) =&gt;
            ()
          case current@Right(token) =&gt;
            // No retries necessary; if state changes from Right(token),
            // it means that the stream is already completed or canceled
            if (ref.compareAndSet(current, COMPLETED))
              token()
        }
    })

  def toSource[A](io: IO[A])(implicit d: Dispatcher[IO]): Source[A, NotUsed] =
    Source.fromPublisher(toPublisher(io))

  def uncancelableIOToFlow[A, B](parallelism: Int)(
    f: A =&gt; IO[B]
  )(implicit d: Dispatcher[IO]): Flow[A, B, NotUsed] =
    Flow[A].mapAsync(parallelism)(a =&gt; d.unsafeToFuture(f(a)))


  def cancelableIOToFlow[A, B](parallelism: Int)(
    f: A =&gt; IO[B]
  )(implicit d: Dispatcher[IO]): Flow[A, B, NotUsed] =
    Flow[A].flatMapMerge(
      breadth = parallelism,
      a =&gt; toSource(f(a))
    )

  def poll0[A](
    tryPoll: IO[Option[A]],
    interval: FiniteDuration,
  )(implicit d: Dispatcher[IO]): Source[A, NotUsed] = {
    val logger = LoggerFactory.getLogger(getClass)
    Source.repeat(())
      .via(cancelableIOToFlow(1) { _ =&gt;
        tryPoll.handleError { e =&gt;
          logger.error(&quot;Unhandled error in poll&quot;, e)
          None
        }.flatTap {
          case None =&gt; IO.sleep(interval)
          case Some(_) =&gt; IO.unit
        }
      })
      .collect { case Some(a) =&gt; a }
  }

  def poll1[A](
    tryPoll: IO[Option[A]],
    interval: FiniteDuration,
  )(implicit d: Dispatcher[IO]): Source[A, NotUsed] = {
    val logger = LoggerFactory.getLogger(getClass)
    // Notice the `takeWhile`. This is a child stream that gets
    // composed via `flatMapConcat`.
    val drain =
    Source.repeat(())
      .via(uncancelableIOToFlow(1) { _ =&gt;
        tryPoll.handleError { e =&gt;
          logger.error(&quot;Unhandled error in poll&quot;, e)
          None
        }
      })
      .takeWhile(_.nonEmpty)
      .collect { case Some(a) =&gt; a }

    Source
      .tick(initialDelay = Duration.Zero, interval = interval, tick = ())
      .flatMapConcat(_ =&gt; drain)
      .mapMaterializedValue(_ =&gt; NotUsed)
  }

  def poll2[A](
    tryPoll: IO[Option[A]],
    interval: FiniteDuration,
  )(implicit d: Dispatcher[IO]): Source[A, NotUsed] = {
    val logger = LoggerFactory.getLogger(getClass)
    val repeatedTask = tryPoll.handleError { e =&gt;
      logger.error(&quot;Unhandled error in poll&quot;, e)
      None
    }.flatTap {
      case None =&gt; IO.sleep(interval)
      case Some(_) =&gt; IO.unit
    }

    val stream = fs2.Stream
      .repeatEval(repeatedTask)
      .collect { case Some(a) =&gt; a }

    import fs2.interop.reactivestreams._
    Source.fromPublisher(new StreamUnicastPublisher(stream, d))
  }

  def ignoreSink[A]: Sink[A, IO[Done]] =
    Sink.ignore.mapMaterializedValue(f =&gt; IO.fromFuture(IO.pure(f)))

  def sharedKillSwitch(name: String): Resource[IO, SharedKillSwitch] =
    Resource(IO {
      val ks = KillSwitches.shared(name)
      (ks, IO(ks.shutdown()))
    })

  def resourceFinalizer(effect: IO[Unit]): Resource[IO, Unit] =
    Resource(IO {
      ((), effect)
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/04/17/integrating-akka-with-cats-effect-3/?pk_campaign=rss&quot;&gt;Integrating Akka with Cats-Effect 3&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 17 Apr 2023 08:05:29 +0000</pubDate>
  <dc:modified>Thu, 25 May 2023 07:30:03 +0000</dc:modified>
  <atom:modified>Thu, 25 May 2023 07:30:03 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/04/17/integrating-akka-with-cats-effect-3/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/04/17/integrating-akka-with-cats-effect-3/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Cats Effect</category>
  <category>FP</category>
  <category>Programming</category>
  <category>Scala</category>
  </item>


<item>
  <title>Server Monitoring with Monit</title>
  <description>I self-host my blog, other websites, Matomo, Mastodon, etc. I love self-hosting. But I need monitoring, to be alerted when things go wrong, as my setup is getting more and more complex. So, I recently asked for help online, being in need of a monitoring system for my VPS, as I need simple, common-sense health alerts. I got a recommendation for M/Monit, which seems to work well. This article shows my configuration.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2023/01/17/server-monitoring-with-monit/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2023-monit-panel.png?202603060940&quot; alt=&quot;&quot; width=&quot;1984&quot; height=&quot;928&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;A screenshot of my browser window, showing the 3 monitors that I configured in Monit, all green-lit, indicating that everything is fine.
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I self-host my blog, other websites, &lt;a href=&quot;https://matomo.org/&quot;&gt;Matomo&lt;/a&gt;, &lt;a href=&quot;https://joinmastodon.org/&quot;&gt;Mastodon&lt;/a&gt;, etc. I love self-hosting. But I need monitoring, to be alerted when things go wrong, as my setup is getting more and more complex. So, I recently asked for help online, being in need of a monitoring system for my VPS, as I need simple, common-sense health alerts. I got a recommendation for &lt;a href=&quot;https://mmonit.com/&quot;&gt;M/Monit&lt;/a&gt;, which seems to work well. This article shows my configuration.
&lt;/p&gt;

&lt;p&gt;Even though I use Docker, I decided to install it at the OS level. Given I use Ubuntu on my server, this is as simple as:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;apt install monit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Its configuration (in &lt;code&gt;/etc/monit/conf.d/my.conf&lt;/code&gt;) looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-conf&quot;&gt;# Monit configuration

## ----
## Configures server port (proxied via Nginx)
set httpd
    port 2812
        read-only
    unixsocket /run/monit.socket
    allow localhost
    allow monit.alexn.org
    signature disable

## Configures email alerts
set mailserver localhost
set alert user@domain.com not on { instance, action } with reminder on 500 cycles

## Monitors system load
check system $HOST
    if loadavg (1min) per core &gt; 2 for 5 cycles then alert
    if loadavg (5min) per core &gt; 1.5 for 10 cycles then alert
    if cpu usage &gt; 95% for 10 cycles then alert
    if memory usage &gt; 90% then alert
    if swap usage &gt; 25% then alert

## Monitors file-system
check filesystem rootfs with path /
    if space usage &gt; 80% for 5 times within 15 cycles then alert
    if inode usage &gt; 80% for 5 times within 15 cycles then alert

## Monitors Docker instances
check program docker-health with path /opt/bin/vm-docker-check-health
    with timeout 10 seconds
    if status != 0 then alert
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;My hostname is &lt;code&gt;monit.alexn.org&lt;/code&gt; for exposing the HTTP interfaces. I decided for a read-only interface. It’s less to worry about, and I don’t need a remote control. I use Nginx as a proxy:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-conf&quot;&gt;server {
    server_name monit.alexn.org;
    listen   80;
    listen   [::]:80;
    access_log /var/log/nginx/monit.alexn.org.log combined;

    location / {
        rewrite ^(.*)$ https://monit.alexn.org$1 permanent;
    }
}

server {
    server_name monit.alexn.org;
    listen 443 ssl;
    listen [::]:443 ssl;

    access_log /var/log/nginx/monit.alexn.org.log combined;

    # https://ssl-config.mozilla.org/#server=nginx&amp;version=1.17.7&amp;config=intermediate&amp;openssl=1.1.1k&amp;guideline=5.6
    ssl_certificate /etc/letsencrypt/live/alexn.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/alexn.org/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/alexn.org/fullchain.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;  # about 40000 sessions
    ssl_session_tickets off;
    ssl_dhparam /etc/nginx/certs/dh2048.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    add_header Strict-Transport-Security &quot;max-age=63072000; includeSubdomains; preload&quot;;
    ssl_stapling on;
    ssl_stapling_verify on;

    location / {
        root   /var/www/monit.alexn.org;
        auth_basic &quot;Monit&quot;;
        auth_basic_user_file /etc/secrets/auth/monit-htpasswd;

        proxy_pass http://0.0.0.0:2812;
        proxy_set_header Host $host;
        proxy_connect_timeout 300;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Generating a “htpasswd” file can be accomplished with this command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;htpasswd -B -c etc/secrets/auth/monit-htpasswd yourUserName
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That configuration alerts me on 3 things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The system’s load (CPU, RAM, Swap);&lt;/li&gt;
  &lt;li&gt;The available disk space;&lt;/li&gt;
  &lt;li&gt;The health of my Docker containers;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For checking the Docker containers, I have a simple script that’s configured above to be executed periodically:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;
#!/usr/bin/env bash

UNHEALTHY_IDS=&quot;$(docker ps -q \
    -f health=&quot;none&quot; \
    -f health=&quot;unhealthy&quot; \
    -f status=&quot;exited&quot; \
    -f status=&quot;dead&quot; \
    -f status=&quot;paused&quot; \
    )&quot;

if [[ -z &quot;$UNHEALTHY_IDS&quot; ]]; then
    docker ps --format &quot;table {{.Names}}\t{{.Status}}&quot;
    exit 0
fi

echo &gt;&amp;2
echo &quot;WARN: Unhealthy docker instances!&quot; &gt;&amp;2
echo &quot;---------------------------------&quot; &gt;&amp;2
docker ps --format &quot;table {{.Names}}\t{{.State}}\t{{.Status}}&quot; \
    -f health=&quot;none&quot; \
    -f health=&quot;unhealthy&quot; \
    -f status=&quot;exited&quot; \
    -f status=&quot;dead&quot; \
    -f status=&quot;paused&quot; &gt;&amp;2
exit 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
  WARN: you need an email server configured for receiving those alerts!
&lt;/p&gt;

&lt;p&gt;You need to configure Monit with an email server. I just use my &lt;code&gt;localhost&lt;/code&gt; because I can configure &lt;code&gt;postfix&lt;/code&gt; to use my Fastmail account as a relay. See my &lt;a href=&quot;https://alexn.org/wiki/ubuntu-server/&quot;&gt;Ubuntu wiki page&lt;/a&gt; for details on how to do that.&lt;/p&gt;

&lt;p&gt;Now I can sleep well at night 🥱&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/01/17/server-monitoring-with-monit/?pk_campaign=rss&quot;&gt;Server Monitoring with Monit&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 17 Jan 2023 11:16:12 +0000</pubDate>
  <dc:modified>Sun, 29 Sep 2024 09:22:06 +0000</dc:modified>
  <atom:modified>Sun, 29 Sep 2024 09:22:06 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/01/17/server-monitoring-with-monit/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/01/17/server-monitoring-with-monit/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Docker</category>
  <category>Self Hosting</category>
  <category>Shell</category>
  <category>Snippet</category>
  </item>


<item>
  <title>#DeleteTwitter</title>
  <description>Friday the 13th just passed 😳 and what a great day it was to finally leave Twitter. It’s been a fun ride, I found my programming community on it, I’ve learned a lot, but those days are over 😞</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  Friday the 13th just passed 😳 and what a great day it was to finally leave Twitter. It’s been a fun ride, I found my programming community on it, I’ve learned a lot, but those days are over 😞
&lt;/p&gt;

&lt;p&gt;I’m a software developer. I don’t know what Twitter’s future is, it might be a bright one, but the problem for me is that Twitter is no longer the place where I can go to learn about programming. Or to find my peers. Twitter is no longer the place you go to talk of your passions, fruitful discussions being few and far between. Twitter is no longer fun, but rather it’s where you go to get your daily fix of unhinged political drama, and then worry that the world is going to shit.&lt;/p&gt;

&lt;p&gt;I had about 6000 followers. Not much, but enough to keep me hooked. However, from my experience, I can tell you that engagement for posts has been going down, for anything but politics. I noticed it not just on my posts, but on the posts of those I followed as well. Having followers feels like an investment, which is one of the ways social networks keep people hooked, but it’s a meaningless number, a proxy for actual reach. We want to learn, to make connections, to promote our work, to be entertained, but these social networks have a real cost, and we have to keep asking ourselves if they help us in achieving our goals.&lt;/p&gt;

&lt;p&gt;These days, Twitter may be more alive than ever, but many of the people I care about are no longer active on Twitter. As far as I’m concerned, the elves have left Middle Earth, taking their magic with them, and I doubt that the magic can come back.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/2023-passing-of-elves.jpg&quot; alt=&quot;&quot; width=&quot;1258&quot; height=&quot;635&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    Elves leaving Middle Earth (&lt;a href=&quot;https://www.deviantart.com/aelinlaerfineart/art/The-Passing-of-the-elves-royal-procession-482093777&quot;&gt;source&lt;/a&gt;).
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Last year, I &lt;a href=&quot;https://alexn.org/blog/2022/09/12/delete-facebook/&quot;&gt;deleted my Facebook account&lt;/a&gt;, too. These days you can find me on &lt;a href=&quot;https://mastodon.social/@alexelcu&quot;&gt;the Fediverse / Mastodon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The issue with centralized social networks is that their business model is ads-driven, which means they have to steal your attention. The more you engage with their service, the more ads you consume. This creates a perverse incentive, as the timeline of these social networks was optimized for stealing your attention. And it turns out that outrage generates a lot of attention, and engagement.&lt;/p&gt;

&lt;p&gt;When you log into Twitter, you get bombarded with political opinions that are counterproductive. Even if you judiciously block, even if you switch to the “latest tweets” timeline, it doesn’t matter, as your connections also get fed outrage, and start sharing. Whenever I see another flame war on Twitter, it’s always another US tantrum, and I have to wait for a couple of days for it to cool off. And US tantrums are digestible because at least I’m not living in the US, whereas Facebook was giving me local news of gruesome local tragedies, many times as “promoted” posts.&lt;/p&gt;

&lt;p&gt;People want more content moderation on these platform, this being seemingly in contradiction with freedom of speech. But we are missing the forest from the trees, I think. The problem with these centralized “public squares” is that their algorithms are now adversarial, shoving speech we don’t want in our faces for profit.&lt;/p&gt;

&lt;p&gt;I’m actually one of those obnoxious free-speech absolutists, and being a European liberal that believes in capitalism, I consider myself to be aligned more with right-wing values. What you’re witnessing with Musk’s supporters aren’t values rooted in classic liberalism. They aren’t concerned with free speech, given the cheering of journalists or left-wing accounts being banned. This is just tribalism. And I’ve got better things to do than participate in a platform whose new leadership has a mission of “owning the libs”.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, Twitter’s leadership is free to spread election or vaccine misinformation, or to promote hatred against LGBT+, but the beauty of freedom and capitalism is that this works both ways … we are free to stop using their service, and vote with our wallet and/or attention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And I can’t in good faith continue to contribute to this platform.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m not here to tell you what to do, but in case you feel as I do and need some motivation, I recommend either one of these books:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.goodreads.com/book/show/40672036-digital-minimalism&quot;&gt;Digital Minimalism: Choosing a Focused Life in a Noisy World&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.goodreads.com/book/show/37830765-ten-arguments-for-deleting-your-social-media-accounts-right-now&quot;&gt;Ten arguments for deleting your social media accounts right now&lt;/a&gt;;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Goodbye, Twitter, and thanks for all the fish 👋&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2023/01/15/delete-twitter/?pk_campaign=rss&quot;&gt;#DeleteTwitter&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 15 Jan 2023 08:30:29 +0000</pubDate>
  <dc:modified>Mon, 25 Sep 2023 14:57:08 +0000</dc:modified>
  <atom:modified>Mon, 25 Sep 2023 14:57:08 +0000</atom:modified>
  <link>https://alexn.org/blog/2023/01/15/delete-twitter/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2023/01/15/delete-twitter/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Personal</category>
  <category>Politics</category>
  </item>


<item>
  <title>Personal Server Backups</title>
  <description>Cloud hosting services like Linode or DigitalOcean offer backup services for your VPS. Save your money, you don’t need it. Here’s how to backup your data safely, and with no extra costs…</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/12/02/personal-server-backups/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-backup-vps.png?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;1000&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
Cloud hosting services like Linode or DigitalOcean offer backup services for your VPS. Save your money, you don’t need it. Here’s how to backup your data safely, and with no extra costs…
&lt;/p&gt;

&lt;p&gt;The plan, for your inspiration:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Place all your server configuration in a personal git repository;&lt;/li&gt;
  &lt;li&gt;Backup your data via cron jobs, with the help of &lt;a href=&quot;https://rclone.org/&quot;&gt;rclone&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;Test how reliable recovery is every time you update your server to a major Linux distribution version;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;server-configuration&quot;&gt;Server configuration&lt;/h2&gt;

&lt;p&gt;On my server, I use the latest LTS of Ubuntu Linux, since it’s what I’ve grown accustomed to. I have a personal GitHub repository where I store the server’s configuration. The bulk of it is:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A &lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;docker-compose.yaml&lt;/a&gt; file;&lt;/li&gt;
  &lt;li&gt;Nginx configurations for my domains;&lt;/li&gt;
  &lt;li&gt;Scripts that need to execute periodically via &lt;code&gt;cron.d&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;A &lt;code&gt;setup.sh&lt;/code&gt; script that configures a server from scratch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One of these days I’ll try &lt;a href=&quot;https://nixos.org/&quot;&gt;NixOS&lt;/a&gt;, as a lot of people love it, and it’s designed for precisely this use-case: to have a reproducible environment described by configuration kept in a repository.&lt;/p&gt;

&lt;p&gt;Start small, and think big. Can you reconfigure a server from scratch in less than an hour? If not, why not?&lt;/p&gt;

&lt;h2 id=&quot;rclone-backups-via-cron-jobs&quot;&gt;Rclone backups via cron jobs&lt;/h2&gt;

&lt;p&gt;You can use Dropbox for storing your backups, you can use Amazon’s S3, or as a pretty cheap alternative, you can use &lt;a href=&quot;https://www.backblaze.com/cloud-storage&quot;&gt;Backblaze B2&lt;/a&gt;. I use Dropbox, since I’m paying for a Plus account anyway, and I have a lot of unused space. Dropbox also keeps about 1-month worth of &lt;a href=&quot;https://help.dropbox.com/delete-restore/version-history-overview&quot;&gt;version history&lt;/a&gt;, so it’s decent.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://rclone.org/&quot;&gt;Rclone&lt;/a&gt; utility supports a lot of backends, including the aforementioned ones.&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
&lt;strong&gt;WARNING:&lt;/strong&gt; when configuring &lt;code&gt;rclone&lt;/code&gt; on your server, you need to think about security. If you have important personal data in your cloud storage, you don’t want to give attackers access to it. Which is why a separation would be better. I used Dropbox because I could set it up such that access is restricted to an “app folder” (&lt;a href=&quot;https://www.dropbox.com/developers/reference/getting-started&quot;&gt;see their docs&lt;/a&gt; for configuring your own “app”). If you can’t do that, it would be safer to create another account (e.g., Backblaze B2), and give access to buckets that are only used for these backups.
&lt;/p&gt;

&lt;p&gt;The “remote” that I configure (via &lt;code&gt;rclone config&lt;/code&gt;) has the name &lt;code&gt;backup&lt;/code&gt;, which are then used in the following scripts.&lt;/p&gt;

&lt;p&gt;For your inspiration, as a sample, here’s the script for backing up my MariaDB / MySQL database (named &lt;code&gt;vm-backup-mysql&lt;/code&gt;). Note that the database is in a Docker container, and we also need a &lt;code&gt;mysql.env&lt;/code&gt; file somewhere with the root password:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;#!/usr/bin/env bash

set -e

DIR=&quot;$(dirname &quot;$0&quot;)&quot;
set -o allexport; source &quot;$DIR/../docker/envs/mysql.env&quot;; set +o allexport

FILENAME=&quot;mysql-$(date +&quot;%Y-%m&quot;).sql.gz&quot;
FILEPATH=&quot;/var/lib/my-backups/$FILENAME&quot;

mkdir -p /var/lib/my-backups

docker exec -i mariadb /bin/mysqldump -u root \
  &quot;-p$MYSQL_ROOT_PASSWORD&quot; \
  --lock-tables=false \
  --all-databases | gzip &gt; &quot;$FILEPATH&quot;

if [ -f &quot;$FILEPATH&quot; ]; then
  rclone copy &quot;$FILEPATH&quot; &quot;backup:MySQL/&quot;
fi

rm -f /var/lib/my-backups/mysql-*.sql.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s the script for backing up the data for my &lt;a href=&quot;https://github.com/posativ/isso/&quot;&gt;Isso comments service&lt;/a&gt;, named &lt;code&gt;vm-backup-isso&lt;/code&gt;. This script is backing up the configuration (from &lt;code&gt;/etc/isso&lt;/code&gt;) and the SQLite database (from &lt;code&gt;/var/lib/isso&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;#!/usr/bin/env bash

set -e

FILENAME1=&quot;isso-db-$(date +&quot;%Y-%m&quot;).tar.gz&quot;
FILEPATH1=&quot;/var/lib/my-backups/$FILENAME1&quot;
FILENAME2=&quot;isso-cfg.tar.gz&quot;
FILEPATH2=&quot;/var/lib/my-backups/$FILENAME2&quot;

mkdir -p /var/lib/my-backups
cd /var/lib/my-backups || exit 1

tar cvzf ./&quot;$FILENAME1&quot; -C / var/lib/isso
tar cvzf ./&quot;$FILENAME2&quot; -C / etc/isso

if [ -f &quot;$FILEPATH1&quot; ]; then
  rclone copy &quot;$FILEPATH1&quot; &quot;backup:Isso/&quot;
fi

if [ -f &quot;$FILEPATH2&quot; ]; then
  rclone copy &quot;$FILEPATH2&quot; &quot;backup:Isso/&quot;
fi

rm -f /var/lib/my-backups/isso-*.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s the script for backing up my &lt;a href=&quot;https://freshrss.org/&quot;&gt;FreshRSS&lt;/a&gt; &lt;a href=&quot;https://en.wikipedia.org//wiki/OPML&quot;&gt;OPML file&lt;/a&gt;, such that I never lose my blog subscriptions 🙂&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;#!/bin/bash

set -e

FILENAME=&quot;freshrss-$(date +&quot;%Y-%m&quot;).opml.xml.gz&quot;
FILEPATH=&quot;/var/lib/my-backups/$FILENAME&quot;

if [ $(docker inspect -f &apos;{{.State.Running}}&apos; freshrss) ]; then
  echo &quot;[$(date +&quot;%Y-%m-%d %H:%M:%S%z&quot;)] Generating $FILEPATH&quot;
  docker exec -t freshrss /bin/bash -c -i &quot;/var/www/FreshRSS/cli/export-opml-for-user.php --user alexandru 2&gt;/dev/null&quot; | gzip &gt;&quot;$FILEPATH&quot;

  if [ -f &quot;$FILEPATH&quot; ]; then
    rclone copy &quot;$FILEPATH&quot; &quot;backup:FreshRSS/&quot;
  fi
fi

rm -f /var/lib/my-backups/freshrss-*.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, here’s my &lt;a href=&quot;https://en.wikipedia.org/wiki/Cron&quot;&gt;cron setup&lt;/a&gt;, in a file named &lt;code&gt;/etc/cron.d/vm-cron&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;MAILTO=cron-errors@my.address.com

# ----------------
# Backups

10 */6 * * * root  cronic /opt/vm/bin/vm-backup-mysql
20 */6 * * * root  cronic /opt/vm/bin/vm-backup-isso
30 */6 * * * root  cronic /opt/vm/bin/vm-backup-freshrss
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, backups are running on my VPS every 6 hours. I have more fine-grained backups than what services like Linode or DigitalOcean can provide.&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
&lt;strong&gt;WARNING:&lt;/strong&gt; when doing backups, it’s best if you have a system alterting you when something goes wrong, like when &lt;code&gt;rclone&lt;/code&gt; can no longer connect to your remote. Which is why sending emails on error is a good practice.
&lt;/p&gt;

&lt;p&gt;My server is configured to send emails via Fastmail, as an external &lt;code&gt;relayhost&lt;/code&gt;. See &lt;a href=&quot;https://alexn.org/wiki/ubuntu-server/#configure-sending-emails-via-fastmail-or-another-smtp-server&quot;&gt;my wiki entry&lt;/a&gt; for details on the setup. In the cron setup above, I’m using &lt;a href=&quot;https://habilis.net/cronic/&quot;&gt;cronic&lt;/a&gt;, a small utility that silences the output of those scripts, only outputting to stdout and stderr if the script finishes with an error code. The effect is that the cron service will only send emails when errors happen.&lt;/p&gt;

&lt;h2 id=&quot;test-your-backups&quot;&gt;Test your backups&lt;/h2&gt;

&lt;p&gt;You won’t know that you have working backups, unless you test them periodically.&lt;/p&gt;

&lt;p&gt;For me this happens naturally, because I’m staying on Ubuntu LTS releases, and frankly updating major Ubuntu versions is best done from scratch. And I also keep resizing my VPS. This means that I frequently recreate my VPS from scratch.&lt;/p&gt;

&lt;p&gt;Nowadays, I can do it in about 1 hour, with no access to the previous VPS setup, as everything I need is already in GitHub or in Dropbox. The more you automate, and the more you test that automation, the more reliable it is when you’ll actually need it.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/12/02/personal-server-backups/?pk_campaign=rss&quot;&gt;Personal Server Backups&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 02 Dec 2022 17:56:39 +0000</pubDate>
  <dc:modified>Sun, 29 Sep 2024 09:22:03 +0000</dc:modified>
  <atom:modified>Sun, 29 Sep 2024 09:22:03 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/12/02/personal-server-backups/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/12/02/personal-server-backups/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Self Hosting</category>
  <category>Server</category>
  <category>Shell</category>
  <category>Web</category>
  </item>


<item>
  <title>Custom Jackson JSON serializer/deserializer from Circe</title>
  <description>Snippet for when you’re using Circe and want to define custom Jackson serializers/deserializers from Circe’s codec definitions.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
Snippet for when you’re using &lt;a href=&quot;https://github.com/circe/circe&quot;&gt;Circe&lt;/a&gt; and want to define custom &lt;a href=&quot;https://github.com/FasterXML/jackson&quot;&gt;Jackson&lt;/a&gt; serializers/deserializers from Circe’s codec definitions.
&lt;/p&gt;

&lt;p&gt;It’s not very efficient, as deserialization seems to parse the JSON in both Jackson and Circe, but I don’t have better ideas.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import com.fasterxml.jackson.core.{ JsonGenerator, JsonParser, TreeNode }
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import com.fasterxml.jackson.databind.{ DeserializationContext, SerializerProvider }
import io.circe.parser.decode
import io.circe.syntax._
import io.circe.{ Decoder, Encoder }
import scala.reflect.ClassTag

class JacksonSerializerFromCirce[A: ClassTag: Encoder]
extends StdSerializer[A](
    implicitly[ClassTag[A]].runtimeClass.asInstanceOf[Class[A]]
  ) {
  override def serialize(
    value: A,
    gen: JsonGenerator,
    provider: SerializerProvider
  ): Unit = {
    val json = value.asJson.noSpaces
    gen.writeRawValue(json)
  }
}

class JacksonDeserializerFromCirce[A: ClassTag: Decoder]
  extends StdDeserializer[A](
    implicitly[ClassTag[A]].runtimeClass.asInstanceOf[Class[A]]
  ) {
  override def deserialize(
    p: JsonParser,
    ctxt: DeserializationContext
  ): A = {
    decode[A](p.readValueAsTree[TreeNode]().toString) match {
      case Right(a) =&gt; a
      case Left(e) =&gt; throw e
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import io.circe.Codec
import io.circe.generic.semiauto.deriveCodec

@JsonSerialize(using = classOf[Sample.Serializer])
@JsonDeserialize(using = classOf[Sample.Deserializer])
final case class Sample(
  name: String,
  isActive: Boolean
)

object Sample {
  implicit val codec: Codec[Sample] =
    deriveCodec

  class Serializer
    extends JacksonSerializerFromCirce[Sample]
  class Deserializer
    extends JacksonDeserializerFromCirce[Sample]
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/11/29/custom-jackson-json-serializer-deserializer-from-circe/?pk_campaign=rss&quot;&gt;Custom Jackson JSON serializer/deserializer from Circe&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 29 Nov 2022 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2022/11/29/custom-jackson-json-serializer-deserializer-from-circe/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/11/29/custom-jackson-json-serializer-deserializer-from-circe/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>I ❤️ Scala&#39;s Community</title>
  <description>I find Scala’s community to be really nice, welcoming, warm, and productive. I am not talking just of the Typelevel sub-community, which is awesome, but of the whole Scala community. The whole thing.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/10/28/love-scala-community/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
I find Scala’s community to be really nice, welcoming, warm, and productive. I am not talking just of the &lt;a href=&quot;https://typelevel.org/&quot;&gt;Typelevel&lt;/a&gt; sub-community, which is awesome, but of the whole Scala community. The whole thing.
&lt;/p&gt;

&lt;p&gt;This may seem odd, because we had, and we may still experience conflicts, that I could personally live without. But in big and heterogeneous groups of people that collaborate, some inevitably get angry with each other.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://www.scala-lang.org/community/&quot;&gt;official community channels&lt;/a&gt; are very civilized, friendly, and welcoming. There, you can easily find very knowledgeable engineers and scientists, willing to help, without having to feel shame for the questions you ask.&lt;/p&gt;

&lt;p&gt;This is no accident. Community volunteers, Scala Center, former and previous stewards of the language (Lightbend employees, etc.), worked hard to make these channels nice. I remember my first interaction with Scala, it happened on IRC, on the now defunct Freenode network, where I presented a small implementation, and I immediately got an insult. Fortunately, those days are long gone.&lt;/p&gt;

&lt;p&gt;Programmers can be quite vicious. I don’t really understand why. When I got into programming, the biggest joys I experienced in high-school was to implement stuff and then show it off to others. This is how all beginners start. But then we tend to become arrogant, and cynical, forgetting from where we started.&lt;/p&gt;

&lt;p&gt;But back to Scala — even the online channels that are sometimes categorized as dumpster fires, are actually nice. For example, Reddit’s &lt;code&gt;/r/scala&lt;/code&gt;. If you don’t believe me, venture yourself into the subreddits of other communities, try asking for help, or having opinions™️, see how that works out.&lt;/p&gt;

&lt;p&gt;The Scala community is freakishly productive, given its size. It’s quite spectacular how, in &lt;a href=&quot;https://madnight.github.io/githut/#/pull_requests/2022/3&quot;&gt;GitHub rankings&lt;/a&gt;, it’s in the same league as several “10 pound gorillas”. And I sometimes complain about the &lt;a href=&quot;https://en.wikipedia.org/wiki/There&apos;s_more_than_one_way_to_do_it&quot;&gt;TIMTOWTDI&lt;/a&gt;, but it’s a direct result of the fact that competing ideas aren’t being shut down, but rather actively worked on by people with a passion to follow.&lt;/p&gt;

&lt;p&gt;This talent, knowledge, and warmth gives me faith in the future of the Scala language.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/10/28/love-scala-community/?pk_campaign=rss&quot;&gt;I ❤️ Scala&apos;s Community&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 28 Oct 2022 07:21:54 +0000</pubDate>
  <dc:modified>Fri, 28 Oct 2022 16:11:49 +0000</dc:modified>
  <atom:modified>Fri, 28 Oct 2022 16:11:49 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/10/28/love-scala-community/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/10/28/love-scala-community/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  </item>


<item>
  <title>Immutable Collections should be Your Default</title>
  <description>Mutable collection types should only be used strategically, with purpose, otherwise for correctness/safety purposes, the default should be immutable collection types, aka persistent data structures.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
Mutable collection types should only be used strategically, with purpose, otherwise for correctness/safety purposes, the default should be immutable collection types, aka &lt;a href=&quot;https://en.wikipedia.org/wiki/Persistent_data_structure&quot;&gt;persistent data structures&lt;/a&gt;.
&lt;/p&gt;

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

&lt;p&gt;For working with immutable collections:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Java’s standard library has utilities for &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/core/creating-immutable-lists-sets-and-maps.html&quot;&gt;creating unmodifiable copies&lt;/a&gt;, which are better than nothing;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.vavr.io/&quot;&gt;VAVR&lt;/a&gt; works well for Java;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/google/guava/wiki/ImmutableCollectionsExplained&quot;&gt;Guava&lt;/a&gt; is also a standard recommendation for Java;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/Kotlin/kotlinx.collections.immutable&quot;&gt;kotlinx.collections.immutable&lt;/a&gt; works well for Kotlin;&lt;/li&gt;
  &lt;li&gt;In Scala and Clojure, the default collection implementations are immutable by default, a wise design choice for JVM languages that provide their own (maximal) standard library;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/immutable-js/immutable-js/&quot;&gt;Immutable.js&lt;/a&gt; works well for JavaScript;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Immutable collections are much like &lt;code&gt;String&lt;/code&gt;. You don’t need &lt;code&gt;String&lt;/code&gt; to be mutable, whenever you build a bigger &lt;code&gt;String&lt;/code&gt;, you just do &lt;code&gt;ref += nextLine&lt;/code&gt; or you work with a &lt;code&gt;StringBuilder&lt;/code&gt;. And &lt;code&gt;String&lt;/code&gt; being immutable helps with sharing it safely across threads, or with using it in &lt;code&gt;HashMap&lt;/code&gt; implementations. Java’s Strings are surprisingly sane, compared with other implementations, people should take note. So why shouldn’t collections also be immutable by default, just like &lt;code&gt;String&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Mutable collections may have a performance advantage, even when used in a concurrent context. Java’s &lt;code&gt;ConcurrentLinkedQueue&lt;/code&gt; for example will perform better than an &lt;code&gt;AtomicReference(immutable.Queue())&lt;/code&gt;. Or an &lt;code&gt;ArrayList&lt;/code&gt; will perform better than an immutable/persistent &lt;code&gt;List&lt;/code&gt; (which is actually a stack). But performance optimizations are often unnecessary, and safety should be the default.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Performance is a currency&lt;/em&gt;, and whenever you can afford it (most of the time), what better way to spend such a currency than on correctness?&lt;/p&gt;

&lt;h2 id=&quot;sample-simple-sharing&quot;&gt;Sample: Simple Sharing&lt;/h2&gt;

&lt;p&gt;Sharing of mutable data structures is bad, and demonstrating it is easy:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Java code

record class ProjectConfig(
  List&lt;String&gt; availableTimezones,
  //...
) {}

//... later ...
config.availableTimezones().add(&quot;Mars/SpaceXFirst&quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is bad because it modifies that configuration for all call sites. Even if a project-wide configuration change was your intent, this is a pretty bad way to model configuration updates in your code, because then your components need to be notified of such configuration changes. For the call-site, this is bad too, because the user doesn’t really know if doing this is safe or not. The users may end up thinking that they received their own copy, so this is safe.&lt;/p&gt;

&lt;p&gt;And note, it’s acceptable to use Java’s way of handling this — by wrapping that list into something that throws an &lt;code&gt;UnsupportedOperationException&lt;/code&gt; when you try to &lt;code&gt;add()&lt;/code&gt; or &lt;code&gt;remove()&lt;/code&gt;. But it would be even better if you used some type that makes the immutability clear, e.g., &lt;code&gt;ImmutableList&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;sample-concurrent-data-structures&quot;&gt;Sample: Concurrent Data Structures&lt;/h2&gt;

&lt;p&gt;Just this week I stumbled on the following Java declaration:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Java code
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

//...
Map&lt;String, List&lt;String&gt;&gt; dns = new ConcurrentHashMap&lt;&gt;();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should immediately notice that something is wrong, because the type of &lt;code&gt;ConcurrentHashMap&lt;/code&gt; is hidden, which means that its methods specifically meant for dealing with concurrent updates aren’t used. Then, I stumbled on gems like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// All unsynchronized of course
var value = &quot;another value&quot;
var list = dns.get(&quot;key&quot;);
if (list != null) {
  list.add(value);
} else {
  list = new ArrayList&lt;&gt;();
  list.add(value);
  dns.put(&quot;key&quot;, newList);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I mean, yikes! The developer that wrote this code felt that multi-threading synchronization was needed. But rubbing some &lt;code&gt;ConcurrentHashMap&lt;/code&gt; on your code won’t help, if you don’t treat those values as being immutable. By extracting a &lt;code&gt;List&lt;/code&gt; from that &lt;code&gt;ConcurrentHashMap&lt;/code&gt;, then modifying it, that code is thread unsafe. Also, that &lt;code&gt;get&lt;/code&gt; followed by &lt;code&gt;put&lt;/code&gt; is not atomic. Such concurrency issues lead to overridden updates (lost values), or even to corrupted data structures. This could have all been avoided with proper use of an immutable &lt;code&gt;List&lt;/code&gt; in those values, combined with good use of &lt;code&gt;ConcurrentHashMap&lt;/code&gt;’s API (e.g., &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html#compute(K,java.util.function.BiFunction)&quot;&gt;compute&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So, the result was a hard to trace bug in our project, coming from a (proprietary) library that we can’t fix.&lt;/p&gt;

&lt;p&gt;In Scala, even if we use &lt;code&gt;ConcurrentHashMap&lt;/code&gt;, we’d use it in combination with a Scala immutable &lt;code&gt;List&lt;/code&gt;, which is available by default, no import necessary:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code
import java.util.concurrent.ConcurrentHashMap

//..
val dns = new ConcurrentHashMap[String, List[String]]()

//..
dns.compute(&quot;key&quot;, (k, v) =&gt; {
  val current = if (v != null) v else Nil
  current.prepended(&quot;new-value&quot;)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can do this with Java’s mutable &lt;code&gt;ArrayList&lt;/code&gt;, of course, but:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;you need to remember to not modify the extracted values — this means creating a clone, and adding values to that clone;&lt;/li&gt;
  &lt;li&gt;creating clones of mutable data structures can cost more than using specialized implementations of persistent/immutable collection types (e.g., Scala’s &lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Queue&lt;/code&gt;, &lt;code&gt;Vector&lt;/code&gt;, &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;);&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Immutable collection types can also be transformed into concurrent collections, very cheaply, by wrapping them into an &lt;code&gt;AtomicReference&lt;/code&gt;. Which is actually a neat trick used by many libraries handling concurrency.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala 3 code, making use of &quot;Explicit Nulls&quot;
// Needs the -Yexplicit-nulls compiler option to see it in action
import java.util.concurrent.atomic.AtomicReference
import scala.collection.immutable.Queue
import scala.collection.mutable.ListBuffer

final class ConcurrentQueue[V]() {
  private val ref = new AtomicReference(Queue.empty[V])

  def enqueue(value: V): Unit = {
    var continue = true
    while (continue) {
      val current = ref.get().nn
      val update = current.enqueue(value)
      continue = !ref.compareAndSet(current, update)
    }
  }

  def dequeue(): Option[V] = {
    // A legitimate case when Option&apos;s None doesn&apos;t mean Null 🙂
    var result: Option[V] | Null = null
    while (result == null) {
      val current = ref.get().nn
      current.dequeueOption match {
        case None =&gt;
          result = None
        case Some((v, update)) =&gt;
          if (ref.compareAndSet(current, update)) {
            result = Some(v)
          }
      }
    }
    result.nn
  }

  def dequeueAll(): List[V] = {
    val buffer = ListBuffer.empty[V]
    var continue = true
    while (continue) {
      dequeue() match {
        case None =&gt;
          continue = false
        case Some(v) =&gt;
          buffer.append(v)
      }
    }
    buffer.toList
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code
val queue = new ConcurrentQueue[String]()
queue.enqueue(&quot;Hello&quot;)
queue.enqueue(&quot;World&quot;)

for (value &lt;- queue.dequeueAll()) {
  println(value)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
&lt;strong&gt;WARN:&lt;/strong&gt; your &lt;code&gt;AtomicReference&lt;/code&gt; or your &lt;code&gt;ConcurrentHashMap&lt;/code&gt; references won’t work for managing concurrent access, if the values you put in them aren’t immutable (or at least treated as such)!
&lt;/p&gt;

&lt;p&gt;If you’re ever tempted to do this, remember, THIS IS A BUG:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Java code
final AtomicReference&lt;List&lt;String&gt;&gt; ref =
  new AtomicReference&lt;&gt;(new ArrayList&lt;&gt;());

// BUG!!!
ref.get().add(&quot;value&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that instead of atomic references, or other concurrent and mutable data structures, you could use intrinsic locks via &lt;code&gt;synchronize&lt;/code&gt; blocks and a &lt;code&gt;mutable.Queue&lt;/code&gt;, of course, but by using atomic references the algorithm is &lt;a href=&quot;https://en.wikipedia.org/wiki/Non-blocking_algorithm&quot;&gt;lock-free&lt;/a&gt;, and for example, with virtual threads in Java 19 (Project Loom) by using &lt;code&gt;synchronize&lt;/code&gt; blocks you can still have OS/platform threads blocked (pinned), whereas if you work this way, you can avoid that.&lt;/p&gt;

&lt;p&gt;As a fair warning, the algorithm may be non-blocking, but it is not “wait-free”, and might not do well on high contention. So for performance reasons, when you need concurrent queues, you’re better off using Java’s &lt;code&gt;ConcurrentLinkedQueue&lt;/code&gt; or specialized implementations, such as those in &lt;a href=&quot;https://github.com/JCTools/JCTools&quot;&gt;JCTools&lt;/a&gt; (which are awesome!🌞). However, you can put any immutable data structure in an &lt;code&gt;AtomicReference&lt;/code&gt;, and then claim that you’re working with &lt;a href=&quot;https://en.wikipedia.org/wiki/Software_transactional_memory&quot;&gt;STM&lt;/a&gt; (or at least something close) 😎.&lt;/p&gt;

&lt;h2 id=&quot;epilogue&quot;&gt;Epilogue&lt;/h2&gt;

&lt;p&gt;Immutable collections being used by default is one of the biggest wins people get when adopting “functional programming”, or when adopting alternative JVM languages, like Scala or Clojure. Nothing else comes close.&lt;/p&gt;

&lt;p&gt;Even when working with Java, you can adopt immutable collection types by default, as a best practice. You can do this either by:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Wrapping them in “unmodifiable” collections, using the standard library — but this won’t bring all possible benefits;&lt;/li&gt;
  &lt;li&gt;Adopting libraries such as Vavr or Guava.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now go forth and convince your team to adopt this best practice 🎤🎶😎&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/10/27/immutable-collections-your-default/?pk_campaign=rss&quot;&gt;Immutable Collections should be Your Default&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 27 Oct 2022 12:34:46 +0000</pubDate>
  <dc:modified>Sun, 04 Dec 2022 22:02:50 +0000</dc:modified>
  <atom:modified>Sun, 04 Dec 2022 22:02:50 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/10/27/immutable-collections-your-default/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/10/27/immutable-collections-your-default/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Java</category>
  <category>Scala</category>
  </item>


<item>
  <title>On Scala 3&#39;s Optional Braces</title>
  <description>I dislike Scala 3’s significant whitespace syntax. At this point it’s safe to say that I hate it, being (IMO) an unfortunate evolution of the language.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/10/24/scala-3-optional-braces/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-scala3-optional-braces.png?202603060940&quot; alt=&quot;&quot; width=&quot;2856&quot; height=&quot;1884&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
I dislike Scala 3&apos;s significant whitespace syntax. At this point it&apos;s safe to say that I hate it 🤷‍♂️, being (IMO) an unfortunate evolution of the language.
&lt;/p&gt;

&lt;p&gt;As a disclaimer, this may well be a subjective opinion, so full disclosure: I have never liked working with languages that have significant whitespace syntax. On the list of languages I dislike most, CoffeeScript is in the top 3, with YAML being a close second, and I had hoped that CoffeeScript’s failure will finally make the notion of significant whitespace unpopular. But significant whitespace is like a siren song that keeps coming back in language design, possibly propelled by the popularity of Python and of YAML, and I don’t understand why.&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
This is a strongly worded article, using words such as “hate”. I’m criticising ideas, not people, and I’m only criticising Scala’s new developments because it’s a language that I love. Since we don’t do science, expressing feelings is perfectly adequate 😛
&lt;/p&gt;

&lt;h2 id=&quot;virtues-of-indentation-based-syntax&quot;&gt;Virtues of indentation-based syntax&lt;/h2&gt;

&lt;p&gt;There are some virtues of a syntax based on significant whitespace. For example, code like this is sometimes a bug:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;if (x &gt; 0)
  foo(x)
  bar(x)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But you can have code linters, or the compiler, to force that &lt;code&gt;{}&lt;/code&gt; when &lt;code&gt;if&lt;/code&gt; is used as a statement, and once you add the braces, it’s much clearer what the code is supposed to do, no longer depending on whitespace. In my opinion, significant whitespace makes these instances harder to detect and solve by tooling. Think of all the copy/paste issues you can have.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;if (x &gt; 0) {
  foo(x)
}
bar(x)

// .. vs ..

if (x &gt; 0) {
  foo(x)
  bar(x)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, which formatting style should you pick?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;if (x &gt; 0) {
  ...
} else if (x &lt; 0) {
} else {
  ...
}
// ..vs ...
if (x &gt; 0) {
  ...
}
else if (x &lt; 0) {
  ...
}
else {
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But with tools such as Scalafmt, or &lt;code&gt;gofmt&lt;/code&gt;, this is a nonissue. It’s certainly not the kind of choice that has any impact on code quality, and it’s not enough to require the changing of an entire language. Scala could have an official coding style, enforced via Scalafmt, and this conversation would be over.&lt;/p&gt;

&lt;p&gt;Less boilerplate you say?&lt;/p&gt;

&lt;p&gt;I’m one of those people that doesn’t mind the &lt;code&gt;;&lt;/code&gt; at the end of lines in Java. I don’t miss it either, but it’s trivial to automate via the IDE, and sometimes it can serve as a useful visual delimiter. Because in fact &lt;code&gt;;&lt;/code&gt; separates imperative statements that are sequenced. And for &lt;code&gt;{}&lt;/code&gt;, what I notice from my peers is that they often want more braces, not less. Don’t you have colleagues that tend to do this?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;something match {
  case Something =&gt; { // &lt;- unnecessary, yet, desired

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

&lt;p&gt;Even though in this case the syntax is not ambiguous, some people would prefer those extra braces as a visual delimiter. It takes Scalafmt to enforce a common style, although I can never complain about extra chars meant to make the code less ambiguous.&lt;/p&gt;

&lt;h2 id=&quot;scala-is-not-python&quot;&gt;Scala is not Python&lt;/h2&gt;

&lt;p&gt;In Scala 3, I don’t know what the motivation was, but the word is that the new syntax is supposed to make Scala 3 more appealing to Python developers. I’m going to focus on Python, since I’m assuming that few people actually like YAML. So, at the risk of building a straw-man, I want to dispel this notion that Scala can be attractive to Python developers.&lt;/p&gt;

&lt;p&gt;First, &lt;em&gt;Python is popular in spite of its syntax&lt;/em&gt;, because it’s an interactive/dynamic language that’s easy to learn, it comes installed by default on all Linux distributions, and it comes with useful libraries such as Numpy, Scipy, Matplotlib, and others, which makes it the de facto standard for certain domains. To try to copy Python’s recipe for success, by making the syntax to have significant indentation, is shortsighted at best. I worked as a Python developer, and I can tell you that its syntax was my least favorite part.&lt;/p&gt;

&lt;p&gt;Such cosmetic changes may look appealing, but any copied success recipe should start with Python striving to NOT be a &lt;a href=&quot;https://en.wikipedia.org/wiki/There&apos;s_more_than_one_way_to_do_it&quot;&gt;TIMTOWTDI&lt;/a&gt; language. And Scala 3 did, in fact, introduce even more ways to express yourself. The language that proudly allowed many ways to express yourself, such as &lt;a href=&quot;https://metacpan.org/pod/Lingua::tlhInganHol::yIghun&quot;&gt;programming in the Klingon language&lt;/a&gt;, is Perl, which is Python’s nemesis 😎. Even more, Python historically rejected multi-line anonymous functions. In &lt;a href=&quot;https://www.artima.com/weblogs/viewpost.jsp?thread=147358&quot;&gt;Language Design Is Not Just Solving Puzzles&lt;/a&gt;, Guido van Rossum says about a proposal for multi-line lambdas:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;But such solutions often lack “Pythonicity” – that elusive trait of a good Python feature. It’s impossible to express Pythonicity as a hard constraint. Even the Zen of Python doesn’t translate into a simple test of Pythonicity.&lt;/p&gt;

  &lt;p&gt;… And still that’s not why I rejected this proposal. If the double colon is unpythonic, perhaps a solution could be found that uses a single colon and is still backwards compatible (the other big constraint looming big for Pythonic Puzzle solvers). I actually have one in mind: if there’s text after the colon, it’s a backwards-compatible expression lambda; if there’s a newline, it’s a multi-line lambda; the rest of the proposal can remain unchanged. Presto, QED, voilà, etcetera.&lt;/p&gt;

  &lt;p&gt;But I’m rejecting that too, because in the end (and this is where I admit to unintentionally misleading the submitter) I find &lt;strong&gt;any solution unacceptable that embeds an indentation-based block in the middle of an expression&lt;/strong&gt;. Since I find alternative syntax for statement grouping (e.g. braces or begin/end keywords) equally unacceptable, this pretty much makes a multi-line lambda an unsolvable puzzle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I find this quote very interesting, as it says that in Python significant indentation is reserved for grouping statements, and is not for describing expressions. Guido certainly finds the distinction between groups of statements and expressions to be an important one. I think it’s pretty clear that Scala’s new (fewer-braces) syntax is not “pythonic”:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;xs.map: x =&gt;
  val y = x - 1
  y * y
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And I seriously fail to see how it improves on:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;xs.map { x =&gt;
  val y = x - 1
  y * y
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Reading the &lt;a href=&quot;https://peps.python.org/pep-0020/&quot;&gt;Zen of Python&lt;/a&gt; should make it clear that Scala is, at this point, a very unpythonic language. Note that I always found it odd that Python has the “only one way to do it” mantra, since in practice that’s very far from true, but at least it tries.&lt;/p&gt;

&lt;h2 id=&quot;new-syntax-is-unclear&quot;&gt;New syntax is unclear&lt;/h2&gt;

&lt;p&gt;One thing that I really don’t get is the &lt;code&gt;end&lt;/code&gt; marker:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def largeMethod(...) =
  ...
  if ... then ...
  else
    ... // a large block
  end if
  ... // more code
end largeMethod
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Python does not have an &lt;code&gt;end&lt;/code&gt; marker, Ruby or Pascal do. You could say that Python has the virtue of forcing you to keep your functions short, since obviously, indentation-based syntax is problematic for big blocks of code. I never bought that, which is why an “end marker” makes sense, except that Scala has already had a perfectly usable syntax that made use of &lt;code&gt;{}&lt;/code&gt; braces. And no matter how much more readable you find this new end marker to be, the ensuing TIMTOWTDI is just not worth it.&lt;/p&gt;

&lt;p&gt;Braces were already optional in Scala, in the case of expressions. For example, method definitions could omit braces, in case the implementation was a single expression. If you needed multiple statements, or in case you needed a &lt;a href=&quot;https://en.wikipedia.org/wiki/Scope_(computer_science)&quot;&gt;lexical scope&lt;/a&gt;, you added the braces. Braces are super useful for hiding implementation details in the local scope:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val y = something()
val x = {
  // `y` and `z` can shadow values in the enclosing scope
  // and are no longer visible after this scope ends
  val y = foo()
  val z = bar()
  y + z
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is such a beautiful syntax. IMO, lexical scopes need visual delimiters that are more significant than indentation. It may be important to mention that scoping in Python is at the “enclosing-function” level. You can’t do what I just did here with Scala, unless you create a closure, and then execute it. Which kind of makes sense, since establishing the scope by the indentation level seems to be pretty ambiguous.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Python code
y = something()
# creating new lexical scope
def createX():
  y = foo() # shadowing
  z = bar()
  return y + z
x = createX()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In Scala 2, groups of statements needed braces, expressions didn’t. What those braces meant (a group of statements, also creating a lexical scope) was simple to explain. In Scala 3 this now changes.&lt;/p&gt;

&lt;h2 id=&quot;tooling-is-problematic&quot;&gt;Tooling is problematic&lt;/h2&gt;

&lt;p&gt;Another problem we have is one of &lt;strong&gt;tooling&lt;/strong&gt;. Scala 3 is a language that’s harder to parse than Scala 2. Syntax based on indentation is context-sensitive. IDEs, like IntelliJ IDEA or Metals, or tools like Scalafmt, now have to do more work. My own website isn’t able to correctly do syntax highlighting for Scala 3 yet.&lt;/p&gt;

&lt;p&gt;And simple things, like copy/pasting a piece of code, are a problem because the IDE now has to guess the correct indentation level.&lt;/p&gt;

&lt;h2 id=&quot;on-backwards-compatibility&quot;&gt;On backwards compatibility&lt;/h2&gt;

&lt;p&gt;Languages evolve, but there is such a thing as too much evolution, for the simple reason that backwards compatibility has to be provided, otherwise you’re effectively talking about a new language, and nobody is going to adopt the new version. This is why Scala will have to support both the old and the new indentation-based syntaxes for a very, very long time. Which means that projects will have to depend on compiler options (e.g., &lt;code&gt;-no-indent&lt;/code&gt;), or on tools, such as Scalafmt, to impose the blessed syntax rules. And, don’t get me wrong, Scalafmt is great, but I considered it optional, whereas now it becomes mandatory. This is similar to introducing the &lt;a href=&quot;https://alexn.org/blog/2022/05/11/implicit-vs-scala-3-given/&quot;&gt;using/given syntax&lt;/a&gt;, which is nice, but the old &lt;code&gt;implicit&lt;/code&gt; keyword is still there, so it leads to more complexity, not less.&lt;/p&gt;

&lt;p&gt;Java’s slow evolution makes a lot of sense. Love it or hate it, you can probably take a JAR compiled with Java 1.1, and it would still run on the latest JVM, and that Java 1.1 code probably compiles as well. There are some exceptions, but those are very few and far between. Java’s devotion to backwards compatibility is what propelled it to be considered a platform you can depend on, being in the same league as POSIX. Developers may not like its generics, its boilerplate, or its culture of libraries doing runtime introspection to workaround language issues. But at least its syntax won’t dramatically change overnight, and those Python developers probably learned Java in school, so they can always get back to it.&lt;/p&gt;

&lt;p&gt;Scala 3 is succeeding in sending a message that it’s not Java++, but it’s not doing so in a way that I find appealing.&lt;/p&gt;

&lt;h2 id=&quot;in-closing&quot;&gt;In closing&lt;/h2&gt;

&lt;p&gt;What I expected from Scala 3 was a simplification of Scala 2. It does simplify in some ways, e.g., macros are better, the type system fixes some holes, I love untagged union types, etc. But it also introduces complexity of its own, and for no good reason that I can see.&lt;/p&gt;

&lt;p&gt;I think it’s too late to backtrack on these changes, significant-indentation syntax is probably here to stay (not in my projects), but one can hope.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/10/24/scala-3-optional-braces/?pk_campaign=rss&quot;&gt;On Scala 3&apos;s Optional Braces&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 24 Oct 2022 09:07:21 +0000</pubDate>
  <dc:modified>Tue, 06 Jun 2023 12:19:50 +0000</dc:modified>
  <atom:modified>Tue, 06 Jun 2023 12:19:50 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/10/24/scala-3-optional-braces/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/10/24/scala-3-optional-braces/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Programming Rant</category>
  <category>Scala</category>
  <category>Scala 3</category>
  </item>


<item>
  <title>Building a Queue for Delayed Messages via a RDBMS (1): Design</title>
  <description>Ever had the need to deliver messages on your queue at a certain timestamp in the future? Look no further, because your RDBMS can do it. This is part 1 of a series that builds a solution from scratch.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/10/21/modeling-queue-for-delayed-messages-via-rdbms/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-delayed-queue-design.png?202603060940&quot; alt=&quot;&quot; width=&quot;2484&quot; height=&quot;1244&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
Ever had the need to deliver messages on your queue at a certain timestamp in the future? Look no further, because your RDBMS can do it. This is part 1 of a series that builds a solution from scratch.
&lt;/p&gt;

&lt;p&gt;In our $work project we had the need to push messages on a queue, but delayed, for delivery at a certain timestamp in the future. Our existing MQ servers aren’t adequate for that, and we can’t introduce more technology in our stack.&lt;/p&gt;

&lt;p&gt;Turns out, a relational database is perfectly adequate (such as MySQL or PostgreSQL). Here’s how…&lt;/p&gt;

&lt;p&gt;First, establish the requirements:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Multiple consumers can read from the queue, at the same time, however only one consumer can gain access to a message for processing;&lt;/li&gt;
  &lt;li&gt;When a consumer pulls a message from the queue, that message becomes invisible for other consumers — but if, after a timeout, the consumer fails to process the message and then “acknowledge” that the processing is done (commit), then the message becomes visible again for other consumers (standard MQ functionality);&lt;/li&gt;
  &lt;li&gt;We need a message key, such that we can avoid duplicate messages (functionality usually not provided by standard queues);&lt;/li&gt;
  &lt;li&gt;The payload is usually JSON, but the datatype should be encoded in the table row, such that we know how to parse it, also doubling as an extra validation;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;run-loop&quot;&gt;Run-loop&lt;/h2&gt;

&lt;p&gt;Your code should look more or less like this pseudocode, you can insert your favorite libraries and abstractions, as this could be built via reactive streams or what not:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;while (true) {
  val message = selectNextMessageAvailable()
  if (message == null) {
    sleep(15.seconds)
    continue // next please
  }

  val lockAcquired = updateAcquireLock(message)
  if (!lockAcquired) {
    continue // next please
  }

  try {
    // do whatever it is we want with our message
    process(message)
    // if everything went well, mark it as processed
    delete(message)
  } catch (e: Exception) {
    logger.error(e)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;creating-the-table&quot;&gt;Creating the table&lt;/h2&gt;

&lt;p&gt;The RDBMS table might look like the following — note we are using MySQL/MariaDB as our chosen dialect:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE DelayedQueue
(
    pKey VARCHAR(200) NOT NULL,
    pKind VARCHAR(100) NOT NULL,
    payload BLOB NOT NULL,
    scheduledAt BIGINT NOT NULL,
    scheduledAtInitially BIGINT NOT NULL,
    createdAt BIGINT NOT NULL,
    PRIMARY KEY (pKey, pKind)
);

CREATE INDEX DelayedQueue__KindPlusScheduledAtIndex
ON DelayedQueue (pKind, scheduledAt);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Thus, we have these fields:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The primary key is the tuple &lt;code&gt;(pKey, pKind)&lt;/code&gt; — the &lt;code&gt;pKey&lt;/code&gt; can uniquely identify the message, but &lt;code&gt;pKind&lt;/code&gt; is needed to indicate the stored data type, as we need to validate that we can parse it;&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;payload&lt;/code&gt; can be our JSON document;&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;scheduledAt&lt;/code&gt; is a Unix timestamp (in seconds) indicating when the message is scheduled for delivery — note that this gets used in the &lt;code&gt;SELECT&lt;/code&gt;, but also doubles as the “lock” we acquire on messages that are in processing, being &lt;code&gt;UPDATED&lt;/code&gt; on each pull — which is why we also need &lt;code&gt;scheduledAtInitially&lt;/code&gt;, meant for debugging;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;pushing-new-messages&quot;&gt;Pushing new messages&lt;/h2&gt;

&lt;p&gt;Pushing messages for new keys is easy:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;INSERT IGNORE INTO DelayedQueue
  (pKey, pKind, payload, scheduledAt, scheduledAtInitially, createdAt)
VALUES (
  &quot;c71de6b4-510f-11ed-9d4d-0242ac120002&quot;,
  &apos;Contact&apos;,
  &apos;{ &quot;name&quot;: &quot;Alex&quot;, &quot;emailAddress&quot;: &quot;noreply@alexn.org&quot; }&apos;,
  UNIX_TIMESTAMP(&apos;2022-10-22 10:00:00&apos;),
  UNIX_TIMESTAMP(&apos;2022-10-22 10:00:00&apos;),
  UNIX_TIMESTAMP() -- now
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note, I am using &lt;code&gt;INSERT IGNORE&lt;/code&gt;, because we may deal with duplicates. MySQL/MariaDB allows us to do that, which is pretty nice. Some databases don’t have this syntax, and in Java, primary key violations turn into exceptions. Pattern matching &lt;code&gt;java.sql.SQLException&lt;/code&gt; is something that should be avoided at all costs, as the error you get depends on the database vendor and the context, and you need to find those by trial and error. For example, for Microsoft’s SQL Server, you have to look for &lt;a href=&quot;https://docs.microsoft.com/en-us/sql/relational-databases/replication/mssql-eng002627&quot;&gt;error code 2627&lt;/a&gt;, or &lt;a href=&quot;https://docs.microsoft.com/en-us/sql/relational-databases/replication/mssql-eng002601&quot;&gt;error code 2601&lt;/a&gt;, possibly in combination with sql state &lt;code&gt;23000&lt;/code&gt;. Whereas for HSQLDB, you have to look for error code &lt;code&gt;-104&lt;/code&gt; in combination with sql state &lt;code&gt;23505&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;polling-the-queue&quot;&gt;Polling the queue&lt;/h2&gt;

&lt;p&gt;We do a &lt;code&gt;SELECT&lt;/code&gt; to see if there are any messages where &lt;code&gt;scheduledAt &lt;= NOW&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And for as long as there are no messages available, we repeat the query after a configurable delay. The time interval depends on your latency requirements, but for delayed messages this is not an issue, so you could repeat the query every 15 seconds or so. Repeating it more often could have a negative impact on the database, so be careful with this configuration.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;  pKey, payload, scheduledAt, createdAt
FROM DelayedQueue
WHERE
  pKind = &apos;Contact&apos; AND scheduledAt &lt;= UNIX_TIMESTAMP()
ORDER BY scheduledAt
LIMIT 1;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that this query is optimized by the index that we already created.&lt;/p&gt;

&lt;h2 id=&quot;acquiring-the-lock&quot;&gt;Acquiring the lock&lt;/h2&gt;

&lt;p&gt;Once we have a message available, we have to make it invisible for other consumer, such that there is at most one consumer processing it at the same time. So we need a “lock” per message.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;UPDATE DelayedQueue
SET
  -- acquires the lock, sets the timeout in 5 minutes
  scheduledAt = UNIX_TIMESTAMP() + 60 * 5
WHERE
  pKey = &apos;c71de6b4-510f-11ed-9d4d-0242ac120002&apos; AND
  pKind = &apos;Contact&apos; AND
  scheduledAt = 1666422000 -- concurrency check ;-)
;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Whatever database client you’re using (e.g., JDBC), it will return the number of updated rows. If the update suceeds, it should return &lt;code&gt;1&lt;/code&gt;, if the update fails (due to another consumer winning this race), then it should return &lt;code&gt;0&lt;/code&gt;. If &lt;code&gt;updatedRows &gt; 0&lt;/code&gt;, then you have successfully acquired the lock on this message, otherwise, you cannot proceed, instead you need to retry the transaction (SELECT + UPDATE).&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
NOTE: &lt;code&gt;scheduledAt&lt;/code&gt; is updated to be in the future. THIS here is what makes it invisible to other consumers, with a 5 minutes timeout (after which it becomes visible again).
&lt;/p&gt;

&lt;h2 id=&quot;transactional-commit-acknowledge&quot;&gt;Transactional commit (acknowledge)&lt;/h2&gt;

&lt;p&gt;Once a consumer processes the message, it needs to be marked as being processed. We can do that by deletion, but we need to be careful:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;DELETE FROM DelayedQueue
WHERE
  pKey = &apos;c71de6b4-510f-11ed-9d4d-0242ac120002&apos; AND
  pKind = &apos;Contact&apos; AND
  -- Race-condition check (1) — value should be set from user code:
  createdAt = 1666340050 AND
  -- Race-condition check (2) — value should be set from user code:
  scheduledAt = 1666422300
;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can’t just delete anything that has that key, because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The initial timeout might have passed, and we might now have a concurrent execution (which is inevitable);&lt;/li&gt;
  &lt;li&gt;We might have a new key that was reused;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As such, we need to check the combination of &lt;code&gt;createdAt&lt;/code&gt; (to check that we still have the same entry, instead of a new one), and our updated &lt;code&gt;scheduledAt&lt;/code&gt; (to ensure that we are not dealing with a concurrent execution after timeout).&lt;/p&gt;

&lt;h2 id=&quot;coming-up-next-&quot;&gt;Coming up next …&lt;/h2&gt;

&lt;p&gt;I’m going to follow up with an article that actually builds this, as a Java/Scala/Kotlin library.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/10/21/modeling-queue-for-delayed-messages-via-rdbms/?pk_campaign=rss&quot;&gt;Building a Queue for Delayed Messages via a RDBMS (1): Design&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 21 Oct 2022 06:46:07 +0000</pubDate>
  <dc:modified>Mon, 24 Oct 2022 06:00:29 +0000</dc:modified>
  <atom:modified>Mon, 24 Oct 2022 06:00:29 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/10/21/modeling-queue-for-delayed-messages-via-rdbms/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/10/21/modeling-queue-for-delayed-messages-via-rdbms/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>SQL</category>
  </item>


<item>
  <title>Cut the Technobabble</title>
  <description>The marketing for Functional Programming is made of technobabble. Technobabble was used in Star Trek. Those long discussions are what Star Trek was loved for, but technobabble isn’t good for sharing knowledge or advancing our field.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/10/19/cut-the-technobabble/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-cut-the-technobabble.jpeg?202603060940&quot; alt=&quot;&quot; width=&quot;1400&quot; height=&quot;700&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;&quot;Sir, we have a bug!&quot;; &quot;But we used algebraic reasoning!&quot;&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
The marketing for Functional Programming is made of technobabble. Technobabble was used in Star Trek. Those long discussions are what Star Trek was loved for, but technobabble isn&apos;t good for sharing knowledge or advancing our field.
&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Technobabble: a type of nonsense that consists of buzzwords, esoteric language, or technical jargon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a follow-up to my last article, &lt;a href=&quot;https://alexn.org/blog/2022/10/13/the-case-against-effect-systems-io-data-type/&quot;&gt;“The case against Effect Systems (IO)”&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;composition&quot;&gt;Composition&lt;/h2&gt;

&lt;p&gt;Composition is about taking pieces and combining them in a bigger piece. Functions are automatically composable, and in FP, when people talk about composition, they usually mean this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/category-theory.png&quot; class=&quot;transparency-fix&quot; alt=&quot;Function composition diagram&quot; width=&quot;1400&quot; height=&quot;1400&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;&lt;/p&gt;

&lt;p&gt;It’s not just functions, that’s why we have “category theory”, but to put it plainly in code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def functionAtoB: A =&gt; B = ???
def functionBtoC: B =&gt; C = ???

// We get this for free
def functionAtoC: A =&gt; C =
  a =&gt; functionBtoC(functionAtoB(a))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This works if you have an &lt;code&gt;F[_]&lt;/code&gt; monadic type as well, which is nice, and we can say that these functions provide us with a simple and established protocol to compose smaller pieces into bigger pieces:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def functionAtoB: A =&gt; F[B] = ???
def functionBtoC: B =&gt; F[C] = ???

// We get this for free
def functionAtoC[F[_]: Monad]: A =&gt; F[C] =
  a =&gt; functionAtoB(a).flatMap(functionBtoC)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Different monadic types don’t compose well. So, for example, if you have 2 types, &lt;code&gt;F[_]&lt;/code&gt; and &lt;code&gt;G[_]&lt;/code&gt;, you can’t automatically combine them into an &lt;code&gt;F[G[_]]&lt;/code&gt; or &lt;code&gt;G[F[_]]&lt;/code&gt; (think &lt;code&gt;IO[Option[_]]&lt;/code&gt; and &lt;code&gt;Option[IO[_]]&lt;/code&gt;). Knowledge of their monadic nature isn’t enough for you to do that, as you need more. Hence, we have a need for “&lt;em&gt;monad transformers&lt;/em&gt;”, e.g. &lt;code&gt;OptionT&lt;/code&gt;, &lt;code&gt;EitherT&lt;/code&gt;, &lt;code&gt;ReaderT&lt;/code&gt;. Or we need another type-class, like &lt;code&gt;Traverse&lt;/code&gt;, which allows us to transform an &lt;code&gt;F[G[_]]&lt;/code&gt; into &lt;code&gt;G[F[_]]&lt;/code&gt; (e.g. &lt;code&gt;(list: List[IO]).sequence&lt;/code&gt;). That, or you can basically take the monad transformers and combine everything into a bigger type. Obviously something like this can be hard-coded, to be more ergonomic and/or efficient, moving the costs around:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type ZIO[-Env, +Err, +R] = Kleisli[EitherT[IO, Err, ?], Env, R]
// type ZIO[-Env, +Err, +R] = Env =&gt; IO[Either[Err, R]]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But folks, from where I’m sitting, I don’t see that much automatic “composition” happening for monads, in general, compared to plain old functions. The “composition” happening in Haskell’s ecosystem, via the prevalence of monad transformers, is for me a turnoff, alongside &lt;code&gt;ReaderT&lt;/code&gt; used for dependency injection, even when encoded into something more ergonomic. I’ll take Java’s Spring over that, thanks. But that’s just a personal opinion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Composition”&lt;/strong&gt; is usually technobabble because …&lt;/p&gt;

&lt;p&gt;Objects (from OOP) compose — that’s their whole purpose actually, that’s why we care about subtype polymorphism, or encapsulation, because it’s all about their composition. We may need design patterns to compose, but they compose well. And maybe we have a hard time coming up with an automatic protocol for it, i.e., drawing those arrows from category theory, but it’s composition nonetheless. And structured/imperative programming constructs also compose. It’s why you’re able to build anything at all.&lt;/p&gt;

&lt;p&gt;In the context of &lt;code&gt;IO&lt;/code&gt;, what people mean by “composition” is basically “reuse” via abstract interfaces (type classes). For example, it’s nice being able to transform a &lt;code&gt;List[IO[A]]&lt;/code&gt; into an &lt;code&gt;IO[List[A]]&lt;/code&gt;, or a &lt;code&gt;List[EitherT[IO, E, A]]&lt;/code&gt; into an &lt;code&gt;EitherT[IO, E, List[A]]&lt;/code&gt;, by using very generic functions that make use of type classes. For example, I love doing stuff like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code
def processInBatches[A, B](
  batchSize: Int,
  list: List[A],
  job: A =&gt; IO[B]
): IO[List[B]] =
  list
    .sliding(batchSize, batchSize)
    .map(batch =&gt; batch.map(job).parSequence)
    .sequence
    .map(_.flatten)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Functional programming is expression-oriented&lt;/strong&gt;, we process stuff by transforming input into output via function composition, essentially assembling a pipeline. Working with &lt;code&gt;IO&lt;/code&gt; here allows us to remain within this paradigm, and it’s awesome for it. Expressions are awesome.&lt;/p&gt;

&lt;p&gt;But as far as composition is concerned, this argument isn’t as strong as you’d think, because in the context of blocking I/O and side-effecting functions, going from &lt;code&gt;() =&gt; A&lt;/code&gt; to &lt;code&gt;A&lt;/code&gt; or from &lt;code&gt;List[() =&gt; A]&lt;/code&gt; to &lt;code&gt;List[A]&lt;/code&gt; is trivial, not to mention you can always use plain-old &lt;code&gt;foreach&lt;/code&gt; loops, which also compose 🤷‍♂️&lt;/p&gt;

&lt;p&gt;I don’t see any monadic &lt;code&gt;IO&lt;/code&gt; in the following code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// Kotlin code — only used because Java currently needs boilerplate
suspend fun &lt;A, B&gt; processInBatches(
  batchSize: Int,
  list: List&lt;A&gt;,
  job: suspend (A) -&gt; B
): List&lt;B&gt; = coroutineScope {
  list.windowed(size = batchSize, step = batchSize)
    .map { batch -&gt;
      batch
        .map { async { job(it) } }
        .awaitAll()
    }
    .flatten()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And, say, if you want &lt;em&gt;“compositional resource-safety”&lt;/em&gt;, nothing beats this in terms of how clear it is, or the contract that the JVM runtime gives you:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Java code / try-with-resources
try (final var res1 = new Resource1()) {
  try (final var res2 = new Resource2(res1)) {
    //...
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/resource&quot;&gt;Cats-Effect’s Resource&lt;/a&gt; (or similar abstractions) is a super-power, being a presence in all of my Scala projects. However, it would be a mistake to think that more classic OOP alternatives aren’t available, or that it wouldn’t work with blocking I/O. The problem with resource management in Java is linked to bad design related to &lt;code&gt;Closeable&lt;/code&gt;, or to the &lt;a href=&quot;https://alexn.org/blog/2022/09/19/java-cultural-problem/&quot;&gt;Java EE flavored&lt;/a&gt; dependency injection. C++ developers have a much better time with RAII, possibly because they have to do that for memory management, too, so it’s everywhere. I also find Scala’s own &lt;a href=&quot;https://www.scala-lang.org/api/current/scala/util/Using$$Manager.html&quot;&gt;Using.Manager&lt;/a&gt; interesting, being a simple and effective way to cope with multiple &lt;code&gt;Closeable&lt;/code&gt; resources in imperative code. And better options can happen for imperative code too. Solutions like &lt;code&gt;Resource&lt;/code&gt; aren’t perfect either, because we can leak references, to be used after they are disposed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short:&lt;/strong&gt; expression-oriented programming is awesome, and &lt;code&gt;IO&lt;/code&gt; implementing common type-classes keeps you into the right paradigm. But “composition”, when used to justify the path we took (e.g., &lt;code&gt;IO&lt;/code&gt;), is often just technobabble.&lt;/p&gt;

&lt;h2 id=&quot;algebraic-reasoning&quot;&gt;Algebraic reasoning&lt;/h2&gt;

&lt;p&gt;What “algebraic reasoning” means is that &lt;em&gt;math&lt;/em&gt; gets used.&lt;/p&gt;

&lt;p&gt;But this spans multiple topics, so let’s see …&lt;/p&gt;

&lt;h3 id=&quot;design-from-first-principles&quot;&gt;Design from first principles&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;“First principles”&lt;/em&gt; are &lt;a href=&quot;https://en.wikipedia.org/wiki/Axiom&quot;&gt;axioms&lt;/a&gt;, a word that I like more, used in the Romanian language as well — these are statements we consider to be true with no evidence (or implementation) available, or “intrinsic”, and then every other theorem or operation or principle gets derived from those statements. “Principled” simply means that the software system was started from a bunch of primitive/abstract operations and everything else was implemented in terms of those. Being principled is useful for demonstrating &lt;em&gt;correctness&lt;/em&gt;. When adding new operations that get built on top of already available ones (e.g., non-abstract functions/methods), you don’t need to demonstrate again the correctness of your entire design.&lt;/p&gt;

&lt;p&gt;Designing “from first principles” is a choice for the library authors in order to cut costs, and … that’s about all there is to it. As it does nothing for the user, and can be a hindrance as well. Because obviously, the real world isn’t principled. Even choosing the principles you’re building on is a matter of design (aka, ideology). There are really complex systems that you’re using every day, that aren’t based on first principles. Designs based on science and engineering are very often not based on first principles.&lt;/p&gt;

&lt;h3 id=&quot;type-class-laws&quot;&gt;Type class laws&lt;/h3&gt;

&lt;p&gt;Defining a “technology compatibility kit” (TCK) (aka “the laws”) … is important in case users can implement abstract interfaces / protocols that need a certain behavior that isn’t well expressed just via the exposed types. And these “laws” are defined with math language, with equivalence tests between expressions, but this isn’t a requirement for defining a TCK, and quite often math is not enough when testing the side effects.&lt;/p&gt;

&lt;p&gt;When you see a &lt;code&gt;flatMap&lt;/code&gt;, you know it should have a certain behavior (i.e., left+right identity, and associativity). Monad’s definition is described by “laws” expressed with math. And yet &lt;code&gt;IO&lt;/code&gt; should not cache its result, a potential side effect that can’t really be described with math. Which is fine, I mean, the &lt;a href=&quot;https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.4/README.md&quot;&gt;Reactive Streams specification + TCK&lt;/a&gt; isn’t algebraic, but it’s useful nonetheless.&lt;/p&gt;

&lt;p&gt;I’d also argue that you don’t need algebraic properties in order to be able to operate things, to have a good mental model for it (that only has to be useful, not real). I keep recommending the book &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Design_of_Everyday_Things&quot;&gt;The Design of Everyday Things&lt;/a&gt; for that reason.  Algebraic reasoning is useful in the design process, but if you have to look at math expressions in order to predict the behavior of the API you’re operating, that design is error-prone and hard to use.&lt;/p&gt;

&lt;p&gt;People, programmers, in general, don’t care about algebraic reasoning. What people care about is the User Experience™️, and the harsh reality is that UX usually trumps theorem proofs. Just look at Go/Python versus Haskell. This is why statically typed languages aren’t winning the markets dominated by dynamically typed languages, and will never do, for as long as the UX doesn’t improve, as dynamic languages are great at UX.&lt;/p&gt;

&lt;p&gt;Good UX is about exposing a user interface that, after some training, can allow the user to go in autopilot mode. Think about driving a car, as programming isn’t very different. In that sense, the laws of type classes can help due to having tests for common protocols, implemented by different types, such that you can rely on those protocols no matter what the types represent. I think the innovation is in having a TCK in the first place, and less about that TCK being algebraic.&lt;/p&gt;

&lt;h3 id=&quot;local-reasoning&quot;&gt;Local reasoning&lt;/h3&gt;

&lt;p&gt;“Local reasoning” means that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You can take a piece of code, and understand what it does, without the wider context in which it gets used;&lt;/li&gt;
  &lt;li&gt;In the context of FP, it means that you can assess the correctness of a function call without depending on the history of its invocations (i.e., functions are deterministic);&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For one, code makes sense locally, without a wider context. This isn’t a property of FP, necessarily. The Linux kernel is famous for rejecting C++ for that reason — C doesn’t have classes, and its subroutines need to have any state passed in as parameters. This makes it easier for code reviewers to judge commit diffs. Don’t believe me, see &lt;a href=&quot;http://www.realworldtech.com/forums/index.cfm?action=detail&amp;id=110618&amp;threadid=110549&amp;roomid=2&quot;&gt;Linus Torvalds’ thoughts on C++&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For example, I personally don’t even write much code any more, and haven’t for years. I mainly merge…&lt;/p&gt;

  &lt;p&gt;One of the absolute worst features of C++ is how it makes a lot of things so context-dependent - which just means that when you look at the code, a local view simply seldom gives enough context to know what is going on.&lt;/p&gt;

  &lt;p&gt;That is a huge problem for communication. It immediately makes it much harder to describe things, because you have to give a much bigger context. It’s one big reason why I detest things like overloading - not only can you not grep for things, but it makes it much harder to see what a snippet of code really does.&lt;/p&gt;

  &lt;p&gt;Put another way: when you communicate in fragments (think “patches”), it’s always better to see “sctp_connect()” than to see just “connect()” where some unseen context is what makes the compiler know that it is in the sctp module.&lt;/p&gt;

  &lt;p&gt;And C is a largely context-free language. When you see a C expression, you know what it does. A function call does one thing, and one thing only - there will not be some subtle issue about “which version” of a function it calls.&lt;/p&gt;

  &lt;p&gt;So there are particular reasons why I think C is “as simple as possible, but no simpler” for the particular case of an OS kernel, or system programming in particular.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think C is as far from functional programming as you can get. The language in which you pass stuff as &lt;code&gt;void*&lt;/code&gt;, only to reinterpret it as anything, depending on context, is as mutable, as dirty and as unsafe as it can get. And here is Linus Torvalds, talking about being able to locally reason about its subroutines, better than he’d be able to do with C++.&lt;/p&gt;

&lt;p&gt;Going back to FP, it’s nice when the correctness of a computation does not depend on the history of invocations. Eliminating non-determinism is the ideal in functional programming. The dirty secret, however, is that’s not happening with &lt;code&gt;IO&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class Counter private (ref: AtomicInt) {
  // Looks like it depends on the history of invocations to me 🤷‍♂️
  // I mean, technically, the function call is deterministic, but it&apos;s
  // not returning the data that we crave for, this being codata (computations);
  def increment: IO[Int] = IO(ref.incrementAndGet)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The ideal in functional programming is for functions to return data, the output depending entirely on the call’s (explicit) input parameters, such that the output doesn’t depend on prior invocations of that function. But that’s when you avoid &lt;code&gt;IO&lt;/code&gt;, because &lt;code&gt;IO&lt;/code&gt; is modeling access to shared mutable state by definition.&lt;/p&gt;

&lt;p&gt;You heard it here first, “local algebraic reasoning” is usually technobabble.&lt;/p&gt;

&lt;h2 id=&quot;is-fp-good-at-all-is-io&quot;&gt;Is FP good at all? Is IO?&lt;/h2&gt;

&lt;p&gt;Of course!&lt;/p&gt;

&lt;p&gt;“&lt;a href=&quot;https://en.wikipedia.org/wiki/Referential_transparency&quot;&gt;Referential transparency&lt;/a&gt;”, driving the “substitution model” of evaluation, isn’t technobabble, although I have my doubts when we are talking of “codata” (suspended computations). But in fairness, with &lt;code&gt;IO&lt;/code&gt;, even if the program is still modeling the access to shared mutable state, and still describes a step-by-step computation, fact of the matter is that &lt;code&gt;IO&lt;/code&gt; keeps people honest.&lt;/p&gt;

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

&lt;ol&gt;
  &lt;li&gt;Access to heavy resources, that can only be built via side effects, has to be modelled via &lt;code&gt;IO&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;This forces those resources to be passed as function or constructor parameters;&lt;/li&gt;
  &lt;li&gt;Shared global state, even when it exists, becomes more local — ideally, still depends on code reviews;&lt;/li&gt;
  &lt;li&gt;The state of the world (e.g., the current time, or randomness), passed as function parameters, forces saner data modelling (e.g., maybe you don’t need that timestamp there), and makes the code easier to test — ideally, or you can just have &lt;code&gt;IO&lt;/code&gt; everywhere, much like having side effects everywhere;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of these are best practices, but best practices are best enforced by a compiler 😈&lt;/p&gt;

&lt;p&gt;Also, functional programming is &lt;em&gt;expression-oriented programming&lt;/em&gt;, and expressions are awesome, as it puts you into the mindset of transforming data via pipelines (aka function composition). It’s all about the UX, frankly. It’s always about the UX.&lt;/p&gt;

&lt;p&gt;I’m starting to have some doubts about using monads for modelling side effects, though, but I’m still digesting my feelings 🤷‍♂️&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=h4idB5KAfyc&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-technobabble-2.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=h4idB5KAfyc&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Type R?
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/10/19/cut-the-technobabble/?pk_campaign=rss&quot;&gt;Cut the Technobabble&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 19 Oct 2022 12:00:00 +0000</pubDate>
  <dc:modified>Fri, 21 Oct 2022 06:10:26 +0000</dc:modified>
  <atom:modified>Fri, 21 Oct 2022 06:10:26 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/10/19/cut-the-technobabble/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/10/19/cut-the-technobabble/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Kotlin</category>
  <category>Scala</category>
  </item>


<item>
  <title>The case against Effect Systems (e.g., the IO data type)</title>
  <description>As Scala developers and fans of the functional programming promoted by Haskell, how do we justify the use of IO to newbies coming from Java? It’s been a fun ride, but the truth is that Java 19 is changing everything.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/10/13/the-case-against-effect-systems-io-data-type/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-effect-systems.png?202603060940&quot; alt=&quot;&quot; width=&quot;2428&quot; height=&quot;1652&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
As Scala developers and fans of the functional programming promoted by Haskell, how do we justify the use of &lt;code&gt;IO&lt;/code&gt; to newbies coming from Java? It’s been a fun ride, but the truth is that &lt;a href=&quot;https://alexn.org/blog/2022/09/21/java-19/&quot;&gt;Java 19&lt;/a&gt; is changing everything.
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IO&lt;/code&gt; has been great, with libraries like &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats-Effect&lt;/a&gt; and &lt;a href=&quot;https://fs2.io/&quot;&gt;fs2&lt;/a&gt; taking functional programming on the JVM to new levels, and using these libraries has been a super-power. But here I’m going to argue that the problem hasn’t been imperative programming, and this IO-driven style of static FP has an identity crisis on its hands, due to the introduction of Virtual Threads (&lt;a href=&quot;https://openjdk.org/jeps/425&quot;&gt;JEP 425&lt;/a&gt;), and the adoption of “&lt;a href=&quot;https://en.wikipedia.org/wiki/Structured_concurrency&quot;&gt;structured concurrency&lt;/a&gt;” concepts (&lt;a href=&quot;https://openjdk.org/jeps/428&quot;&gt;JEP 428&lt;/a&gt;), first popularized in &lt;a href=&quot;https://kotlinlang.org/docs/coroutines-overview.html&quot;&gt;Kotlin&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;how-io-shines&quot;&gt;How IO shines&lt;/h2&gt;

&lt;p&gt;When you have the time, you should watch Daniel Spiewak’s presentation:&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=qgfCmQ-2tW0&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/qgfCmQ-2tW0/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=qgfCmQ-2tW0&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      The Case For Effect Systems — Daniel Spiewak
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I loved it, and I’ve long been a proponent of &lt;code&gt;IO&lt;/code&gt;, having exactly these arguments. And yet …&lt;/p&gt;

&lt;h2 id=&quot;a-history-of-asynchrony&quot;&gt;A history of asynchrony&lt;/h2&gt;

&lt;p&gt;I once wrote an article on &lt;a href=&quot;https://alexn.org/blog/2017/01/30/asynchronous-programming-scala/&quot;&gt;asynchronous programming&lt;/a&gt;, in which I explained the progression from callbacks to monads. Here’s the TL;DR …&lt;/p&gt;

&lt;p&gt;If we are to describe asynchronous computations with a type, it would go something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Callback[-A] = (A) =&gt; Unit

type Async[+A] = (Callback[A]) =&gt; Unit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, an async computation is something that executes &lt;em&gt;somewhere else&lt;/em&gt;, other than the current thread, so it could be on another thread, or another process, or on another machine on the network.&lt;/p&gt;

&lt;p&gt;Now, imagine a classic sequence of synchronous function calls:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val x = foo();
val y = bar(x);
baz();
val z = qux(x, y);
return z
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can turn these into a callback-driven sequence, which is what would happen in JavaScript/Node.js land, before the advent of &lt;code&gt;Promise&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def foo(): A = ???
// ...becomes...
def foo(): Async[A] = ???

//...
// Sequence becomes:
foo()(x =&gt;
  bar(x)(y =&gt;
    baz()(_ =&gt;
      qux(x, y)(z =&gt; ???)
    )
  )
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are consequences for working like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;callback hell, due to all the nesting;&lt;/li&gt;
  &lt;li&gt;the implementation is often stack-unsafe, so it can be hard and error-prone to express loops;&lt;/li&gt;
  &lt;li&gt;it invalidates standard language features (e.g., &lt;code&gt;try/catch/finally&lt;/code&gt;);&lt;/li&gt;
  &lt;li&gt;it’s very low level, so managing concurrency is tricky (e.g., waiting on 2 or more jobs running in parallel to finish);&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Scala, the answer has been the introduction of &lt;code&gt;Future&lt;/code&gt;/&lt;code&gt;Promise&lt;/code&gt;, which is a “monadic” type, implementing a &lt;code&gt;flatMap&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code

def foo(): Future[A] = ???
//...

foo().flatMap { x =&gt;
  bar(x).flatMap { y =&gt;
    baz().flatMap(_ =&gt; qux(x, y))
  }
}
// ...or...
for {
  x &lt;- foo()
  y &lt;- bar(x)
  _ &lt;- baz()
  r &lt;- qux(x, y)
} yield r
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which kind of looks like our original, imperative, synchronous program. But, here be dragons — what happens if we invoke Future-driven functions outside that for-expression?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code
val b = baz()
for {
  x &lt;- foo()
  y &lt;- bar(x)
  _ &lt;- b
  r &lt;- qux(x, y)
} yield r
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The non-obvious answer is &lt;em&gt;concurrent execution&lt;/em&gt; happens — this is no longer a sequence of steps, and it wasn’t necessarily what we wanted, leading to bugs, as the logic may access shared mutable state that may be broken by concurrent access. This is invalidating our common sense, because when we see &lt;code&gt;val b = baz()&lt;/code&gt; in code, we do not expect concurrent execution, as it’s not how our brains have been trained in these imperative programming languages. This here invalidates our mental model for how things behave.&lt;/p&gt;

&lt;p&gt;Note that we were careful waiting on the result of &lt;code&gt;baz()&lt;/code&gt;. What happens if we forget about it?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code
val b = baz()
for {
  x &lt;- foo()
  y &lt;- bar(x)
  r &lt;- qux(x, y)
} yield r
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, this is triggering a “fire and forget” job, and if it wasn’t intended, we may now have a leak 🙀&lt;/p&gt;

&lt;h2 id=&quot;imperative-programming-the-devil-we-know&quot;&gt;Imperative programming, the devil we know&lt;/h2&gt;

&lt;p&gt;“Imperative programming” is a paradigm that focuses on describing a program &lt;em&gt;step by step&lt;/em&gt;, via a sequence of instructions that modify state. And I’m going to make this statement:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Imperative programming is extraordinarily intuitive!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In imperative programming &lt;code&gt;;&lt;/code&gt; is a separator between instructions, or statements. Imperative programming tends to be statement-oriented. But &lt;code&gt;;&lt;/code&gt; simply denotes &lt;em&gt;sequencing&lt;/em&gt; of steps. We can think of it as being an operator:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;A ; B ; C
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The above simply means statement &lt;code&gt;A&lt;/code&gt; gets executed before statement &lt;code&gt;B&lt;/code&gt;, which gets executed before statement &lt;code&gt;C&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can follow sequential steps towards achieving something. For example a vast majority of humans can cook, including many children. We may be bad cooks, we may only know simple recipes, given access to a stove we may hurt ourselves, but give people the raw ingredients and the cookware, and they won’t starve. Children understand cooking too, being a sequence of steps, not rocket science.&lt;/p&gt;

&lt;p&gt;My CS teacher from high school introduced us to algorithms with a recipe for pancakes. I don’t remember the specifics, and it’s been years since I cooked pancakes, so my memory is hazy, but I imagine the recipe went something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// As an introductory lesson, he was completely ignoring resource safety, ofc:
val fryingPan = takeFryingPan(); // 1
val batter = mix(eggs, milk, flour, sugar, bakingPowder, salt); // 2
fryingPan.pour(oil); // 3
fryingPan.preHeat(2.minutes); // 4
fryingPan.pour(batter); // 5

while (!fryingPan.check(isContentsBrown)) { // 6
 sleep(30.seconds); // 7
 fryingPan.scoop(); // 8
}

fryingPan.pull(); // 9
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our &lt;code&gt;IO&lt;/code&gt;-driven programming is still a sequence of steps. We may try to describe pure data structures that get interpreted later, but that seldom happens. In our FP programs, what actually happens in practice is still imperative in nature:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code
for {
  fryingPan &lt;- takeFryingPan()
  batter &lt;- mix(eggs, milk, flour, sugar, bakingPowder, salt)
  _ &lt;- fryingPan.pour(oil)
  _ &lt;- fryingPan.preHeat(2.minutes)
  _ &lt;- fryingPan.pour(batter)
  _ &lt;- {
    def loop(): IO[Unit] =
      fryingPan.check(isBrown).flatMap {
        case true =&gt;
          IO.unit
        case false =&gt;
          IO.sleep(30.seconds).flatMap(_ =&gt; loop())
      }
    loop()
  }
  r &lt;- fryingPan.pull()
} yield r
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In Haskell, and in the Scala FP community, the semicolon (&lt;code&gt;;&lt;/code&gt;) gets replaced with &lt;code&gt;flatMap&lt;/code&gt; (AKA &lt;code&gt;bind&lt;/code&gt;, &lt;code&gt;&gt;&gt;=&lt;/code&gt;, &lt;code&gt;SelectMany&lt;/code&gt;, etc.).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;A ; B ; C;

// becomes...

A.flatMap(_ =&gt; B).flatMap(_ =&gt; C)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is made digestible via syntactic sugar. In Haskell that’s the &lt;a href=&quot;https://en.wikibooks.org/wiki/Haskell/do_notation&quot;&gt;do-notation&lt;/a&gt;, in Scala we have the &lt;a href=&quot;https://docs.scala-lang.org/tour/for-comprehensions.html&quot;&gt;for comprehensions&lt;/a&gt;, and in F# we have &lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions&quot;&gt;computation expressions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So our Scala programs can look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code
for {
  x &lt;- foo()
  y &lt;- bar(x)
  _ &lt;- baz()
  z &lt;- qux(x, y)
} yield z
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is similar to what we did with &lt;code&gt;Future&lt;/code&gt;. In Scala this syntactic sugar is more generic, driven by monadic types, because in languages such as C# or TypeScript/JavaScript, we have special &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntax that only works with &lt;code&gt;Future&lt;/code&gt;/&lt;code&gt;Promise&lt;/code&gt;/&lt;code&gt;Task&lt;/code&gt; data types and that looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// JavaScript code
async function doStuff() {
  const x = await foo()
  const y = await bar(x)
  await baz() // better not forget the `await` 😉
  const z = await qux(x, y)
  return z
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Call-sites of functions returning &lt;code&gt;IO&lt;/code&gt;, however, are &lt;a href=&quot;https://en.wikipedia.org/wiki/Referential_transparency&quot;&gt;referentially transparent&lt;/a&gt;. And it’s important to contrast with &lt;code&gt;Future/Promise&lt;/code&gt;. Take for example this program:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code
for {
  x &lt;- fireRocketsToMars()
  y &lt;- fireRocketsToMars()
} yield x + y

// ... versus ...

val r = fireRocketsToMars()
for {
  x &lt;- r
  y &lt;- r
} yield x + y

// ... versus ...

val rx = fireRocketsToMars()
val ry = fireRocketsToMars()
for {
  x &lt;- rx
  y &lt;- ry
} yield x + y
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What’s the difference of behavior between &lt;code&gt;IO&lt;/code&gt; and &lt;code&gt;Future&lt;/code&gt; in this case?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code

def fireRocketsToMars(): IO[Int]
// ... versus ...
def fireRocketsToMars(): Future[Int]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, with &lt;code&gt;IO&lt;/code&gt; the behavior of the program is the same, in all 3 cases, whereas with &lt;code&gt;Future&lt;/code&gt; the behavior changes. With &lt;code&gt;Future&lt;/code&gt; we can talk of 3 different programs with wildly different behavior. And that’s not good, as it can be counter-intuitive, being a source of bugs.  &lt;code&gt;IO&lt;/code&gt; in this case behaves as it should, although in the context of Scala, &lt;code&gt;IO&lt;/code&gt; isn’t without fault either.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code

// No concurrent execution here, but we never use this value,
// so this is a hard to trace no-op:
val bazJob = baz()
for {
  x &lt;- foo()
  y &lt;- bar(x)
  z &lt;- qux(x, y)
} yield z
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Speaking of, I am asking questions on this difference of behavior in interviews. Surprisingly, many people get this wrong, in spite of having experience with real-world &lt;code&gt;IO&lt;/code&gt; usage. And that’s not their fault. The fault lies with the Scala language, because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;code&gt;Future&lt;/code&gt; is a broken abstraction, completely beyond redemption, not much better than the callback hell it improves on, and the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntactic sugar is only an ineffective band-aid — &lt;code&gt;async&lt;/code&gt; doesn’t help, as the default evaluation model should never be concurrent execution, you shouldn’t need to mention an explicit&lt;code&gt;await&lt;/code&gt; to force sequencing;&lt;/li&gt;
  &lt;li&gt;Scala, here, suffers from a severe case of &lt;a href=&quot;https://en.wikipedia.org/wiki/There&apos;s_more_than_one_way_to_do_it&quot;&gt;TIMTOWTDI&lt;/a&gt;, because it’s a strict language, and has multiple ways of expressing the sequencing of instructions, and it’s no wonder that beginners are getting confused;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;More on that later, but first a rant on math 😎&lt;/p&gt;

&lt;h3 id=&quot;math-is-not-intuitive&quot;&gt;Math is not intuitive&lt;/h3&gt;

&lt;p&gt;Math is abstraction, and it takes maturity to learn math abstraction. Some people never do. My high-school teacher used to say that there are two kinds of students, those that understand the formal definitions of limits (with the epsilon notation), and those that don’t. I always thought that’s just a language problem, use better communication and more people will understand, but it’s without doubt that children need to develop the necessary cognitive abilities before understanding abstraction.&lt;/p&gt;

&lt;p&gt;This is important to realize, because, while &lt;code&gt;IO&lt;/code&gt;-driven programs are very much imperative in nature, laziness brings us closer to math. It’s why languages like Haskell may never be in top 5, or why Scala can have a lot of accidental complexity. In &lt;a href=&quot;https://queue.acm.org/detail.cfm?id=2611829&quot;&gt;Curse of the Excluded Middle&lt;/a&gt;, Erik Meijer argues just that … in imperative, strictly-evaluated languages, lazy behavior is surprising, and that’s bad.&lt;/p&gt;

&lt;p&gt;I’d argue that laziness can be surprising in general, even if you’re working in a non-strict language, such as Haskell. Haskell’s non-strict evaluation keeps people honest. You can always call &lt;code&gt;unsafePerformIO&lt;/code&gt; to trigger side effects that aren’t tracked by the type system, but it’s tricky getting the runtime to actually evaluate it, esp if you don’t need the returned result. This means that shortcuts meant for debugging are hard (e.g., logging), and this can surprise people. And no sufficiently smart compiler or runtime has been invented yet to solve efficiency issues, which are a problem, because performance is hard to reason about when thunks get lazily evaluated, even in terms of big-O complexity. Data structures, at least, are meant to be already evaluated and inspectable. When that doesn’t happen (e.g., streams), that’s “codata”, it takes (runtime) effort to inspect such values, and Haskell seriously blurs the lines between them.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
For Haskell developers out there that disagree, I have a question — in your programs, are you using &lt;code&gt;String&lt;/code&gt;, or are you using &lt;code&gt;Text&lt;/code&gt;?
&lt;/p&gt;

&lt;p&gt;There are many things I like about doing FP in Scala, and having strict evaluation as the default is one of them.&lt;/p&gt;

&lt;h2 id=&quot;future-is-bad-because-asynchrony-is-bad&quot;&gt;Future is bad because asynchrony is bad&lt;/h2&gt;

&lt;p&gt;When I say that &lt;code&gt;Future&lt;/code&gt; is broken, the reason is that its usage is prone to accidents. &lt;code&gt;Future&lt;/code&gt; is an honest representation of asynchronous computations, and that’s not the fault of imperative programming.&lt;/p&gt;

&lt;p&gt;To wit, we started from this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code

def fireRocketsToMars(): IO[Int]
// ... versus ...
def fireRocketsToMars(): Future[Int]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But there is a third option that we did not take into account, which is blocking I/O:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def fireRocketsToMars(): Int
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With blocking I/O expressed like this, we have no need for &lt;code&gt;flatMap&lt;/code&gt; or for special sequencing syntax, as it’s pretty damn clear what’s going on — at least in terms of sequencing of steps. It’s not all rosy, my problem being that the signature is lying, as it doesn’t make it clear that there are dangerous side effects going on (but in Scala &lt;a href=&quot;https://alexn.org/blog/2022/05/23/tracking-effects-in-scala/&quot;&gt;this could be fixed&lt;/a&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val x = fireRocketsToMars();
val y = fireRocketsToMars();
x + y
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’s important to realize the virtues of doing this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;if everything becomes synchronous/blocking by default, there are no accidents related to accidental concurrent execution;&lt;/li&gt;
  &lt;li&gt;the distinction between data and codata (i.e., data structures versus computations) becomes clear as day;&lt;/li&gt;
  &lt;li&gt;standard language constructs still work (e.g., for/while loops, &lt;code&gt;try-catch-finally&lt;/code&gt;, &lt;code&gt;try-with-resources&lt;/code&gt; or Java’s checked exceptions);&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the other sample, again:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val x = foo();
val y = bar(x);
baz();
val z = qux(x, y);
return z
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’d argue that there is no meaningful difference between this, and the equivalent IO-driven program, at least in terms of accidents that can happen. If this were &lt;code&gt;Future&lt;/code&gt;-driven, a lot of things could go wrong because all of those invocations could be concurrent, by accident. But we are not using &lt;code&gt;Future&lt;/code&gt; here.&lt;/p&gt;

&lt;p&gt;There can be no accidents here, because once the execution returns from a function invocation, that function is done. And having this mental model is awesome.&lt;/p&gt;

&lt;h2 id=&quot;java-whats-old-is-new-again&quot;&gt;Java: what’s old is new again&lt;/h2&gt;

&lt;p&gt;Blocking I/O has always been the norm in Java land. Java was built for using threads, and for blocking those threads. Java’s memory model, the ease of working with threads, was one of its main innovations.&lt;/p&gt;

&lt;p&gt;This is why Java’s standard library is filled with concurrency primitives that block, such as &lt;code&gt;BlockingQueue&lt;/code&gt;, &lt;code&gt;Semaphore&lt;/code&gt;, &lt;code&gt;ReadWriteLock&lt;/code&gt; or &lt;code&gt;ReentrantLock&lt;/code&gt;, with no async equivalents. It’s why Java has a &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/Future.html&quot;&gt;Future&lt;/a&gt; interface whose only means of getting its result is a blocking &lt;code&gt;.get()&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;The newer &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CompletableFuture.html&quot;&gt;CompletableFuture&lt;/a&gt; happened in Java 8. Java 8 also introduced lambda expressions, so you can feel that was about the time asynchronous programming APIs took off, as a sort of detour from the official way of doing things.&lt;/p&gt;

&lt;p&gt;And this is because Java does “&lt;a href=&quot;https://en.wikipedia.org/wiki/Thread_(computing)#Threading_models&quot;&gt;1:1 kernel-level threading&lt;/a&gt;”, meaning that all Java threads are OS/platform threads, and platform threads are super expensive. This is because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;each thread has its own call-stack, thus consuming memory;&lt;/li&gt;
  &lt;li&gt;the kernel does “preemptive multithreading”, so it does its best to execute many threads on few CPU cores — to do this, the kernel assigns time slots, pausing running threads, resuming previously paused threads, in a process called “context switching” — during which the memory used by a thread needs to be reloaded in a CPU’s cache hierarchy, which consumes a lot of CPU;&lt;/li&gt;
  &lt;li&gt;due to consumption of both memory and CPU, there’s a low limit on how many threads you can use;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The answer in Java land has been to work with thread-pools, to reuse available threads as much as possible, and to limit the maximum number of threads that can be started. Thread-pools are problematic as well, because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;code&gt;ThreadLocal&lt;/code&gt; values can now leak, and thread interruption is very unsafe if you don’t own the thread;&lt;/li&gt;
  &lt;li&gt;Complicated libraries tend to start their own thread-pool, and you can assess the maturity of Java projects by the number of thread-pools active at the same time;&lt;/li&gt;
  &lt;li&gt;Blocking I/O makes limiting threads hard, because you can end up with thread-starvation, a type of deadlock, a situation in which threads are unable to make progress due to hard limits on the thread-pool;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And managing threads and thread-pools being low level, the community evolved towards using “reactive”/fluent APIs, such as &lt;a href=&quot;https://github.com/ReactiveX/RxJava&quot;&gt;RxJava&lt;/a&gt;, &lt;a href=&quot;https://projectreactor.io/&quot;&gt;Project Reactor&lt;/a&gt;, &lt;a href=&quot;https://akka.io/&quot;&gt;Akka&lt;/a&gt;, and others. Which are essentially libraries meant to recreate “M:N threading” on top of the JVM, i.e., multiplexing many jobs on few OS/platform threads.&lt;/p&gt;

&lt;p&gt;Java 19 introduces “virtual threads”, bringing M:N threading support at the runtime level, which makes threads, and blocking I/O cheap. It’s not perfect, as the JVM can still block OS threads, generating “pinned” events in “flight recorder”, which I’m sure will be the new bread and butter of profilers everywhere. But everything in the language and the standard library starts making sense again. All those APIs built for blocking suddenly become much cheaper to use, effectively obsoleting the &lt;code&gt;Future&lt;/code&gt; data types.&lt;/p&gt;

&lt;h2 id=&quot;structured-concurrency&quot;&gt;Structured concurrency&lt;/h2&gt;

&lt;p&gt;Thus far we’ve seen that sequential / synchronous execution is intuitive and should probably be the default, in order to prevent concurrency accidents (in our general purpose programming languages, not talking of domain-specific ones). But what if we need concurrency?&lt;/p&gt;

&lt;p&gt;“Structured concurrency”, as a concept, is similar to that of &lt;a href=&quot;https://en.wikipedia.org/wiki/Structured_programming&quot;&gt;structured programming&lt;/a&gt;. Back in the day, when GOTO-driven languages were still used, introductory CS lessons included an incursion into structured programming and why it is needed.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-structured-programming.png&quot; alt=&quot;&quot; class=&quot;transparency-fix&quot; width=&quot;1872&quot; height=&quot;1053&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    Old-school structured programming diagram, showing Euclid&apos;s algorithm for the &quot;greatest common divisor&quot;.
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The problem with GOTO statements is that they create a fork in the road, the program’s flow becoming very hard to follow, leading to unmaintainable code. Edsger Dijkstra called GOTO statements harmful, because it complicates program analysis, verifying the correctness of algorithms becoming difficult, particularly the correctness of loops.&lt;/p&gt;

&lt;p&gt;In the context of concurrency, this should sound very familiar. With classical Java, concurrent execution would look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Java code
final var mixJob =
  ec.submit(() -&gt;
    mix(eggs, milk, flour, sugar, bakingPowder, salt)
  );

final var prepareFryingPanJob =
  ec.submit(() -&gt; {
    final var fryingPan = takeFryingPan();
    fryingPan.pour(oil);
    fryingPan.preHeat(Duration.ofMinutes(2));
    return fryingPan;
  });

final var fryingPan = prepareFryingPanJob.get();
final var batter = mixJob.get();
//...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We now have concurrent execution, making more efficient use of our resources. But therein lie problems:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;if &lt;code&gt;prepareFryingPanJob.get()&lt;/code&gt; throws an exception, the execution of &lt;code&gt;mixJob&lt;/code&gt; won’t get cancelled, thus creating a leak;&lt;/li&gt;
  &lt;li&gt;if the current thread gets interrupted, the interruption signal doesn’t propagate to the started concurrent tasks;&lt;/li&gt;
  &lt;li&gt;if &lt;code&gt;prepareFryingPanJob&lt;/code&gt; takes a long time to execute, but &lt;code&gt;mixJob&lt;/code&gt; fails immediately, we won’t see that failure until &lt;code&gt;prepareFryingPanJob&lt;/code&gt; finishes;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Kotlin’s coroutines did not introduce the notion of “structured concurrency”, but I think it popularized it. The basic idea is this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Concurrent jobs should be cancellable;&lt;/li&gt;
  &lt;li&gt;Concurrent jobs get started in a “scope”, and that scope can’t finish until all started concurrent jobs finish or get cancelled;&lt;/li&gt;
  &lt;li&gt;On error, all running concurrent jobs get cancelled;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is similar to the idea behind C++’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization&quot;&gt;RAII&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// Kotlin code
coroutineScope {
  val mixJob = async {
    mix(eggs, milk, flour, sugar, bakingPowder, salt)
  }
  val prepareFryingPanJob = async {
    val fryingPan = takeFryingPan()
    fryingPan.pour(oil)
    fryingPan.preHeat(2.minutes)
    fryingPan
  }

  val fryingPan = prepareFryingPanJob.await()
  val mix = mixJob.await()
  //...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In Kotlin, if the code of such a &lt;code&gt;coroutineScope&lt;/code&gt; throws an error, all its concurrent jobs gets cancelled. The scope also awaits all concurrent jobs to finish, before it can finish, so there can be no accidental “fire and forget” jobs. And if any of the concurrent jobs throws an exception, then the other concurrent job gets cancelled.&lt;/p&gt;

&lt;p&gt;Java 19 also introduced very experimental extensions for doing the same, in &lt;a href=&quot;https://openjdk.org/jeps/428&quot;&gt;JEP 428&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// Java code
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
  final var mixJob =
    scope.submit(() -&gt;
      mix(eggs, milk, flour, sugar, bakingPowder, salt)
    );

  final var prepareFryingPanJob =
    scope.submit(() -&gt; {
      final var fryingPan = takeFryingPan();
      fryingPan.pour(oil);
      fryingPan.preHeat(Duration.ofMinutes(2));
      return fryingPan;
    });

  scope.join();
  scope.throwIfFailed();

  final var fryingPan = prepareFryingPanJob.resultNow();
  final var batter = mixJob.resultNow();
  //...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This API is currently “incubating” and looks clumsy, but the concept is the same, and its efficient use is made possible due to blocking I/O becoming cheap.&lt;/p&gt;

&lt;p&gt;What would we do in Scala with Cats-Effect’s &lt;code&gt;IO&lt;/code&gt;?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Scala code

// No-op
val mixJob =
  mix(eggs, milk, flour, sugar, bakingPowder, salt)

// No-op
val prepareFryingPanJob =
  for {
    fryingPan &lt;- takeFryingPan
    _ &lt;- fryingPan.pour(oil)
    _ &lt;- fryingPan.preHeat(2.minutes)
  } yield fryingPan

(mixJob, prepareFryingPanJob).parMapN { (mx, fryingPan) =&gt;
  //...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With Cats-Effect &lt;code&gt;IO&lt;/code&gt; concurrency/parallel execution must be made explicit. Here we are using the &lt;code&gt;parMapN&lt;/code&gt; operator from the &lt;a href=&quot;https://typelevel.org/cats/typeclasses/parallel.html&quot;&gt;Parallel&lt;/a&gt; type class. The creation of those tasks is lazy. Nothing gets executed then and there. This makes it a little clumsy, so you’d better turn your linter to warn against unused values.&lt;/p&gt;

&lt;p&gt;But this raises important questions — in this context, what does &lt;code&gt;IO&lt;/code&gt; buy us? I’m finding this question increasingly difficult to answer. I used to say that &lt;code&gt;IO&lt;/code&gt; is very explicit about how things get evaluated (e.g., in parallel or sequential), so there can be no accidents, but &lt;code&gt;IO&lt;/code&gt; isn’t the only way for achieving that. And due to its laziness, it introduces some accidental complexity of its own.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IO&lt;/code&gt; is very composable. You can, for example, combine it with &lt;code&gt;Either&lt;/code&gt;, via &lt;code&gt;EitherT&lt;/code&gt;. Or you can bake &lt;code&gt;EitherT&lt;/code&gt; in, like what ZIO did.&lt;/p&gt;

&lt;p&gt;But with blocking I/O, in Java, you can make use of checked exceptions again. And for Kotlin, checkout &lt;a href=&quot;https://arrow-kt.io/&quot;&gt;Arrow&lt;/a&gt;, see their article on &lt;a href=&quot;https://arrow-kt.io/docs/effects/io/&quot;&gt;why &lt;code&gt;suspend () -&gt; A&lt;/code&gt; instead of &lt;code&gt;IO&lt;A&gt;&lt;/code&gt;&lt;/a&gt;. If typed exceptions is your cup of team, here’s how that sample would look like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// Kotlin code
suspend fun makePancakes(): Either&lt;SomeError, Pancakes&gt; =
  either {
    val fryingPan = takeFryingPan().bind()
    val batter = mix(eggs, milk, flour, sugar, bakingPowder, salt).bind()
    fryingPan.pour(oil).bind()
    fryingPan.preHeat(2.minutes).bind()
    fryingPan.pour(batter).bind()
    //...
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For another more real use-case, here’s a snippet from my own &lt;a href=&quot;https://github.com/alexandru/github-webhook-listener/blob/v2.1.2/src/main/kotlin/org/alexn/hook/Server.kt#L85&quot;&gt;personal project&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// Kotlin code
either {
    val project = Either
        .fromNullable(config.projects[projectKey])
        .mapLeft { RequestError.NotFound(&quot;Project `$projectKey` does not exist&quot;) }
        .bind()
    val signature = call.request.header(&quot;X-Hub-Signature-256&quot;)
        ?: call.request.header(&quot;X-Hub-Signature&quot;)

    val body = call.receiveText()
    EventPayload
        .authenticateRequest(body, project.secret, signature)
        .bind()

    val parsed =
        EventPayload.parse(call.request.contentType(), body).bind()
    val result = if (parsed.shouldProcess(project)) {
        commandTriggerService.triggerCommand(projectKey)
    } else {
        RequestError.Skipped(&quot;Nothing to do for project `$projectKey`&quot;).left()
    }
    result.bind()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This isn’t different from what was tried in Scala via attempts like &lt;a href=&quot;https://github.com/monadless/monadless&quot;&gt;Monadless&lt;/a&gt;, a use-case that Kotlin’s coroutines makes comfortable. In my opinion, if Scala continues to embrace &lt;code&gt;flatMap&lt;/code&gt;, then it should expand the syntax of “for comprehensions” to be more ergonomic. F#’s “computation expressions” look more like imperative programming, going beyond &lt;code&gt;flatMap&lt;/code&gt; and blending better within F#’s syntax, and that’s good.&lt;/p&gt;

&lt;h2 id=&quot;in-closing&quot;&gt;In closing&lt;/h2&gt;

&lt;p&gt;Functions working with monadic types, such as &lt;code&gt;IO&lt;/code&gt;, are referentially transparent, following the substitution model of evaluation, and facilitate algebraic reasoning. But showing what that is good for can be a challenge, especially in light of the TIMTOWTDI.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IO&lt;/code&gt; is awesome, but its existence in strictly-evaluated languages is increasingly questionable. Even in Scala land, many developers don’t believe that monads are the only or the best way to deal with effects, even if (I bet) the community’s opinion is increasingly biased, due to the natural churn that happens (people that like monads may stick around more than those that don’t). I’m happy that proposals for alternatives still happen (even if they may go nowhere), checkout: &lt;a href=&quot;https://contributors.scala-lang.org/t/pre-sip-suspended-functions-and-continuations/5801&quot;&gt;PRE-SIP: Suspended functions and continuations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IO&lt;/code&gt; (and monads in general) on the JVM can have a bright future, but need better stories to tell.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/10/13/the-case-against-effect-systems-io-data-type/?pk_campaign=rss&quot;&gt;The case against Effect Systems (e.g., the IO data type)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 13 Oct 2022 09:00:00 +0000</pubDate>
  <dc:modified>Tue, 18 Oct 2022 17:02:09 +0000</dc:modified>
  <atom:modified>Tue, 18 Oct 2022 17:02:09 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/10/13/the-case-against-effect-systems-io-data-type/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/10/13/the-case-against-effect-systems-io-data-type/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>FSharp</category>
  <category>Java</category>
  <category>Kotlin</category>
  <category>Scala</category>
  </item>


<item>
  <title>Execute Shell Commands in Java/Scala/Kotlin</title>
  <description>The following describes snippets for executing shell commands, in Java, Scala, and Kotlin, using standard functionality. It’s also useful to compare Java vs Scala vs Kotlin for this particular problem.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/10/03/execute-shell-commands-in-java-scala-kotlin/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-exec-shell-command.png?202603060940&quot; alt=&quot;&quot; width=&quot;2024&quot; height=&quot;1012&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
The following describes snippets for executing shell commands, in Java, Scala, and Kotlin, using standard functionality. It’s also useful to compare Java vs Scala vs Kotlin for this particular problem.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
These snippets make use of &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Runtime.html#exec(java.lang.String%5B%5D)&quot;&gt;Runtime.getRuntime().exec&lt;/a&gt;. You may find libraries that already do this, but I find dependencies to be a risk, and wheel reinvention to be fun. I apologize for the NIH in advance.
&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
&lt;strong&gt;UPDATE (2022-10-05):&lt;/strong&gt; all code samples were updated to concurrently collect the output from the input streams. This makes the code more foolproof, as programs with a lot of output can overflow a stream’s buffer.
&lt;/p&gt;

&lt;p&gt;This article is a follow-up to: &lt;a href=&quot;https://alexn.org/blog/2020/12/06/execute-shell-command-in-fsharp/&quot;&gt;execute shell commands in F#&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;This has been developed with Java 17, so please excuse the use of newer syntax additions, such as “record”, or “var”. The only dependency that this declares is Apache’s &lt;a href=&quot;https://commons.apache.org/proper/commons-text/&quot;&gt;commons-text&lt;/a&gt;, because we need to do proper escaping of shell arguments:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;///usr/bin/env jbang &quot;$0&quot; &quot;$@&quot; ; exit $?
//JAVA 17+
//DEPS org.apache.commons:commons-text:1.9

import org.apache.commons.text.StringEscapeUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.stream.Collectors;

record CommandResult(
  int exitCode,
  String stdout,
  String stderr
) {}

class OSUtils {
  /**
   * Executes a program. This needs to be a valid path on the
   * file system.
   * &lt;p&gt;
   * See {@link #executeShellCommand(ExecutorService, String, String...)}
   * for the version that executes `/bin/sh` commands.
   */
  public static CommandResult executeCommand(
    ExecutorService es,
    Path executable,
    String...args
  ) throws IOException, InterruptedException {
    Objects.requireNonNull(executable);
    Objects.requireNonNull(args);

    final var commandArgs = prepend(
      executable.toAbsolutePath().toString(),
      args
    );
    final var proc = Runtime.getRuntime().exec(commandArgs);
    Future&lt;byte[]&gt; stdout = null;
    Future&lt;byte[]&gt; stderr = null;
    try {
      // Reading output streams in parallel
      stdout = es.submit(() -&gt; proc.getInputStream().readAllBytes());
      stderr = es.submit(() -&gt; proc.getErrorStream().readAllBytes());
      return new CommandResult(
        proc.waitFor(),
        // Should both be ready after `waitFor`
        new String(stdout.get(), StandardCharsets.UTF_8),
        new String(stderr.get(), StandardCharsets.UTF_8)
      );
    } catch (ExecutionException e) {
      throw new RuntimeException(e);
    } finally {
      // Should close streams as well:
      proc.destroy();
      // Idempotent — it&apos;s fine if already complete:
      TaskUtils.cancelAll(stdout, stderr);
    }
  }

  /**
   * Executes shell commands.
   * &lt;p&gt;
   * WARN: command arguments need be given explicitly because
   * they need to be properly escaped.
   */
  public static CommandResult executeShellCommand(
    ExecutorService es,
    String command,
    String... args
  ) throws IOException, InterruptedException {
    Objects.requireNonNull(command);
    Objects.requireNonNull(args);

    final String shellCommand = Arrays
      .stream(prepend(command, args))
      .map(StringEscapeUtils::escapeXSI)
      .collect(Collectors.joining(&quot; &quot;));

    return executeCommand(
      es,
      Path.of(&quot;/bin/sh&quot;),
      &quot;-c&quot;,
      shellCommand
    );
  }

  private static String[] prepend(String elem, String[] array) {
    final var newArray = new String[array.length+1];
    newArray[0] = elem;
    System.arraycopy(array, 0, newArray, 1, array.length);
    return newArray;
  }
}

class TaskUtils {
  public static &lt;A&gt; A withTimeout(
    ExecutorService es,
    Duration timeout,
    Callable&lt;A&gt; task
  ) throws InterruptedException, TimeoutException {
    final var ft = new FutureTask&lt;&gt;(task);
    try {
      es.submit(ft);
      return ft.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
    } catch (ExecutionException e) {
      ft.cancel(true);
      throw new RuntimeException(e);
    } catch (Exception e) {
      ft.cancel(true);
      throw e;
    }
  }

  public static void cancelAll(Future&lt;?&gt;...futures) {
    for (final var f : futures)
      if (f != null) {
        f.cancel(true);
      }
  }
}

class Main {
  public static void main(String[] args) throws Exception {
    final var es = Executors.newCachedThreadPool();
    try {
      final var r =
        TaskUtils.withTimeout(es, Duration.ofSeconds(2), () -&gt;
          OSUtils.executeShellCommand(es, &quot;ls&quot;, &quot;-alh&quot;)
        );
      System.out.print(r.stdout());
      System.out.print(r.stderr());
      System.exit(r.exitCode());
    } finally {
      es.shutdown();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;scripting-with-java&quot;&gt;Scripting with Java&lt;/h3&gt;

&lt;p&gt;The above sample is an executable script, you can play with it directly via &lt;a href=&quot;https://www.jbang.dev/&quot;&gt;JBang&lt;/a&gt;. On macOS this can be easily installed via:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;brew install jbang

# You might want this too:
brew install openjdk@17
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Save the above script as &lt;code&gt;runCommand.java&lt;/code&gt;. You can then execute the script above:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;jbang ./runCommand.java

# Or make the script executable; works due to the included &apos;shebang&apos;
# (https://en.wikipedia.org/wiki/Shebang_(Unix))
chmod +x ./runCommand.java

# And then run it directly
./runCommand.java
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;notes-on-concurrency-in-java&quot;&gt;Notes on concurrency in Java&lt;/h3&gt;

&lt;p&gt;The code needs an explicit &lt;code&gt;ExecutorService&lt;/code&gt; because we need concurrent execution for:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;reading the STDOUT and STDERR input streams;&lt;/li&gt;
  &lt;li&gt;triggering a timeout with interruption of the running process;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I don’t like passing explicit &lt;code&gt;ExecutorService&lt;/code&gt; references, because blocking I/O is best executed on top of unbounded thread-pools, so the configuration is error-prone. On the other hand, platform threads are expensive, and I also don’t like libraries that initiate their own thread-pools for blocking I/O. This is why I’m very happy about the upcoming &lt;a href=&quot;https://openjdk.org/jeps/425&quot;&gt;Virtual Threads&lt;/a&gt; from Java 19.&lt;/p&gt;

&lt;p&gt;To collect the input streams in parallel, we submit 2 jobs in this thread-pool:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;Future&lt;byte[]&gt; stdout = es.submit(() -&gt; proc.getInputStream().readAllBytes());
Future&lt;byte[]&gt; stderr = es.submit(() -&gt; proc.getErrorStream().readAllBytes());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In Java, cancelling blocking I/O tasks is done via &lt;a href=&quot;https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html&quot;&gt;thread interruption&lt;/a&gt;, however it’s a low-level protocol that’s very error-prone (especially if you don’t own the threads you’re interrupting). This is why it’s best to leave interruption to higher level abstractions, like &lt;code&gt;Future&lt;?&gt;&lt;/code&gt; references initialized via &lt;code&gt;ExecutorService#submit&lt;/code&gt;.  We use &lt;code&gt;ExecutorService.submit&lt;/code&gt; in order to create &lt;code&gt;Future&lt;/code&gt; references that can be cancelled. In this case it doesn’t really help, as that &lt;code&gt;InputStream#read&lt;/code&gt; doesn’t listen to thread interruption signals, but it’s a good practice anyway, as a future implementation might be interruptible.&lt;/p&gt;

&lt;p&gt;And to have blocking I/O timing out after a timespan, we can use the same mechanism, although for such use-case you’re better off finding a library that does this better. And I am hopeful for what will come out of the additions for &lt;a href=&quot;https://openjdk.org/jeps/428&quot;&gt;structured concurrency&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public static &lt;A&gt; A withTimeout(
  ExecutorService es,
  Duration timeout,
  Callable&lt;A&gt; task
) throws InterruptedException, TimeoutException {
 final var ft = new FutureTask&lt;&gt;(task);
 try {
   es.submit(ft);
   return ft.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
 } catch (ExecutionException e) {
   ft.cancel(true);
   throw new RuntimeException(e);
 } catch (Exception e) {
   ft.cancel(true);
   throw e;
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note how I’m just using blocking I/O, and not bothering with any async abstractions here. That’s because &lt;a href=&quot;https://alexn.org/blog/2022/09/21/java-19/&quot;&gt;Java 19&lt;/a&gt; moves Java’s paradigm back to blocking I/O, and the underlying API (&lt;code&gt;Runtime#exec&lt;/code&gt;) is based on blocking I/O.&lt;/p&gt;

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

&lt;p&gt;For Scala, we’re going to introduce a &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats-Effect&lt;/a&gt; dependency to describe the above as an interruptible &lt;code&gt;IO&lt;/code&gt; data type. It’s not in the standard library, but all my Scala projects have an &lt;code&gt;IO&lt;/code&gt; data type 😎. Besides the cool factor of working with this legendary monadic type, &lt;code&gt;IO&lt;/code&gt; can handle the timeout under the hood via thread interruption:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;#!/usr/bin/env -S scala-cli shebang -q

//&gt; using scala &quot;2.13.9&quot;
//&gt; using lib &quot;org.typelevel::cats-effect::3.3.12&quot;
//&gt; using lib &quot;org.apache.commons:commons-text:1.9&quot;

import cats.effect.{ExitCode, IO, IOApp}
import cats.syntax.all._
import org.apache.commons.text.StringEscapeUtils
import java.nio.charset.StandardCharsets.UTF_8
import java.nio.file.Path
import scala.concurrent.duration._

final case class CommandResult(
  exitCode: Int,
  stdout: String,
  stderr: String,
)

object OSUtils {
  def executeCommand(executable: Path, args: String*): IO[CommandResult] =
    IO.blocking {
      val commandArgs = executable.toAbsolutePath.toString +: args
      Runtime.getRuntime.exec(commandArgs.toArray)
    }
    // A `bracket` works like `try-with-resources` or `try-finally`
    .bracket { proc =&gt;
      // These aren&apos;t &quot;interruptible&quot;, what actually interrupts them
      // is proc.destroy(); and due to how they are used, it&apos;s better
      // to not declare them as interruptible, as to not mislead:
      val collectStdout = IO.blocking {
        new String(proc.getInputStream.readAllBytes(), UTF_8)
      }
      val collectStderr = IO.blocking {
        new String(proc.getErrorStream.readAllBytes(), UTF_8)
      }
      // This is actually cancellable via thread interruption
      val awaitReturnCode = IO.interruptible {
        proc.waitFor()
      }
      for {
        // Starts jobs asynchronously
        stdoutFiber &lt;- collectStdout.start
        stderrFiber &lt;- collectStderr.start
        // Waits for process to complete
        code &lt;- awaitReturnCode
        // Reads output
        stdout &lt;- stdoutFiber.joinWithNever
        stderr &lt;- stderrFiber.joinWithNever
      } yield {
        CommandResult(code, stdout, stderr)
      }
    } { proc =&gt;
      IO.blocking {
        println(&quot;Destroying process&quot;)
        proc.destroy()
      }
    }

  def executeShellCommand(command: String, args: String*): IO[CommandResult] =
    executeCommand(
      Path.of(&quot;/bin/sh&quot;),
      &quot;-c&quot;,
      (command +: args).map(StringEscapeUtils.escapeXSI).mkString(&quot; &quot;)
    )
}

object Main extends IOApp {
  def run(args: List[String]): IO[ExitCode] =
    for {
      r &lt;- OSUtils.executeShellCommand(&quot;ls&quot;, &quot;-alh&quot;).timeout(3.seconds)
      _ &lt;- IO.print(r.stdout)
      _ &lt;- IO.print(r.stderr)
    } yield ExitCode(r.exitCode)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;scripting-with-scala&quot;&gt;Scripting with Scala&lt;/h3&gt;

&lt;p&gt;The above Scala sample is an executable script, you can play with it directly via &lt;a href=&quot;https://scala-cli.virtuslab.org/&quot;&gt;Scala CLI&lt;/a&gt;. On macOS this can be easily installed via:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;brew install Virtuslab/scala-cli/scala-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Save the above script as &lt;code&gt;runCommand.scala&lt;/code&gt;. You can then execute it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;scala-cli run ./runCommand.scala

# Or make the script executable; works due to the included &apos;shebang&apos;
# (https://en.wikipedia.org/wiki/Shebang_(Unix))
chmod +x ./runCommand.scala

# And then run it directly
./runCommand.scala
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;notes-on-concurrency-in-scala&quot;&gt;Notes on concurrency in Scala&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;IO&lt;/code&gt; can handle this automatically via its &lt;a href=&quot;https://typelevel.org/cats-effect/api/3.x/cats/effect/IO.html#timeout[A2%3E:A](duration:scala.concurrent.duration.FiniteDuration):cats.effect.IO[A2]&quot;&gt;timeout&lt;/a&gt; method:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent.duration._
//...
for {
  r &lt;- OSUtil
    .executeShellCommand(&quot;sleep&quot;, &quot;30&quot;)
    .timeout(3.seconds)
  _ &lt;- IO.print(r.stdout)
  _ &lt;- IO.print(r.stderr)
} yield ExitCode(r.exitCode)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This works because we’ve used &lt;code&gt;IO.bracket&lt;/code&gt; and the &lt;code&gt;IO.interruptible&lt;/code&gt; builder in &lt;code&gt;executeCommand&lt;/code&gt;, which knows how to cancel the running task via actual thread interruption. And &lt;code&gt;timeout&lt;/code&gt; creates a concurrent race condition, cancelling the running process after the given timespan. The Cats-Effect library is designed for safe resource acquisition and release, having cancellation baked in.&lt;/p&gt;

&lt;p&gt;Forking concurrent “fibers” happens, in this sample, via &lt;code&gt;.start&lt;/code&gt;. At the moment of writing, forked fibers aren’t getting cancelled when the main fiber is cancelled. This is because Cats-Effect has &lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/supervisor&quot;&gt;other mechanisms&lt;/a&gt; for dealing with scopes, and &lt;code&gt;.start&lt;/code&gt; is considered to be lower-level. But it was appropriate for this sample.&lt;/p&gt;

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

&lt;p&gt;For Kotlin, we are going to use its &lt;a href=&quot;https://kotlinlang.org/docs/coroutines-overview.html&quot;&gt;coroutines&lt;/a&gt; support (with the &lt;a href=&quot;https://github.com/Kotlin/kotlinx.coroutines/&quot;&gt;kotlinx.coroutines&lt;/a&gt; dependency):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;///usr/bin/env jbang &quot;$0&quot; &quot;$@&quot; ; exit $?

//JAVA 17+
//KOTLIN 1.7.20
//DEPS org.apache.commons:commons-text:1.9
//DEPS org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.runInterruptible
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import org.apache.commons.text.StringEscapeUtils
import java.nio.charset.StandardCharsets.UTF_8
import java.nio.file.Path
import kotlin.time.Duration.Companion.seconds

data class CommandResult(
  val exitCode: Int,
  val stdout: String,
  val stderr: String,
)

/**
 * Executes a program. This needs to be a valid path on the
 * file system.
 *
 * See [executeShellCommand] for the version that executes
 * `/bin/sh` commands.
 */
suspend fun executeCommand(
  executable: Path,
  vararg args: String
): CommandResult =
  // Blocking I/O should use threads designated for I/O
  withContext(Dispatchers.IO) {
    val cmdArgs = listOf(executable.toAbsolutePath().toString()) + args
    val proc = Runtime.getRuntime().exec(cmdArgs.toTypedArray())
    try {
      // Concurrent execution ensures the stream&apos;s buffer doesn&apos;t
      // block processing when overflowing
      val stdout = async {
        runInterruptible {
          // That `InputStream.read` doesn&apos;t listen to thread interruption
          // signals; but for future development it doesn&apos;t hurt
          String(proc.inputStream.readAllBytes(), UTF_8)
        }
      }
      val stderr = async {
        runInterruptible {
          String(proc.errorStream.readAllBytes(), UTF_8)
        }
      }
      CommandResult(
        exitCode = runInterruptible { proc.waitFor() },
        stdout = stdout.await(),
        stderr = stderr.await()
      )
    } finally {
      // This interrupts the streams as well, so it terminates
      // async execution, even if thread interruption for that
      // InputStream doesn&apos;t work
      proc.destroy()
    }
  }

/**
 * Executes shell commands.
 *
 * WARN: command arguments need be given explicitly because
 * they need to be properly escaped.
 */
suspend fun executeShellCommand(
  command: String,
  vararg args: String
): CommandResult =
  executeCommand(
    Path.of(&quot;/bin/sh&quot;),
    &quot;-c&quot;,
    (listOf(command) + args)
      .map(StringEscapeUtils::escapeXSI)
      .joinToString(&quot; &quot;)
  )

fun main(vararg args: String) = runBlocking {
  // Dealing with timeouts
  val r = withTimeout(3.seconds) {
    executeShellCommand(&quot;ls&quot;, &quot;-alh&quot;)
  }
  System.out.print(r.stdout)
  System.err.print(r.stderr)
  System.exit(r.exitCode)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;scripting-with-kotlin&quot;&gt;Scripting with Kotlin&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.jbang.dev/&quot;&gt;JBang&lt;/a&gt; has experimental Kotlin support. Save the above script as &lt;code&gt;runCommand.kt&lt;/code&gt;. You can then execute the script like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;jbang ./runCommand.kt

# Or make the script executable; works due to the included &apos;shebang&apos;
# (https://en.wikipedia.org/wiki/Shebang_(Unix))
chmod +x ./runCommand.kt

# And then run it directly
./runCommand.kt
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;notes-on-concurrency-in-kotlin&quot;&gt;Notes on concurrency in Kotlin&lt;/h3&gt;

&lt;p&gt;Kotlin’s coroutine jobs are &lt;a href=&quot;https://kotlinlang.org/docs/cancellation-and-timeouts.html&quot;&gt;cancellable&lt;/a&gt;. The &lt;a href=&quot;https://github.com/Kotlin/kotlinx.coroutines/issues/1947&quot;&gt;runInterruptible&lt;/a&gt; function transforms regular blocking code into a suspending function that can be cancelled, with the cancellation signal being converted into thread interruption. And by explicitly specifying &lt;code&gt;Dispatchers.IO&lt;/code&gt; as the “coroutine context”, we also require the execution to happen on the thread-pool designated for blocking I/O tasks.&lt;/p&gt;

&lt;p&gt;Due to use of the API, and due to the &lt;a href=&quot;https://www.youtube.com/watch?v=Mj5P47F6nJg&quot;&gt;structured concurrency&lt;/a&gt; design, installing timeouts works as expected:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;import kotlinx.coroutines.withTimeout
import kotlin.time.Duration.Companion.seconds

//...
val r = withTimeout(3.seconds) {
  executeShellCommand(&quot;sleep&quot;, &quot;30&quot;)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is equivalent with the Scala sample. Kotlin’s “suspended” functions are slick, for many purposes being &lt;a href=&quot;https://arrow-kt.io/docs/effects/io/&quot;&gt;equivalent with IO&lt;/a&gt; (also see &lt;a href=&quot;https://arrow-kt.io/&quot;&gt;Arrow&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;An &lt;code&gt;IO&lt;/code&gt; data type can be better due to reusability and compositionality, but it relies on &lt;code&gt;flatMap&lt;/code&gt; handling the sequencing of effects (instead of Java’s &lt;code&gt;;&lt;/code&gt;), which is at the same time a strength and a weakness — for one, it can be awkward to learn and use without syntactic sugar, it leads to more TIMTOWTDI, and it encourages reuse via a lot of &lt;a href=&quot;https://github.com/fsharp/fslang-suggestions/issues/243#issuecomment-916079347&quot;&gt;type-level programming that may be too complex&lt;/a&gt;. In Scala having &lt;a href=&quot;https://alexn.org/blog/2022/05/13/oop-vs-type-classes-part-1-ideology/&quot;&gt;type classes&lt;/a&gt; and &lt;a href=&quot;https://typelevel.org/cats/&quot;&gt;Cats&lt;/a&gt; is pretty awesome, though.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/10/03/execute-shell-commands-in-java-scala-kotlin/?pk_campaign=rss&quot;&gt;Execute Shell Commands in Java/Scala/Kotlin&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 03 Oct 2022 05:13:13 +0000</pubDate>
  <dc:modified>Wed, 05 Oct 2022 15:34:13 +0000</dc:modified>
  <atom:modified>Wed, 05 Oct 2022 15:34:13 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/10/03/execute-shell-commands-in-java-scala-kotlin/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/10/03/execute-shell-commands-in-java-scala-kotlin/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Snippet</category>
  <category>Java</category>
  <category>Scala</category>
  <category>Kotlin</category>
  </item>


<item>
  <title>The Trouble with Checked Exceptions: Part 2</title>
  <description>Java’s Checked Exceptions are problematic, and it’s not only due to their ergonomics. The bigger problem is that they are in conflict with abstraction and OOP. Also, few people care about typed exceptions (unless they are happy path results, not errors).</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/09/28/the-trouble-with-checked-exceptions-part-2/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-checked-exceptions.png?202603060940&quot; alt=&quot;&quot; width=&quot;2152&quot; height=&quot;1268&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
Java’s Checked Exceptions are problematic, and it’s not only due to their ergonomics. The bigger problem is that they are in conflict with abstraction and OOP. Also, few people care about typed exceptions (unless they are happy path results, not errors).
&lt;/p&gt;

&lt;p&gt;And Scala solutions have a tendency to reinvent Java’s checked exceptions, due to the allure of static typing, I guess. You should read my previous articles on this matter:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;a href=&quot;https://alexn.org/blog/2018/05/06/bifunctor-io/&quot;&gt;Bifunctor IO and Java’s Checked Exceptions&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://alexn.org/blog/2022/04/18/scala-oop-design-sample/&quot;&gt;Scala OOFP Design Sample&lt;/a&gt;, in which I argue for “&lt;em&gt;designing errors out of existence&lt;/em&gt;”;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In support, I stumbled on the perfect example from Java’s standard library. It’s a classic one, it turns out, I’m not the first to point at it … Java’s &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/StringBuilder.html&quot;&gt;StringBuilder&lt;/a&gt;, which implements the following method:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;Appendable append(CharSequence csq) throws IOException;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which is why code using &lt;code&gt;StringBuilder&lt;/code&gt; can end up with ridiculous try-catch statements like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;try {
  buffer.append(string)
} catch (IOException ignored) {
  // never happens!
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Java does have a redeeming quality here. Due to the covariance of the return type, you can make the return type more specific, which means you can skip from the &lt;code&gt;throws&lt;/code&gt; clause in implementations (the equivalent of &lt;code&gt;throws Nothing&lt;/code&gt;).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;class StringBuilder implements Appendable {
  // ...
  @Override
  public StringBuilder append(Sequence s) {
    //...
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;StringBuilder&lt;/code&gt; works in-memory, it can never throw &lt;code&gt;IOException&lt;/code&gt;. The reason for that signature is because &lt;code&gt;StringBuilder&lt;/code&gt; implements &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Appendable.html&quot;&gt;Appendable&lt;/a&gt;, and that &lt;code&gt;IOException&lt;/code&gt; is there just in case &lt;code&gt;Appendable&lt;/code&gt; gets implemented by something that does side effects. Note that this isn’t a case of ergonomics, but rather a fundamental problem. It wouldn’t matter if we used your favorite bifunctor &lt;code&gt;IO&lt;/code&gt; or monad transformer, replacing checked-exceptions with &lt;code&gt;Either&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Appendable {
  // Same issue, although EitherT is worse due to
  // having issues with covariance;
  def append(csq: CharSequence): EitherT[IO, IOException, Unit]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Covariance issues of &lt;code&gt;EitherT&lt;/code&gt; aside, introducing an &lt;code&gt;Either&lt;/code&gt; data type makes this even more awkward:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Appendable {
  def append(csq: CharSequence): Either[IOException, Unit]
}

class StringBuilder extends Appendable {
  // ...
  // Awkward, because the `Either` is now completely unneeded,
  // and because it&apos;s lying, since on top of the JVM,
  // `Throwable` can always happen...
  override def append(Sequence s): Either&lt;Nothing, Unit&gt; = ???
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Scala users already suffer from &lt;code&gt;flatMap&lt;/code&gt; chains replacing &lt;code&gt;;&lt;/code&gt; and from unneeded type wrappers, so I’m guessing that if we squint enough, we can make this work.&lt;/p&gt;

&lt;p&gt;Regardless of how you model this, fact of the matter is that &lt;code&gt;StringBuilder&lt;/code&gt; will never throw &lt;code&gt;IOException&lt;/code&gt;. Like all Scala things, we could try introducing type parameters, or abstract type members, but that’s ridiculous, because the interface becomes unusable, as you can’t treat the error if you don’t know what it is, so you’re either going to work with &lt;code&gt;Any&lt;/code&gt;, or you’re going to have an extra type parameter at all call sites:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Ridiculous!
trait Appendable {
  type Error

  def append(csq: CharSequence): EitherT[IO, Error, Unit]
}

// Even more ridiculous! (ver.2)
trait Appendable[+E] {
  def append(csq: CharSequence): EitherT[IO, E, Unit]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We have the issues mentioned in the original article:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;code&gt;IOException&lt;/code&gt; is often an irrelevant exception, equivalent with &lt;code&gt;Throwable&lt;/code&gt;, as it doesn’t provide anything more specific than a signal for “&lt;em&gt;you can probably retry&lt;/em&gt;”, something which &lt;code&gt;Throwable&lt;/code&gt; does too;&lt;/li&gt;
  &lt;li&gt;The error type is an encapsulation leak, which forces a tax on all implementations;&lt;/li&gt;
  &lt;li&gt;It pushes complexity to the user;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ironically, in Java’s world, input errors (i.e., those thrown by tasks that you can’t retry) are often not checked exceptions. E.g., &lt;code&gt;InvalidArgumentException&lt;/code&gt; is a &lt;code&gt;RuntimeException&lt;/code&gt;, and this one gets thrown in constructors, being what libraries like Jackson expect for validating input when parsing, a contract that you have to find by reading the documentation. You can see here another issue with checked exceptions: importance gets decided by the library author instead of the downstream user, but this classification is often wrong, as it depends on the use-case at the call-site.&lt;/p&gt;

&lt;p&gt;Going further than the issue of abstract methods leaking implementation details, this is also an issue of &lt;em&gt;changes breaking compatibility&lt;/em&gt;. Turns out, &lt;code&gt;IOException&lt;/code&gt; isn’t a good super-type for I/O related exceptions, and the library’s authors might want to change that signature to this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;Appendable append(CharSequence csq) throws IOException, SQLException;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The implementation leak should be even more obvious, it would be absurd to deal with &lt;code&gt;SQLException&lt;/code&gt; when using a &lt;code&gt;StringBuilder&lt;/code&gt;. But even more problematic is that this breaks both source and binary compatibility, hurting all downstream users of the API, and &lt;a href=&quot;https://github.com/lightbend/mima&quot;&gt;Mima&lt;/a&gt; will complain, leading to interesting compromises. Turns out, people care about correctness only as long the fix is cheap 😉 so imagine, if you will, big repositories making liberal use of this function, alongside an entire ecosystem of libraries built on top of it. And remember, in this case, the exception type is absolutely useless, as people care only about these things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;closing resources safely — important to remember that a vast majority of call-sites care about the &lt;code&gt;finally&lt;/code&gt; more than the &lt;code&gt;catch&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;retrying locally (in which case this information is insufficient);&lt;/li&gt;
  &lt;li&gt;short-circuiting the happy-path, and logging the message and the call stack trace (globally, as locally this is done only when the outcome gets ignored);&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;BTW, this widening of the exception type isn’t unheard of. In Java’s standard library we now have:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/Closeable.html&quot;&gt;Closeable&lt;/a&gt;, which has a &lt;code&gt;close() throws IOException&lt;/code&gt;, inheriting from &lt;code&gt;AutoCloseable&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/AutoCloseable.html&quot;&gt;AutoCloseable&lt;/a&gt;, a newer interface (introduced by try-with-resources) that has a &lt;code&gt;close() throws Exception&lt;/code&gt;, a trick in order to make &lt;code&gt;Closeable&lt;/code&gt; compatible with it (covariance FTW), and note the total lack of information in &lt;code&gt;throws Exception&lt;/code&gt;;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I don’t know why &lt;code&gt;AutoCloseable&lt;/code&gt; was introduced, but if I were to take a guess, it’s probably because having that &lt;code&gt;IOException&lt;/code&gt; in the interface of &lt;code&gt;Closeable&lt;/code&gt; sucks. Java designers carrying about compatibility, however, chose this path instead of just modifying &lt;code&gt;Closeable&lt;/code&gt;, which is what a Scala FP developer would have done, to force correctness down on everyone 😎&lt;/p&gt;

&lt;p&gt;There is no loss of information, of course, if we just used &lt;code&gt;IO&lt;/code&gt;, which is what Java meant to do, but lacked the right type to do it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Appendable {
  // &quot;throws IOException&quot; is Java&apos;s `IO`, but it didn&apos;t quite work out
  def append(csq: CharSequence): IO[Unit]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;throws Throwable&lt;/code&gt; part is implicit in I/O tasks. And now the interface is abstract enough to be useful, yet more specific, in the sense that we can see that it has side effects, but not because of the returned exceptions. And evaluating an &lt;code&gt;IO&lt;/code&gt; can throw.&lt;/p&gt;

&lt;p&gt;Scala is an OOP language, and I’ve never worked on any major codebase that did not contain OOP interfaces. It’s a take it or leave it sort of deal. And this is a taste of the &lt;a href=&quot;https://alexn.org/blog/2022/05/13/oop-vs-type-classes-part-1-ideology/&quot;&gt;different ideologies in OOP versus static FP&lt;/a&gt;. What FP developers call “parametricity” is actually in opposition to well encapsulated abstractions. It’s white-box versus black-box design.&lt;/p&gt;

&lt;p&gt;For me, not carrying about implementation details is a powerful coping mechanism. And you also see such design choices in &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Design_of_Everyday_Things&quot;&gt;the design of everyday things&lt;/a&gt; that you use, meaning that user interfaces often get designed with the minimum amount of info and control knobs exposed for the users to be able to do their job. Think about the complexity of your car, in stark contrast to its simple controls (2 pedals, a steering wheel, and rearview mirrors), the ultimate black box. And all cars get steered mostly in the same way, standard interface, no reason to expose controls for implementation-specific errors.&lt;/p&gt;

&lt;p&gt;Exposing stuff “just in case” is not a good recipe, as it shifts responsibility on the user, and the user will do stupid things. Can’t emphasize this enough: &lt;strong&gt;errors should be designed out of existence!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For your reading pleasure, here are some references talking about these issues:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.artima.com/articles/the-trouble-with-checked-exceptions&quot;&gt;The Trouble with Checked Exceptions, a conversation with Anders Hejlsberg&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://radio-weblogs.com/0122027/stories/2003/04/01/JavasCheckedExceptionsWereAMistake.html&quot;&gt;Java’s checked exceptions where a mistake — Rod Waldhoff&lt;/a&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or hear Bruce Eckel, a quote from “Thinking in Java”:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Examination of small programs leads to the conclusion that requiring exception specifications could both enhance developer productivity and enhance code quality, but experience with large software projects suggests a different result – decreased productivity and little or no increase in code quality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s difficult, however, to convince people that their carefully designed, super explicit return types are actually a smell of bad design. Therefore, the legend and allure of checked exceptions will persist, but hey, placebos are valid treatments too 😛&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/28/the-trouble-with-checked-exceptions-part-2/?pk_campaign=rss&quot;&gt;The Trouble with Checked Exceptions: Part 2&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 28 Sep 2022 22:41:48 +0000</pubDate>
  <dc:modified>Thu, 29 Sep 2022 05:32:44 +0000</dc:modified>
  <atom:modified>Thu, 29 Sep 2022 05:32:44 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/28/the-trouble-with-checked-exceptions-part-2/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/28/the-trouble-with-checked-exceptions-part-2/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Java</category>
  <category>Scala</category>
  </item>


<item>
  <title>Proprietary Environments are a Trap</title>
  <description>What to learn in order to not become obsolete as a software developer, and then being forced into early retirement from programming? What platforms to prefer for building products that last with minimal maintenance?</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/09/22/proprietary-environments-are-a-trap/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-me-and-my-son-on-laptops.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;1000&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Me, with my son, learning the Lua programming language on proprietary macOS laptops.&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
What to learn in order to not become obsolete as a software developer, and then being forced into early retirement from programming? What platforms to prefer for building products that last with minimal maintenance?
&lt;/p&gt;

&lt;p&gt;Jeremy Allison (&lt;a href=&quot;https://en.wikipedia.org/wiki/Jeremy_Allison&quot;&gt;bio&lt;/a&gt;) is a computer programmer, contributor to Samba, and Free Software proponent that I have long admired.  In &lt;a href=&quot;https://web.archive.org/web/20150309050037/http://tuxdeluxe.org/node/122&quot;&gt;Working for The Man&lt;/a&gt;, he has a paragraph on proprietary platforms that stuck in my head…&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Proprietary environments are a trap&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;&lt;em&gt;I used to be a Microsoft Windows programmer, as well as a UNIX/POSIX programmer.&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;&lt;em&gt;The knowledge I’ve gained about programming POSIX is still useful, even though I learned a lot of it over twenty years ago. My Windows knowledge is now rather out of date, and getting more so over the years. It isn’t worth my time anymore to keep up with each increasingly baroque change to the Windows environment. Just as an example, over this time the latest “hot” communication paradigm that Microsoft recommended developers use in Windows changed from NetBEUI, to NetDDE, then OLE, followed by OLE2, then COM, DCE/RPC, DCOM, and now currently seems to be Web Services (SOAP and the like).&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;&lt;em&gt;Meanwhile, in the UNIX world the Berkeley socket API was useful in the 1980s and is still the core of all communications frameworks in the open standards world. All the UNIX RPC, object and Web Service environments are built on that stable base. Learn as much about the proprietary environments as you need to be able to help people port programs over to open standards. You’ll never be lost for work. The same is true of any proprietary environment, not just Windows. Windows just happens to be the one I know best.&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;&lt;em&gt;What will get very interesting in the future is the effect a fully open Java platform will have on the software environment in the next ten years. After initially ignoring Java due to its proprietary restrictions, I now believe Java and it’s associated libraries have the potential to be the next POSIX.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was written in 2007, so 15 years ago. Was Jeremy Allison right?&lt;/p&gt;

&lt;p&gt;I know people that left the software industry due to obsoletion, not able to keep up with the latest and greatest. Learning proprietary platforms is planned obsolesce for your career. Windows, a shadow of its former self, is now just an ads-delivery vehicle and a GUI toolkit for MS Office. Java, propelled by its openness and availability on all platforms, grew and is now more popular than ever, although it’s not alone in being popular, or a POSIX-like platform, others being JavaScript, .NET, or LLVM, and all are FOSS.&lt;/p&gt;

&lt;p&gt;There is one dimension that this misses – learning the latest and greatest can also be a losing bet. What young programmers should focus on is standards. And de facto standards happen with age, solutions becoming more entrenched and better as time passes, much like good wine.&lt;/p&gt;

&lt;p&gt;The Atom&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; text editor is dead. GitHub killed it, because it was acquired by Microsoft, and Microsoft has its own editor, VS Code&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. These editors were inspired by TextMate&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, a once popular, but proprietary editor for macOS that died, and the resurrection attempt via open sourcing failed. VS Code is right now the most popular editor. I don’t know if it will be around in another 20 years. But I do know that Emacs and Vi, both released in 1976 (46 years ago), will still be around in another 20 years, and the skills you acquire while using them won’t be obsolete any time soon.&lt;/p&gt;

&lt;p&gt;Programming languages become entrenched faster, because programs get built with them and then those programs need to be maintained. But Borland’s Pascal&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; or FoxPro are dead, and C isn’t. Although, oddly, at the time of writing the TIOBE Index&lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; has Object Pascal / Delphi in 13th place 🤦‍♂️&lt;/p&gt;

&lt;p&gt;Embrace open platforms, open standards, build on top of Open Source. But there’s also wisdom in “embracing boring technology”&lt;sup id=&quot;fnref:6&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;, as boring is simply a signal for older, more entrenched, more stable, that survived fashion trends. And boring technology is usually Open Source / Free Software, because FOSS survives for much longer 😉&lt;/p&gt;

&lt;p&gt;In addition to preferring boring FOSS technology, I’d also add … &lt;em&gt;learn math and algorithms&lt;/em&gt;. Math is the ultimate language and open standard for what we do, and it will never be obsolete. And not much progress happened in CS algorithms, except for machine learning. These are the fundamentals, which you may shun, but if all you’re doing is to call library functions, one of these days that job will get automated.&lt;/p&gt;

&lt;p&gt;Also, and perhaps this is the most important advice — engage in building software that helps people. If you’re not proud of your work, like for example if you work on an unscrupulous ads-delivery network or some online bets platform, or maybe if you work on military drones, quit your job and go work on software that doesn’t make the world more miserable than it is. You may find your job technically challenging and stimulating, but working on immoral products is just not worth it.&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;I grew up as a software developer with such words, with essays instilling ideas of software freedom, and I see such advice less and less these days.&lt;/p&gt;

&lt;p&gt;What changed is that Open Source won. It won the hearts and minds of software developers. Most of us build on top of FOSS libraries, and deploy on top of FOSS runtimes and operating systems, using many FOSS tools in the process. But it seems to me like the trend is reversing&lt;sup id=&quot;fnref:7&quot;&gt;&lt;a href=&quot;#fn:7&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“Life swings like a pendulum backward and forward between pain and boredom.”&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;— Arthur Schopenhauer&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When freedom is abundant, we begin taking it for granted, forgetting why it is needed, forgetting to contribute. Oblivion is how freedom dies.&lt;/p&gt;

&lt;hr&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://atom.io/&quot;&gt;Atom.io&lt;/a&gt; (&lt;a href=&quot;https://web.archive.org/web/20220922061411/https://atom.io/&quot;&gt;archive&lt;/a&gt;), also see &lt;a href=&quot;https://en.wikipedia.org/wiki/Atom_(text_editor)&quot;&gt;Wikipedia&lt;/a&gt; — is a text editor developed by GitHub, based on Electron, scriptable via JavaScript/CoffeeScript; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VS Code&lt;/a&gt;, also see &lt;a href=&quot;https://en.wikipedia.org/wiki/Visual_Studio_Code&quot;&gt;Wikipedia&lt;/a&gt; — is a text editor developed by Microsoft, also based on Electron, scriptable in TypeScript; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/TextMate&quot;&gt;TextMate&lt;/a&gt; was a proprietary editor built for macOS, made popular by the screencasts of &lt;a href=&quot;https://en.wikipedia.org/wiki/David_Heinemeier_Hansson&quot;&gt;DHH&lt;/a&gt; and others; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Turbo_Pascal&quot;&gt;Turbo Pascal&lt;/a&gt; was the programming language and environment I learned in high school; &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://www.tiobe.com/tiobe-index/&quot;&gt;Tiobe Index&lt;/a&gt; (&lt;a href=&quot;https://web.archive.org/web/20220922063355/https://www.tiobe.com/tiobe-index/&quot;&gt;archive&lt;/a&gt;) is a piece of shit that people take way too seriously — the &lt;a href=&quot;https://madnight.github.io/githut/#/pull_requests/2022/1&quot;&gt;GitHub language stats&lt;/a&gt; (&lt;a href=&quot;https://web.archive.org/web/20220909230229/https://madnight.github.io/githut/#/pull_requests/2022/1&quot;&gt;archive&lt;/a&gt;) are IMO far better at assessing a language’s popularity, as even if biased, it shows the FOSS output of the language’s community, and that’s a much stronger signal than Google searches, or whatever crap the TIOBE Index does; &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://mcfunley.com/choose-boring-technology&quot;&gt;Choose boring technology&lt;/a&gt; (&lt;a href=&quot;https://web.archive.org/web/20220922063839/https://mcfunley.com/choose-boring-technology&quot;&gt;archive&lt;/a&gt;) is an essay by Dan McKinley that became an instant hit; &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:7&quot;&gt;
      &lt;p&gt;What triggered these thoughts is &lt;a href=&quot;https://alexn.org/blog/2022/09/07/akka-is-moving-away-from-open-source/&quot;&gt;Akka’s license change&lt;/a&gt;, following other “open source companies” flipping, such as Elasticsearch or MongoDB, and others, alongside the general sentiment I’m seeing among my peers; &lt;a href=&quot;#fnref:7&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/22/proprietary-environments-are-a-trap/?pk_campaign=rss&quot;&gt;Proprietary Environments are a Trap&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 22 Sep 2022 07:00:00 +0000</pubDate>
  <dc:modified>Fri, 06 Sep 2024 06:33:48 +0000</dc:modified>
  <atom:modified>Fri, 06 Sep 2024 06:33:48 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/22/proprietary-environments-are-a-trap/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/22/proprietary-environments-are-a-trap/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Open Source</category>
  <category>Proprietary</category>
  </item>


<item>
  <title>Java 19</title>
  <description>Java 19 is now released, and it’s a big deal, as it ships with Virtual Threads (JEP 425), among other goodies, like structured concurrency (JEP 428), or improvements to pattern matching (JEPs 405, 427). I haven’t been as excited about a Java release in a long time.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/09/21/java-19/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/java-duke.png?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;901&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Honestly, Java&apos;s mascot is pretty cool, Scala needs a mascot too.&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
Java 19 is now &lt;a href=&quot;https://www.oracle.com/news/announcement/oracle-releases-java-19-2022-09-20/&quot;&gt;released&lt;/a&gt;, and it’s a big deal, as it ships with &lt;a href=&quot;https://openjdk.org/jeps/425&quot;&gt;Virtual Threads (JEP 425)&lt;/a&gt;, among other goodies, like &lt;a href=&quot;https://openjdk.org/jeps/428&quot;&gt;structured concurrency (JEP 428)&lt;/a&gt;, or improvements to pattern matching (JEPs &lt;a href=&quot;https://openjdk.org/jeps/405&quot;&gt;405&lt;/a&gt;, &lt;a href=&quot;https://openjdk.org/jeps/427&quot;&gt;427&lt;/a&gt;). I haven’t been as excited about a Java release in a long time.
&lt;/p&gt;

&lt;p&gt;I once claimed that this function signature needs special platform support, on top of the JVM this needs to block threads, and on top of some other platforms this gets implemented with continuations/coroutines. Not all platforms can provide support for it, and blocking (platform) threads is very expensive, therefore it should be avoided:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;Future[A] =&gt; A // aka `Await.result`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Java ecosystem has been increasingly moving to reactive APIs, with projects like &lt;a href=&quot;https://projectreactor.io/&quot;&gt;Project Reactor&lt;/a&gt;, &lt;a href=&quot;https://github.com/ReactiveX/RxJava&quot;&gt;RxJava&lt;/a&gt;, or &lt;a href=&quot;https://vertx.io/&quot;&gt;Vert.x&lt;/a&gt; becoming really popular. The introduction of Virtual Threads, however, has the potential to move the ecosystem back to usage of blocking APIs for I/O or structured concurrency.&lt;/p&gt;

&lt;p&gt;Blocking threads plays nice with Java’s features in a way that reactive APIs can’t. For instance: for loops, try/catch, try-with-resources, or checked exceptions. Java was built to synchronize on concurrent tasks by blocking threads, and the incursion into reactive APIs was only temporary. Other languages, such as Kotlin, implemented &lt;a href=&quot;https://kotlinlang.org/docs/coroutines-overview.html&quot;&gt;coroutines&lt;/a&gt; for mostly the same effect. But note that Virtual Threads improves everything, including all blocking APIs from the &lt;code&gt;java.io&lt;/code&gt; package, and it does so for all languages running on top of the JVM, whereas Kotlin’s coroutines can’t work around the platform’s limitations (blocking I/O is still blocking I/O). This is what having control over the entire stack gives you.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“With only a tiny code change to use JDK19 “virtual threads” JRuby can now spin up over 100k fibers at once! Launching and completing them takes about 0.7s after warmup. This will make async IO servers and thousands of concurrent users possible on JRuby. 🤯”&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;— &lt;a href=&quot;https://x.com/headius/status/1563205672300609536&quot; target=&quot;_blank&quot;&gt;Charles Oliver Nutter (@headius)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mind you, I don’t think this invalidates the available projects built with reactive APIs. I think Virtual Threads will make everything better, as these projects will simply adapt to provide the best API depending on use-case. We use reactive APIs due to the strong guarantees they provide, and due to their declarative approach, and that won’t change. But users will no longer be forced to use reactive APIs if all they want is efficiency.&lt;/p&gt;

&lt;p&gt;Virtual Threads also has the potential to change APIs for Scala, too. If blocking threads is now cheap, this should no longer be a big problem in terms of efficiency:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;IO[A] =&gt; A // aka `unsafeRunSync`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And neither is something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;Stream[IO, A] =&gt; ??? =&gt; A // Iterator#next() ftw 😛
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is interesting, as we can now do some stuff afforded with Kotlin’s coroutines, see &lt;a href=&quot;https://arrow-kt.io/docs/fx/&quot;&gt;Arrow-fx&lt;/a&gt;. Meaning that, instead of using &lt;code&gt;flatMap&lt;/code&gt; to compose &lt;code&gt;IO&lt;/code&gt; values, we could use a more imperative approach, and have &lt;a href=&quot;https://alexn.org/blog/2022/05/23/tracking-effects-in-scala/&quot;&gt;Scala help with the safety&lt;/a&gt;. Many people will object to replacing &lt;code&gt;flatMap&lt;/code&gt;, as it’s about composition, but other Scala devs could prefer such an API. Even without any API changes, calling Java APIs will be less like walking on a landmine field. The big problem that I’m seeing for evolving Scala APIs is that this is a runtime feature, not a language one, meaning that the portability to Scala.js and Scala Native will suffer.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
Did you know that Cats-Effect’s &lt;code&gt;IO&lt;/code&gt; now &lt;a href=&quot;https://typelevel.org/blog/2022/09/19/typelevel-native.html&quot;&gt;supports Scala Native&lt;/a&gt;? 😱
&lt;/p&gt;

&lt;p&gt;And do you remember &lt;a href=&quot;https://monix.io/docs/current/best-practices/blocking.html&quot;&gt;that practice&lt;/a&gt; of having 2 thread-pools in your project, one for CPU-bound tasks and another for blocking I/O tasks? Oracle just ended it in Java 19. You no longer need to shift between thread-pools in order to avoid thread starvation, while efficiently using your CPU cores.&lt;/p&gt;

&lt;p&gt;Interesting times ahead — and I’d like to predict the future, but truth is, I have no idea how our Scala effect systems will change to take advantage of it. In the meantime:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;sdk install java 19-oracle
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s a good video explaining why Java got virtual threads, and how it compares with alternatives:&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=KmMU5Y_r0Uk&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/KmMU5Y_r0Uk/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=KmMU5Y_r0Uk&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Ron Pressler — Why user-mode threads are (often) the right answer
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/21/java-19/?pk_campaign=rss&quot;&gt;Java 19&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 21 Sep 2022 16:00:00 +0000</pubDate>
  <dc:modified>Sat, 18 May 2024 07:19:26 +0000</dc:modified>
  <atom:modified>Sat, 18 May 2024 07:19:26 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/21/java-19/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/21/java-19/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Java</category>
  <category>Scala</category>
  </item>


<item>
  <title>Akka Fork FUD</title>
  <description>Lightbend made Akka proprietary from version 2.7.x onward. This left the community wondering about the possibility of a fork, and unfortunately, I see some FUD that needs to be addressed.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
Lightbend &lt;a href=&quot;https://alexn.org/blog/2022/09/07/akka-is-moving-away-from-open-source/&quot;&gt;made Akka proprietary&lt;/a&gt; from version 2.7.x onward. This left the community wondering about the possibility of a fork, and unfortunately, I see some FUD that needs to be addressed.
&lt;/p&gt;

&lt;h2 id=&quot;fear-lightbend-can-sue&quot;&gt;Fear: Lightbend can sue&lt;/h2&gt;

&lt;p&gt;There is a high likelihood that bugs get discovered and will have to be fixed in both the BSL-licensed Akka, and in the community fork. As such, this leaves people wondering … what if Lightbend sues for copyright infringement? What if the bug fixes are so similar that a court will decide such bug fixes are derivate works of the BSL-licensed code?&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
Speaking of a fork, I’d license all new development of a fork in a copyleft license, like &lt;a href=&quot;https://www.gnu.org/licenses/lgpl-3.0.en.html&quot;&gt;LGPLv3&lt;/a&gt;, precisely so that the BSL-licensed Akka can’t use it, and it would be compatible with the current Apache 2.0 license. But IANAL, and I don’t know how practical a copyleft license is for such libraries. This inability to share future bug fixes can go both ways 😉
&lt;/p&gt;

&lt;p&gt;First, of how many lawsuits targeting Open Source forks have you heard of? Do your research and name them. I’d bet that your list will be mostly blank. Because, it turns out, suing and winning in cases of copyright or patents infringement is actually hard.&lt;/p&gt;

&lt;p&gt;Anyone can sue for anything, and due to the high costs of such lawsuits, settlements are quite common. But for the few lawsuits against FOSS products that happened, it didn’t go so well for the plaintiff. For example, Oracle, with its patents war chest, sued Google for using pieces from a &lt;a href=&quot;https://en.wikipedia.org/wiki/Apache_Harmony&quot;&gt;3rd party Java implementation&lt;/a&gt; in Android, built via reverse engineering. They also sued for copyright infringement. And Oracle lost. I remember the anti-Java FUD campaigns from back then, people being happy they picked some alternative, like JavaScript, even if Oracle’s patents war chest probably impacted them, too, since modern JS engines are also derivates of Smalltalk and Java’s Hotspot VM.&lt;/p&gt;

&lt;p&gt;As a similar issue, for years people have &lt;a href=&quot;https://en.wikipedia.org/wiki/Mono_(software)&quot;&gt;spread FUD about Mono&lt;/a&gt;, the clean room dotNET-compatible implementation (I was part of that choir). The likelihood of Microsoft suing was high, actually, as this was unfolding in the age when Microsoft was threatening to sue Linux distributions (they never stopped the patents racketeering BTW). Microsoft never sued for Mono, probably because they would’ve lost. &lt;a href=&quot;https://en.wikipedia.org/wiki/SCO%E2%80%93Linux_disputes#Microsoft_funding_of_SCO_controversy&quot;&gt;Their puppet company&lt;/a&gt; did lose. If the Mono contributors could manage to not look at .NET’s disassembled code, or at &lt;a href=&quot;https://en.wikipedia.org/wiki/Shared_Source_Common_Language_Infrastructure&quot;&gt;Rotor&lt;/a&gt; for that matter, I think projects smaller than that can be fine. Note, lawsuits may not work, but many in the Linux, or Mono, or &lt;a href=&quot;https://en.wikipedia.org/wiki/UNIX_System_Laboratories,_Inc._v._Berkeley_Software_Design,_Inc.&quot;&gt;BSD&lt;/a&gt; camps can probably tell you: FUD works, as big organizations are risk-averse.&lt;/p&gt;

&lt;p&gt;In our case, we aren’t even talking of clean room reverse engineering, which is a much bigger problem. In this instance a fork is perfectly legal due to the Apache 2.0 license, which is perfect for forking, because it contains an explicit patents grant too. Worth mentioning, as this explicit patents grant does not favor any company, and covers derivate works too. This in contrast with what Facebook and Microsoft have been doing 😉 and why Apache 2.0 is better than the MIT or BSD licenses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The whole value proposition of &lt;a href=&quot;https://alexn.org/blog/2022/09/07/free-software-vs-open-source/&quot;&gt;Open Source&lt;/a&gt; is that you can &lt;a href=&quot;https://en.wikipedia.org/wiki/Fork_(software_development)&quot;&gt;fork&lt;/a&gt;.&lt;/strong&gt; That’s all there is to it. There’s nothing else worthwhile about Open Source that’s worth mentioning.&lt;/p&gt;

&lt;p&gt;If that’s not true, then might as well drop all Open Source libraries and tools from your project right now, especially those projects built by companies that require copyright agreements or assignments, legally binding documents granting them the right to re-license everything you contribute as proprietary software.&lt;/p&gt;

&lt;p&gt;For instance, one of the contenders for Akka’s market share is ZIO. Ziverge, the company behind it, does require a &lt;a href=&quot;https://zio.dev/about/contributing/#2-grant-of-rights&quot;&gt;grant of rights&lt;/a&gt; (&lt;a href=&quot;https://web.archive.org/web/20220921044332/https://zio.dev/about/contributing/#2-grant-of-rights&quot;&gt;archive&lt;/a&gt;) on all contributions, giving them the right to distribute your contributions under a proprietary license. Discussions on copyleft aside, they can do precisely what Lightbend is doing. Personally, I don’t trust such CLAs and companies that require them, unless we’re speaking of the Apache Foundation. If I’d fear the companies behind FOSS projects, at the very least I’d use libraries that don’t require CLAs for contributions.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; not all companies do this, not all FOSS projects do this. &lt;a href=&quot;https://typelevel.org/&quot;&gt;Typelevel&lt;/a&gt; in particular does not require the signing of any copyright agreement, and the only agreement required of you is for your work to get distributed strictly under Apache 2.0 (see &lt;a href=&quot;https://github.com/typelevel/cats-effect/blob/series/3.x/CONTRIBUTING.md#licensing&quot;&gt;contributing&lt;/a&gt;), mentioned here as &lt;a href=&quot;https://github.com/typelevel/cats-effect/issues/521&quot;&gt;I was there&lt;/a&gt;, complaining. &lt;a href=&quot;https://www.linuxjournal.com/content/contributor-agreements-considered-harmful&quot;&gt;I am not the first to have this opinion&lt;/a&gt;, I won’t be the last either. And as the most successful FOSS project in history, now getting a majority of contributions from companies, the Linux kernel should be enough to give you pause.
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The only protection we get, in all such cases, is the Apache 2.0 license, due to the ability for forking.&lt;/strong&gt; Open Source licenses exist because “trust” isn’t enough, and if you rely on trust, and you’re not paying, then “you’re the product”. If the ability to fork is off the table, then all Open Source software built by companies is a liability. Might as well drop such dependencies, as they are all landmines that will keep you hostage when the company behind them flips.&lt;/p&gt;

&lt;p&gt;Thankfully, that’s not how Open Source works.&lt;/p&gt;

&lt;p&gt;And I am mentioning Ziverge explicitly, as they are the ones spreading these fears right now. Not cool. Especially because Akka can’t be replaced. There are a lot of projects building on top of Akka, including projects built in Java or &lt;a href=&quot;https://getakka.net/&quot;&gt;in .NET&lt;/a&gt;, that can’t just switch to something else, no matter how much you like your monads and dislike actors. And all claims otherwise are either shortsighted or disingenuous, given how software development at scale works.&lt;/p&gt;

&lt;p&gt;I’ve always been a fan of “growing the whole pie” in terms of market share. Competition does in fact grow the market for everyone. Which is why I never understood &lt;a href=&quot;https://en.wikipedia.org/wiki/Fear,_uncertainty,_and_doubt&quot;&gt;“fear, uncertainty and doubt” (FUD)&lt;/a&gt; as a marketing tactic, because it shrinks the pie for everyone, and the salesmen using FUD end up getting a bigger piece from a smaller pie.&lt;/p&gt;

&lt;p&gt;Akka has been a central part of Scala, the gravitational force that attracted a lot of developers, and quite frankly, if Akka users get thrown under the bus like this, in order to pump up the numbers for some company or another, I will view the entire Scala ecosystem as a liability, for any project, in spite of all my Scala investments, and I’m sure that I won’t be alone. It’s not personal, it’s just business.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, &lt;strong&gt;nobody can demand free labor, a fork may not be possible,&lt;/strong&gt; but let us all leave our crystal balls at home, and just leave it to the market. Because Scala is small, compared to the juggernauts in this space, and unfortunately how this Akka situation is being handled shows the world what Scala is made of. It’s unfair, and I wish this wasn’t so, but it is what it is.&lt;/p&gt;

&lt;h2 id=&quot;fear-akka-is-too-complex&quot;&gt;Fear: Akka is too complex&lt;/h2&gt;

&lt;p&gt;The idea is that Akka is built with VC money, a lot of work went into it, and a community fork isn’t sustainable, as it requires man-hours and knowledge about distributed systems.&lt;/p&gt;

&lt;p&gt;All I can say is that forks like &lt;a href=&quot;https://getakka.net/&quot;&gt;Akka .NET&lt;/a&gt; and &lt;a href=&quot;https://opensearch.org/&quot;&gt;OpenSearch&lt;/a&gt; exist (🎤 drop).&lt;/p&gt;

&lt;p&gt;Yes, it will take resources, but if there really are big companies with Akka investments, such a fork can happen. And if a fork doesn’t happen, that’s life, and maybe Akka isn’t so popular or valuable after all.&lt;/p&gt;

&lt;p&gt;For our project, I’d also argue that we have everything needed in Akka already, and what we require (beside bug fixing) is for Akka to not hold us back when upgrading dependencies. I’d like to update the libraries that Akka depends on, I’d like us to upgrade to Scala 3 at some point. Updating such dependencies in an Akka fork may take a lot of effort, but it probably doesn’t require a PhD in distributed computing.&lt;/p&gt;

&lt;p&gt;Therefore, personally, I remain hopeful.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/21/akka-fork-fud/?pk_campaign=rss&quot;&gt;Akka Fork FUD&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 21 Sep 2022 09:00:00 +0000</pubDate>
  <dc:modified>Wed, 21 Sep 2022 20:22:54 +0000</dc:modified>
  <atom:modified>Wed, 21 Sep 2022 20:22:54 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/21/akka-fork-fud/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/21/akka-fork-fud/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Open Source</category>
  <category>Scala</category>
  </item>


<item>
  <title>Java&#39;s Cultural Problem</title>
  <description>Java is good by modern standards, from a technical perspective, the platform having received a lot of improvements from Java 8 to 17. Unfortunately, it still stinks, and the problem is its “enterprise” culture.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/09/19/java-cultural-problem/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/java-logo.png?202603060940&quot; alt=&quot;&quot; width=&quot;1800&quot; height=&quot;1013&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Java is good by modern standards, from a technical perspective, the platform having received a lot of improvements from Java 8 to 17. Unfortunately, it still stinks, and the problem is its &quot;enterprise&quot; culture.
&lt;/p&gt;

&lt;p&gt;Let me illustrate the problem via examples …&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://quarkus.io/&quot;&gt;Quarkus&lt;/a&gt; is a very promising framework, being a lightweight replacement for Spring, promising compatibility with &lt;a href=&quot;https://www.graalvm.org/reference-manual/native-image/&quot;&gt;GraalVM’s Native Image&lt;/a&gt;. Full of hope, I enthusiastically opened its documentation, and started with &lt;a href=&quot;https://quarkus.io/guides/config&quot;&gt;how to configure an app&lt;/a&gt;, expecting something with common sense, like &lt;a href=&quot;https://www.dropwizard.io/en/latest/getting-started.html#creating-a-configuration-class&quot;&gt;Dropwizard’s quick-start guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Quarkus depends on &lt;a href=&quot;https://github.com/smallrye/smallrye-config&quot;&gt;SmallRye Config&lt;/a&gt;. And if you want to map your configuration to objects, &lt;a href=&quot;https://quarkus.io/guides/config-mappings&quot;&gt;the documentation&lt;/a&gt; has this to say:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;@ConfigMapping(prefix = &quot;server&quot;)
interface ServerConfig {

  String host();

  int port();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In Java’s world, interfaces and abstract classes get used by dependency injection libraries, with methods left abstract in order for their implementation to be filled-in later. Any &lt;a href=&quot;https://alexn.org/blog/2017/10/15/functional-programming/&quot;&gt;FP developer&lt;/a&gt; should scream when seeing this, because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;This should be a pure data structure;&lt;/li&gt;
  &lt;li&gt;These abstract methods signal the possibility of side effects — in general, it is the possibility of side effects that drives the demand for abstract methods, as pure data structures rarely need it;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do you know what the library does in this instance? I sure don’t. It could be reading from a file and block a thread on every access, it could be thread unsafe, I wouldn’t know, since whatever it does is magic™️, and this isn’t my data structure. Even if it generates a pure data structure, for all I know its implementation can always change in future versions to also launch rockets to Mars.&lt;/p&gt;

&lt;p&gt;Since Java 14 we have &lt;a href=&quot;https://docs.oracle.com/en/java/javase/14/language/records.html&quot;&gt;records&lt;/a&gt;. The more common-sense definition doesn’t work, the library being (currently) unable to work with it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;//
// java.lang.IllegalStateException: SRCFG00043:
// The @ConfigMapping annotation can only be placed in interfaces...
//
@ConfigMapping(prefix = &quot;server&quot;)
final record ServerConfig(
  String host,
  int port,
) {}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; to drive this point home, let me make it clear that I don’t care from where the configuration is being read (the actual I/O side effect), but rather what happens afterwards. This configuration has an implicit usage protocol that isn’t properly expressed by an abstract interface:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;code&gt;host&lt;/code&gt; and &lt;code&gt;port&lt;/code&gt; values should be read from the same configuration source;&lt;/li&gt;
  &lt;li&gt;These values shouldn’t change during the application’s lifecycle, otherwise the interface should provide the ability to register a listener;&lt;/li&gt;
  &lt;li&gt;There’s no point in doing the side effect more than once, at the application’s start;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In other words, this is not just bad FP design, this is bad OOP design. A better abstract interface would be this, which makes the behavior crystal clear:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;interface ServerConfigReader {
  ServerConfig read() throws IOException;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Dropwizard has a more common-sense approach, as it leaves you in charge of defining a type safe configuration object. But it, too, was infected by the Java EE culture (aka &lt;a href=&quot;https://en.wikipedia.org/wiki/Jakarta_EE&quot;&gt;Jakarta EE&lt;/a&gt;), preferring &lt;a href=&quot;https://beanvalidation.org/&quot;&gt;Bean Validation via annotations&lt;/a&gt;, with the help of &lt;a href=&quot;https://hibernate.org/validator/&quot;&gt;hibernate-validator&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public record ServerConfig(
  @NotNull @NotEmpty
  String host,

  @NotNull
  Integer port,

  @NotNull @Email
  String contact
) {}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I understand the &lt;code&gt;@NotNull&lt;/code&gt; annotation. Java has &lt;code&gt;null&lt;/code&gt; in it, all object references can be &lt;code&gt;null&lt;/code&gt;, and it’s too late for that to change. What’s odd is that &lt;code&gt;contact&lt;/code&gt; should always be an email address, no matter the context. Not even if you consider this “raw input”, because actual “raw input” is a plain string or an array of bytes, and if you ever reach this stage of having a structured &lt;code&gt;record&lt;/code&gt;, then you should already have an email address.&lt;/p&gt;

&lt;p&gt;Java’s culture eschews common sense approaches, like defining new types. Defining new types would &lt;a href=&quot;https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/&quot;&gt;make illegal states unrepresentable&lt;/a&gt;. Note how, with the following definition, there is no way to get an &lt;code&gt;EmailAddress&lt;/code&gt; that doesn’t pass the “validation”, and you don’t need a freaking annotations-driven library to validate your values:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.Objects;

public record EmailAddress(String value) {
  public EmailAddress {
    // We could&apos;ve used an Either data type, ofc;
    Objects.requireNonNull(value);
    // regexp could be better
    if (!value.matches(&quot;^[^@\\s]+@\\S+$&quot;))
      throw new IllegalArgumentException(
        String.format(&quot;&apos;%s&apos; is not a valid email address&quot;, value));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Back to Quarkus, usage of a DI container is required (via CDI annotations), and it’s not easy to keep the Java EE crap out of your classes. Reading &lt;a href=&quot;https://quarkus.io/guides/cdi-reference&quot;&gt;their documentation&lt;/a&gt;, by default you’d end up with something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;@ConfigMapping(prefix = &quot;greetings&quot;)
public interface GreetingServiceConfig {
  String name();
}

// Not a final class
@RequestScoped
public class GreetingService {
  // Abstract, and it cannot be private 😱
  @Inject
  GreetingServiceConfig config;

  public String greeting() {
    return &quot;Hello, &quot; + name + &quot;!&quot;;
  }

  // @PreDestroy is required for &quot;closeable&quot; resources;
  // I would have expected the framework to work with AutoCloseable,
  // but ALAS it doesn&apos;t;
  @PreDestroy
  public void close() {
    LoggerFactory.getLogger(getClass).info(&quot;Destroying GreetingService!&quot;);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the sample above, adding a scope (e.g., &lt;code&gt;@RequestScoped&lt;/code&gt;) makes the framework automatically initialize this “bean” when needed. And &lt;code&gt;@PreDestroy&lt;/code&gt; marks methods that have to be called when the “bean” is disposed. Note that my “bean” should implement &lt;code&gt;Closeable&lt;/code&gt;, but the framework completely ignores it, this being another instance in which a Java EE implementation ignores the Java language. You need that &lt;code&gt;@PreDestroy&lt;/code&gt;, or otherwise you’ll have a leak.&lt;/p&gt;

&lt;p&gt;Of note is how this approach will infect your entire codebase, forcing all your downstream users to forgo Java language constructs, such as easily building an instance with &lt;code&gt;new&lt;/code&gt;, or safe disposal of resources via &lt;a href=&quot;https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html&quot;&gt;try-with-resources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With this approach, not working with &lt;code&gt;final&lt;/code&gt; classes jumps at me, because &lt;a href=&quot;https://www.artima.com/articles/versioning-virtual-and-override&quot;&gt;“final” is a best practice&lt;/a&gt;. This isn’t related to Quarkus in any way, but rather with DI containers in general. For instance, Kotlin’s classes are &lt;a href=&quot;https://kotlinlang.org/docs/inheritance.html&quot;&gt;final by default&lt;/a&gt;, yet if you want to &lt;a href=&quot;https://kotlinlang.org/docs/jvm-spring-boot-restful.html&quot;&gt;build Spring apps&lt;/a&gt;, the recommended way would be to import the &lt;a href=&quot;https://kotlinlang.org/docs/all-open-plugin.html#spring-support&quot;&gt;kotling-spring&lt;/a&gt; plugin, which automatically “opens” your classes that have certain DI-related annotations. Whether you agree with “final by default” as a best practice or not, you’re getting a bad deal if the framework makes that choice for you.&lt;/p&gt;

&lt;p&gt;Quarkus ships with a &lt;a href=&quot;https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html&quot;&gt;CDI 2.0&lt;/a&gt; implementation, like Spring before it, although &lt;a href=&quot;https://quarkus.io/guides/cdi-reference&quot;&gt;its implementation&lt;/a&gt; isn’t fully compliant, since all those annotations and runtime behavior can’t be fully supported on top of GraalVM’s Native Image. It’s odd seeing such a framework forcing the use of Java EE’s CDI.&lt;/p&gt;

&lt;p&gt;Quarkus makes it hard to have a common-sense &lt;a href=&quot;https://blog.ploeh.dk/2011/07/28/CompositionRoot/&quot;&gt;composition root&lt;/a&gt;. Thankfully, I discovered how, via trial and error, meaning half-baked Stack Overflow answers and using the right keywords to appease the search gods. One of these days I’ll find out what the heck is a “bean”.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// ------------------------------------------------
// No Java EE crap
public record GreetingServiceConfig(String name) {}

// ------------------------------------------------
// No Java EE crap
public final class GreetingService implements Closeable {
  private final GreetingServiceConfig config;

  public GreetingService(GreetingServiceConfig cfg) {
    this.config = cfg;
  }

  public String greeting() {
    return &quot;Hello, &quot; + config.name() + &quot;!&quot;;
  }

  @Override
  public void close() {
    LoggerFactory.getLogger(getClass()).info(&quot;Destroying GreetingService!&quot;);
  }
}

// ------------------------------------------------
// Implements the &quot;composition root&quot; pattern...
//
// All of these imports are already a code smell, but at
// least it&apos;s localized, and does help with managing DI.
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Disposes;
import javax.ws.rs.Produces;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Disposes;
import javax.ws.rs.Produces;

public class AppConfiguration {
  @Produces
  @ApplicationScoped
  public GreetingServiceConfig gsConfig() {
    return new GreetingServiceConfig(
      ConfigProvider.getConfig().getValue(&quot;greetings.name&quot;, String.class)
    );
  }

  @Produces
  @RequestScoped
  public GreetingService greetingService(GreetingServiceConfig config) {
    return new GreetingService(config);
  }

  // Closeable resource needs to be destroyed, and
  // framework won&apos;t do it automatically;
  void disposesGreetingService(@Disposes GreetingService ref) {
    ref.close();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This way you can limit the impact of Java EE on your codebase. But it does need restraint, and you still have to learn a domain-specific language that has few things in common with Java, the language.&lt;/p&gt;

&lt;p&gt;Newcomers to Java have to deal with this nonsense, and it’s a pity given that Java 17 is a decent language and awesome platform. Java’s ecosystem still hasn’t learned enough from its competition, but hope never dies.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/19/java-cultural-problem/?pk_campaign=rss&quot;&gt;Java&apos;s Cultural Problem&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 19 Sep 2022 09:00:00 +0000</pubDate>
  <dc:modified>Wed, 21 Sep 2022 20:22:39 +0000</dc:modified>
  <atom:modified>Wed, 21 Sep 2022 20:22:39 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/19/java-cultural-problem/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/19/java-cultural-problem/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Java</category>
  <category>JVM</category>
  <category>Languages</category>
  <category>Programming Rant</category>
  </item>


<item>
  <title>Scripting with Scala</title>
  <description>Unix has a long tradition with scripting — small programs represented as text files that can be inspected, modified, and executed. Scala can be used for scripting too.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/09/13/scripting-with-scala/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-09-scala-cli.png?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;900&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Unix has a long tradition with scripting — small programs represented as text files that can be inspected, modified, and executed. Scala can be used for scripting too.
&lt;/p&gt;

&lt;p&gt;Scala is a compiled language, your average project has quite a complicated build setup, but we have 2 tools that makes scripting possible and quite pleasant:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://ammonite.io/#ScalaScripts&quot;&gt;Ammonite&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://scala-cli.virtuslab.org/&quot;&gt;Scala CLI&lt;/a&gt;, which is newer, does more, and can embed Ammonite;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this sample, &lt;strong&gt;I’m going to use Scala CLI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;First step, install &lt;code&gt;scala-cli&lt;/code&gt;. I’m on macOS, using &lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt;, for other operating systems refer to &lt;a href=&quot;https://scala-cli.virtuslab.org/docs/overview#installation&quot;&gt;its documentation&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;brew install Virtuslab/scala-cli/scala-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We are going to create a command-line utility that tells us how much time has passed since some timestamp in the past. It’s usage and output will look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;$ time-since.sc 2022-01-01

Since:   Sat, 1 Jan 2022 00:00:00 +0200
Until:   Tue, 13 Sep 2022 14:06:15 +0300

Elapsed: 255 days, 13 hours, 6 minutes, 15 seconds

Years:          0.70
Months:         8.40
Weeks:         36.51
Days:         255.55
Hours:       6133.10
Minutes:   367986.26
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Create a text file in &lt;code&gt;$HOME/bin/time-since.sc&lt;/code&gt; (or somewhere else that’s on your system &lt;code&gt;$PATH&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;#!/usr/bin/env -S scala-cli shebang -q

//&gt; using scala &quot;2.13.8&quot;
//&gt; using lib &quot;com.github.scopt::scopt::4.1.0&quot;

import scopt.{OParser, Read}
import java.time.format.DateTimeFormatter
import java.time._
import java.util.concurrent.TimeUnit
import scala.util.Try

case class Args(
  since: LocalDateTime,
  until: Option[LocalDateTime],
  zoneId: ZoneId,
)

val parsedArgs = {
  val builder = OParser.builder[Args]
  import builder._

  implicit val readsTime: Read[LocalDateTime] =
    implicitly[Read[String]].map { dt =&gt;
      Try(LocalDateTime.parse(dt, DateTimeFormatter.ISO_LOCAL_DATE_TIME))
        .orElse {
          Try(LocalDate.parse(dt, DateTimeFormatter.ISO_LOCAL_DATE))
            .map(_.atTime(LocalTime.of(0, 0, 0, 0)))
        }
        .getOrElse(
          throw new IllegalArgumentException(
            s&quot;Not a valid timestamp, correct format is `yyyy-mm-dd` OR `yyyy-mm-ddTHH:MM:SS`.&quot;
          ))
    }

  implicit val readsZoneId: Read[ZoneId] =
    implicitly[Read[String]].map { id =&gt;
      Try(ZoneId.of(id))
        .getOrElse(throw new IllegalArgumentException(s&quot;&apos;$id&apos; is not a valid timezone id&quot;))
    }

  val parser = OParser.sequence(
    programName(&quot;time-since.sc&quot;),
    head(&quot;time-since&quot;, &quot;1.x&quot;),
    arg[LocalDateTime](&quot;&lt;timestamp&gt;&quot;)
      .text(&quot;Format: `yyyy-mm-dd` or `yyyy-mm-ddTHH:MM:SS`.&quot;)
      .action((ts, args) =&gt; args.copy(since = ts)),
    opt[LocalDateTime](&apos;u&apos;, &quot;until&quot;)
      .text(&quot;Format: `yyyy-mm-dd` or `yyyy-mm-ddTHH:MM:SS`. Defaults to NOW.&quot;)
      .action { (ts, args) =&gt; args.copy(until = Some(ts)) },
    opt[ZoneId](&apos;z&apos;, &quot;zone-id&quot;)
      .text(&quot;Example: Europe/Bucharest&quot;)
      .action { (id, args) =&gt; args.copy(zoneId = id) },
  )
  OParser
    .parse(parser, args, Args(null, None, ZoneId.systemDefault()))
    .getOrElse {
      System.exit(1)
      throw new RuntimeException()
    }
}

val since = parsedArgs.since.atZone(parsedArgs.zoneId)
val until = parsedArgs.until.fold(ZonedDateTime.now(parsedArgs.zoneId))(_.atZone(parsedArgs.zoneId))
val sinceTs = since.toInstant.toEpochMilli
val untilTs = until.toInstant.toEpochMilli

println()
println(s&quot;Since:   ${since.format(DateTimeFormatter.RFC_1123_DATE_TIME)}&quot;)
println(s&quot;Until:   ${until.format(DateTimeFormatter.RFC_1123_DATE_TIME)}&quot;)

val totalMs = untilTs - sinceTs
val days = TimeUnit.MILLISECONDS.toDays(totalMs)
val rem1 = totalMs - TimeUnit.DAYS.toMillis(days)
val hours = TimeUnit.MILLISECONDS.toHours(rem1)
val rem2 = rem1 - TimeUnit.HOURS.toMillis(hours)
val minutes = TimeUnit.MILLISECONDS.toMinutes(rem2)
val rem3 = rem2 - TimeUnit.MINUTES.toMillis(minutes)
val seconds = TimeUnit.MILLISECONDS.toSeconds(rem3)

println()
println(s&quot;Elapsed: $days days, $hours hours, $minutes minutes, $seconds seconds&quot;)
println()

println(f&quot;Years:   ${(untilTs - sinceTs) / (1000.0 * 60 * 60 * 24 * 365.24)}%11.2f&quot;)
println(f&quot;Months:  ${(untilTs - sinceTs) / (1000.0 * 60 * 60 * 24 * 30.417)}%11.2f&quot;)
println(f&quot;Weeks:   ${(untilTs - sinceTs) / (1000.0 * 60 * 60 * 24 * 7)}%11.2f&quot;)
println(f&quot;Days:    ${(untilTs - sinceTs) / (1000.0 * 60 * 60 * 24)}%11.2f&quot;)
println(f&quot;Hours:   ${(untilTs - sinceTs) / (1000.0 * 60 * 60)}%11.2f&quot;)
println(f&quot;Minutes: ${(untilTs - sinceTs) / (1000.0 * 60)}%11.2f&quot;)
println()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This script has what’s called a &lt;a href=&quot;https://en.wikipedia.org/wiki/Shebang_(Unix)&quot;&gt;shebang&lt;/a&gt; declaration, which tells your shell (Bash, Zsh) how to interpret your script:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;#!/usr/bin/env -S scala-cli shebang -q
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, note the dependencies — we can specify the Scala version, and any library dependencies we require, in this case &lt;a href=&quot;https://github.com/scopt/scopt&quot;&gt;scopt&lt;/a&gt;, a library that helps us parse command line arguments:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//&gt; using scala &quot;2.13.8&quot;
//&gt; using lib &quot;com.github.scopt::scopt::4.1.0&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I usually build such scripts in Python or Ruby. These are good choices because they can be installed everywhere easily, and have “batteries included”, but extra functionality is hard to import. Scala-CLI (Ammonite too) allows us to import any dependency from Maven Central, and that’s awesome! ❤️&lt;/p&gt;

&lt;p&gt;Make this script executable:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;$ chmod +x ~/bin/time-since.sc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let’s execute it, and see what happens:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;$ time-since.sc

Error: Missing argument &lt;timestamp&gt;
time-since 1.x
Usage: time-since.sc [options] &lt;timestamp&gt;

  &lt;timestamp&gt;            Format: `yyyy-mm-dd` or `yyyy-mm-ddTHH:MM:SS`.
  -u, --until &lt;value&gt;    Format: `yyyy-mm-dd` or `yyyy-mm-ddTHH:MM:SS`. Defaults to NOW.
  -z, --zone-id &lt;value&gt;  Example: Europe/Bucharest

$ time-since.sc 2022-03-01

Since:   Tue, 1 Mar 2022 00:00:00 +0200
Until:   Tue, 13 Sep 2022 14:06:37 +0300

Elapsed: 196 days, 13 hours, 6 minutes, 37 seconds

Years:          0.54
Months:         6.46
Weeks:         28.08
Days:         196.55
Hours:       4717.11
Minutes:   283026.63
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that you can edit this script in &lt;a href=&quot;https://www.jetbrains.com/idea/&quot;&gt;IntelliJ IDEA&lt;/a&gt;, with auto-completion and everything. See &lt;a href=&quot;https://scala-cli.virtuslab.org/docs/cookbooks/intellij&quot;&gt;the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A disadvantage of working with Scala-CLI is that it’s not available everywhere, as for example, on Ubuntu/Debian I prefer &lt;code&gt;.deb&lt;/code&gt; packages via official repositories. But Java is available everywhere, and you can always &lt;a href=&quot;https://scala-cli.virtuslab.org/docs/cookbooks/scala-package&quot;&gt;package scripts in JARs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The startup time is not ideal either, being that of any Java app:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;$ time time-since.sc
...
time-since.sc  0.51s user 0.13s system 99% cpu 0.645 total
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, the startup cost is half a second. It’s not that bad though. &lt;del&gt;And I hope some out-of-the-box integration with &lt;a href=&quot;https://www.graalvm.org/native-image/&quot;&gt;GraalVM’s Native Image&lt;/a&gt; will happen.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;You can package the script using &lt;a href=&quot;https://www.graalvm.org/native-image/&quot;&gt;GraalVM’s Native Image&lt;/a&gt; to speed things up, see &lt;a href=&quot;https://scala-cli.virtuslab.org/docs/cookbooks/native-images&quot;&gt;the documentation&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;cd $HOME/bin

scala-cli package --native-image ./time-since.sc -o ./time-since -- --no-fallback
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
GraalVM’s native image only has partial support for libraries using reflection, and needs to know about them ahead of time. This sample was easy, but depending on your dependencies, other scripts may require some tweaking.
&lt;/p&gt;

&lt;p&gt;The startup time is now much better:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;$ time ./time-since 2022-01-01 1&gt;/dev/null

...  0.01s user 0.01s system 36% cpu 0.034 total
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’m in love! 😍&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/13/scripting-with-scala/?pk_campaign=rss&quot;&gt;Scripting with Scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 13 Sep 2022 09:00:00 +0000</pubDate>
  <dc:modified>Wed, 10 Jan 2024 11:29:19 +0000</dc:modified>
  <atom:modified>Wed, 10 Jan 2024 11:29:19 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/13/scripting-with-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/13/scripting-with-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>CLI</category>
  <category>Scala</category>
  <category>Shell</category>
  <category>Snippet</category>
  </item>


<item>
  <title>#DeleteFacebook</title>
  <description>I finally managed to delete my Facebook account. This was a long time coming. Being disconnected feels good, it feels liberating.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
I finally managed to delete my Facebook account. This was a long time coming. Being disconnected feels good, it feels liberating.
&lt;/p&gt;

&lt;p&gt;On Saturday I turned 40, and this was the ultimate test — not being on Facebook meant that my acquaintances did not know about my birthday, which meant I only received Happy Birthday wishes from family and very close friends. I received very few birthday-wishes this year. And it felt … weird, but good.&lt;/p&gt;

&lt;p&gt;On Facebook you “Like”, “Share”, or provide shallow comments, as a substitute for having meaningful face-to-face conversations. The comments are shallow because, when online, people no longer have the patience to listen, and start talking past each other, becoming adversarial, the goal being to be right, not to learn. Complex human interactions are replaced with mere bits of information (like / dislike), and those bits are enough to satisfy our inner urges. Yet society is more and more depressed, especially the teenagers.&lt;/p&gt;

&lt;p&gt;Humans are social beings, we crave human connection, and Facebook is the junk food of social interaction. Facebook pushes people to wish you Happy Birthday, which is how you get (impersonal) birthday wishes from people you haven’t talked with in 20 years, or from complete strangers. Those birthday wishes don’t mean much, though. We like to think that long-lost acquaintances, from school, from former jobs, are still thinking of us, but that ain’t true. It’s just a Facebook-driven automation. If anything, given that people tend to look stupid on social media, Facebook can and does severe ties, instead of strengthening them. If you connect with your work colleagues on Facebook, you’re not wise.&lt;/p&gt;

&lt;p&gt;I first thought of deleting Facebook on reading &lt;a href=&quot;https://openlibrary.org/works/OL19744680W/Ten_arguments_for_deleting_your_social_media_accounts_right_now&quot;&gt;“Ten arguments for deleting your social media accounts right now”&lt;/a&gt;. Actually, I thought about it, then tried to find a book that affirmed my decision. Well, it’s a poor book actually, as the arguments are almost religious. What the book argues is that social media companies invest in behavior modification, because they are betting on humans being just automatons, in order to get us to buy more stuff. I don’t doubt that social media companies try doing just that, except that &lt;em&gt;I no longer believe humans are so easy to manipulate&lt;/em&gt;. It’s like with smoking. Tobacco companies may have engaged in despicable practices, but in the end, human nature is to blame, as we often like to engage in toxic vices for instant gratification. Nowadays, people smoke a lot less only due to increased costs (extremely high taxes, and having fewer smoker-friendly places). In other words, smokers exist, not because they’ve been manipulated, but because they like it and because cigarettes were made easily accessible.&lt;/p&gt;

&lt;p&gt;Even if the environment plays a huge role in our behavior, the argument that we’re manipulated robs us of personal responsibility, of agency, an argument that I won’t buy. Red flags go off in my head whenever I hear of profit-driven puppeteers. When I quit smoking, more than a decade ago, I managed to do it solely due to economic reasons, as it has gotten simply too expensive to smoke. This argument also overestimates Facebook’s power, playing into their marketing. After all, nobody would pay for those ad-placements, if Facebook would fail to influence its users. Truth is, mentalities are really hard to change, and the only people buying the crap that FB sells are the people that would’ve bought that crap anyway.&lt;/p&gt;

&lt;p&gt;Facebook isn’t any more guilty than your favorite messenger application (SMS included), or the smartphone that you keep near you 24/7. Technology, even when neutral, has unintended consequences. Internet-connected smartphone applications are behaving like slot machines, triggering dopamine releases, pushing us to check for notifications and refresh the page. Stories of profit-driven automatic algorithms may be good for your self-esteem, or for your motivation to quit, but such stories don’t tell the whole picture. And the full picture is that many apps are slot machines, especially those designed for portable devices, fueling our addiction for shallow social interaction. Which would be OK, except that by stealing so much time away from our lives, it detracts us from having meaningful social and learning experiences.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/slot-machines.jpg&quot; width=&quot;1100&quot; height=&quot;768&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Slot machines in a Las Vegas casino.&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;And so, I’ve decided to delete Facebook. Not because I believe Facebook is evil, or special. But because it provides no value, it’s a source of stress (due to all the politics), and the time I lose on social media is time that I’d rather spend elsewhere. Time isn’t unlimited and it needs budgeting. For me the question is less about what I’m doing on Facebook, and more about what I’m not doing in general. I’m not calling my friends, for example. Or, I’m not learning as much as I’d like, or engaging in meaningful projects. Or, I’m reading less and less fiction books, because my time and patience is in short supply. Admit it, it takes great effort to just sit down with a book without checking any status updates on your smartphone 😉&lt;/p&gt;

&lt;p&gt;Deleting Facebook is easier said than done. These platforms make it hard to delete your account by merely “deactivating” your account for 30 days, giving you plenty of time to reconsider. You initiate the deletion process, and then a couple of days later guilt starts setting in, or fear that you’re going to miss out. You invested in your online identity, and there’s that lingering thought that you still have time to recover it, and maybe you can impose usage limits, etc. This dark pattern (the 30 days deactivation) is, of course, not accidental.&lt;/p&gt;

&lt;p&gt;To finally delete it, after a couple of failed attempts, I had to make recovery impossible:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I changed the email address to a “temporary” one (e.g., &lt;a href=&quot;https://www.fastmail.help/hc/en-us/articles/4406536368911-Masked-Email&quot;&gt;Fastmail’s masked emails&lt;/a&gt;);&lt;/li&gt;
  &lt;li&gt;I removed the phone number from my account;&lt;/li&gt;
  &lt;li&gt;I changed the username to something random;&lt;/li&gt;
  &lt;li&gt;I changed the password to something random;&lt;/li&gt;
  &lt;li&gt;I deleted the account (starting the 30 days process);&lt;/li&gt;
  &lt;li&gt;I deleted all traces of the temporary email address, and of the new username, or the new password;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(Take that, Facebook puppeteers)&lt;/p&gt;

&lt;p&gt;I managed to do it, as I realized that I’m not missing anything. If I want pictures from my family, I’ll ask for them. If I want to keep in touch with people, I’ll simply call them on the phone, and then maybe go out for coffee or beer, if possible; although just having phone conversations is nice, too. For telling my distant family how my life is going, if phone calls or visits aren’t practical, a plain-old newsletter might be better. I don’t need the events, or the politics, or the support groups. Everything I got from Facebook was either not productive, or had better options elsewhere.&lt;/p&gt;

&lt;p&gt;And not just Facebook. I deleted multiple social media accounts, actually. For example Instagram, and TikTok. And almost 2 years ago I gave up on my Hacker News account. Giving up on HN, with my hard-earned karma, was actually more painful than Facebook. I’m still on &lt;a href=&quot;https://x.com/alexelcu&quot;&gt;Twitter&lt;/a&gt;, as it can be useful for learning, or for notifying others of my blog posts. But only if kept in check, the rules being: no social interactions on it whatsoever, absolutely all notifications off, and time limited. I’m pretty sure that, given my current mentality, I’m no longer the ideal Twitter user, having turned it into a glorified RSS feed. Ditto Reddit.&lt;/p&gt;

&lt;p&gt;So here I am, a 40-year-old with no Facebook. Now, you kids get off my lawn!&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/12/delete-facebook/?pk_campaign=rss&quot;&gt;#DeleteFacebook&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 12 Sep 2022 09:00:00 +0000</pubDate>
  <dc:modified>Sat, 18 May 2024 07:19:22 +0000</dc:modified>
  <atom:modified>Sat, 18 May 2024 07:19:22 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/12/delete-facebook/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/12/delete-facebook/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Personal</category>
  </item>


<item>
  <title>Scala isn&#39;t fun anymore</title>
  <description>I’ve just spent over a day, going to sleep at 1:00 am, to upgrade dependencies and fix eviction warnings in the build of a Scala project.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/09/09/scala-isnt-fun-anymore/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p&gt;I’ve just spent over a day, going to sleep at 1:00 am, to upgrade dependencies and fix eviction warnings in the build of a Scala project. Had to fix the usual suspects:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.slf4j.org/&quot;&gt;Slf4j-api&lt;/a&gt; &lt;code&gt;1.7.x&lt;/code&gt; evicted by &lt;code&gt;2.0.0&lt;/code&gt;. They are binary backwards compatible, but the linking to the backend happens at runtime, so it can fail at runtime. This was a mix and match job. I had to downgrade &lt;a href=&quot;https://github.com/tpolecat/doobie&quot;&gt;Doobie&lt;/a&gt; from &lt;code&gt;0.13.4&lt;/code&gt; to &lt;code&gt;0.13.3&lt;/code&gt;, because that one patch version also bumped HikariCP from &lt;code&gt;3.4.5&lt;/code&gt; to &lt;code&gt;4.0.3&lt;/code&gt;, which in turn bumped &lt;code&gt;slf4j-api&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/brettwooldridge/HikariCP&quot;&gt;HikariCP&lt;/a&gt;, also a mix and match job, because &lt;a href=&quot;https://github.com/akka/akka-persistence-jdbc&quot;&gt;akka-persistence-jdbc&lt;/a&gt; also depends on it. I would have stayed on &lt;code&gt;4.0.3&lt;/code&gt;, but Akka wants &lt;code&gt;3.4.x&lt;/code&gt;, and I have no idea if they are compatible.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/scala/scala-xml&quot;&gt;Scala-xml&lt;/a&gt; &lt;code&gt;1.2.0&lt;/code&gt; evicted by &lt;code&gt;2.1.0&lt;/code&gt;; unfortunately we rely on Twirl templates, that require both a sbt plugin and a library dependency, and sbt plugins still rely on Scala 2.12, which require Scala-xml &lt;code&gt;1.2.0&lt;/code&gt;. The fix was to forcefully upgrade to &lt;code&gt;2.1.0&lt;/code&gt; and hope for the best.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/FasterXML/jackson&quot;&gt;Jackson (JSON)&lt;/a&gt; &lt;code&gt;2.11.4&lt;/code&gt; evicted by &lt;code&gt;2.12.7&lt;/code&gt; — normally, in Java world, this would be fine, except that &lt;a href=&quot;https://github.com/FasterXML/jackson-module-scala&quot;&gt;jackson-module-scala&lt;/a&gt; is sensitive to minor version bumps, and it fails at runtime (thank God we have unit tests); and we wouldn’t use &lt;code&gt;jackson-module-scala&lt;/code&gt;, but ALAS, &lt;a href=&quot;https://doc.akka.io/docs/akka/current/serialization-jackson.html&quot;&gt;akka-serialization-jackson&lt;/a&gt; depends on it. This was hard to fix, because it manifests as a weird runtime exception, and I had no idea where it came from or who’s complaining.
    &lt;ul&gt;
      &lt;li&gt;In case you’re wondering, we use &lt;a href=&quot;https://github.com/circe/circe&quot;&gt;Circe&lt;/a&gt; too, but Circe has been fine this round, as nobody updated its minor version (&lt;code&gt;early-semver&lt;/code&gt;).&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;You can guess the maturity of any Scala project by the number of libraries it uses to do JSON parsing.&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;org.apache.kafka:kafka-clients&lt;/code&gt; version &lt;code&gt;3.0.1&lt;/code&gt; was also evicted by &lt;code&gt;7.0.5-css&lt;/code&gt;; the former is used by &lt;a href=&quot;https://github.com/akka/alpakka-kafka&quot;&gt;akka-streams-kafka&lt;/a&gt;, whereas the latter is required by &lt;a href=&quot;https://github.com/confluentinc/schema-registry&quot;&gt;kafka-avro-serializer&lt;/a&gt;; no worries, I consulted this &lt;a href=&quot;https://docs.confluent.io/platform/current/installation/versions-interoperability.html#cp-ak-compatibility&quot;&gt;HTML table of compatibility&lt;/a&gt; and I think they were compatible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Couple of months ago this list was bigger, but I prefer dropping dependencies causing issues like hot potatoes.&lt;/p&gt;

&lt;p&gt;This was before I went in to fix the compilation and the test errors; at least Scala fails a lot at compile time, instead of runtime. Getting &lt;code&gt;sbt evicted&lt;/code&gt; to stay silent can be a chore. In fairness, sbt is really sweet for the ability to turn eviction warnings to errors, by setting the &lt;a href=&quot;https://www.scala-lang.org/blog/2021/02/16/preventing-version-conflicts-with-versionscheme.html&quot;&gt;versioning schemes&lt;/a&gt; for the required dependencies. Did I mention that I absolutely love sbt? (except for how freaking slow it is)&lt;/p&gt;

&lt;p&gt;Anyway, this wasn’t fun:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// https://www.scala-lang.org/blog/2021/02/16/preventing-version-conflicts-with-versionscheme.html
libraryDependencySchemes ++= ourLibraryVersioningSchemes,
// Configures eviction reports
evicted / evictionWarningOptions := EvictionWarningOptions.default
  .withWarnDirectEvictions(true)
  .withWarnEvictionSummary(true)
  .withWarnScalaVersionEviction(true)
  .withWarnTransitiveEvictions(true)
  .withShowCallers(true),
// Checks evictions on resolving dependencies
update := update.dependsOn(evicted).value,
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;PRO-TIP: to hunt down from where transitive dependencies come from, &lt;code&gt;sbt dependencyBrowseTreeHTML&lt;/code&gt; is your friend 😉😍&lt;/p&gt;

&lt;p&gt;Many Scala libraries are really well maintained and stable (e.g., Cats), and we’ve got the tools to do it, such as sbt being awesome at conditional/cross compilation, checking versioning schemes, or the availability of &lt;a href=&quot;https://github.com/lightbend/mima&quot;&gt;Mima&lt;/a&gt;, a plugin meant to check for breakages of binary compatibility. It’s a useful case study in communities adapting to their sins. But being the user, and having to deal with all the breakage, is still painful as hell, and I feel that in general many libraries have no respect for downstream users suffering from breakage.&lt;/p&gt;

&lt;p&gt;Speaking of versioning schemes, I’ve set Akka’s stuff to &lt;code&gt;pvp&lt;/code&gt;. This means that minor versions break compatibility, which should trigger eviction errors. Not sure if it will work. I hope we can pin it down to &lt;code&gt;2.6.20&lt;/code&gt; (&lt;a href=&quot;https://alexn.org/blog/2022/09/07/akka-is-moving-away-from-open-source/&quot;&gt;the last Open Source version&lt;/a&gt;) 🤷‍♂️&lt;/p&gt;

&lt;p&gt;This new development is such a shame, as in my experience Akka has been the gravitational force attracting a vast majority of the Java programmers (the ones into programming, not data science 😛). That will be over soon. I wonder what will happen to the libraries depending on Akka. You may think of libraries meant for the enterprise, with corporate sponsorship, but what about libraries made by volunteers, like &lt;a href=&quot;https://github.com/DanielaSfregola/twitter4s&quot;&gt;Twitter4s&lt;/a&gt;? Oh, well.&lt;/p&gt;

&lt;p&gt;We’re left with the Scala FP communities, which yield awesome libraries and are awesome people, but the ecosystem is essentially a microcosm of the US political landscape. I’m guessing all programming communities are turning to this nowadays. As an Eastern European, however, it kind of pisses me off.&lt;/p&gt;

&lt;p&gt;Maybe this is just me getting older (going to turn 40 soon). Maybe all programming is terrible.  I’ve actually started to read &lt;a href=&quot;https://blog.jetbrains.com/idea/2022/09/java-annotated-monthly-september-2022/&quot;&gt;Java newsletters&lt;/a&gt;, maybe Spring isn’t that bad, I’m also having affectionate memories of JavaScript and Python, and thinking about having a plan B in case this programming thing doesn’t work out 🤷‍♂️&lt;/p&gt;

&lt;p&gt;Oh, &lt;a href=&quot;https://alexn.org/blog/2020/10/10/when-my-world-vanishes/&quot;&gt;how the mighty have fallen&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Bye, going to reboot my MacBook, since IntelliJ wanted to reload the project, and nothing works anymore.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/09/scala-isnt-fun-anymore/?pk_campaign=rss&quot;&gt;Scala isn&apos;t fun anymore&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 09 Sep 2022 05:00:37 +0000</pubDate>
  <dc:modified>Mon, 19 Sep 2022 16:15:53 +0000</dc:modified>
  <atom:modified>Mon, 19 Sep 2022 16:15:53 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/09/scala-isnt-fun-anymore/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/09/scala-isnt-fun-anymore/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Languages</category>
  <category>Personal</category>
  <category>Politics</category>
  <category>Programming Rant</category>
  <category>Scala</category>
  </item>


<item>
  <title>Akka is moving away from Open Source</title>
  <description>According to today’s announcement, Lightbend is changing Akka’s licensing to “Business Source License (BSL)”. This is not an Open Source, or a Free Software license. This is a proprietary license.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
According to &lt;a href=&quot;https://www.lightbend.com/blog/why-we-are-changing-the-license-for-akka&quot;&gt;today’s announcement&lt;/a&gt;, Lightbend is changing Akka’s licensing to “&lt;em&gt;Business Source License (BSL)&lt;/em&gt;”. This is not an &lt;a href=&quot;https://opensource.org/osd-annotated&quot;&gt;Open Source&lt;/a&gt;, or a &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.en.html&quot;&gt;Free Software&lt;/a&gt; license. This is a proprietary license.
&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
  &lt;strong&gt;UPDATE:&lt;/strong&gt; The license change &lt;a href=&quot;https://github.com/akka/akka/pull/31561&quot;&gt;arrived in the repository&lt;/a&gt;.
&lt;/p&gt;

&lt;h2 id=&quot;freedom&quot;&gt;Freedom&lt;/h2&gt;

&lt;p&gt;Read &lt;a href=&quot;https://www.lightbend.com/akka/license-faq&quot;&gt;their licensing FAQ&lt;/a&gt;. Here’s what to take away from it:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It restricts free usage to non-commercial purposes only, otherwise for any production use you’ll need to have a commercial license:
    &lt;ul&gt;
      &lt;li&gt;This violates Open Source’s &lt;strong&gt;rule 6&lt;/strong&gt;: “&lt;em&gt;no discrimination against fields of endeavor&lt;/em&gt;”;&lt;/li&gt;
      &lt;li&gt;Or Free Software’s &lt;strong&gt;freedom zero&lt;/strong&gt;: “&lt;em&gt;the freedom to run the program as you wish, for any purpose&lt;/em&gt;”;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;It adds a clause that says the software will eventually be licensed as Open Source after 3-4 years.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The commercial license might be free of charge for small companies. That is, if you’re comfortable building your company on &lt;a href=&quot;https://en.wikipedia.org/wiki/Freeware&quot;&gt;freeware&lt;/a&gt; that’s always subject to change.&lt;/p&gt;

&lt;p&gt;Note that such licenses are similar to what Microsoft tried doing with their &lt;a href=&quot;https://en.wikipedia.org/wiki/Shared_Source_Initiative&quot;&gt;shared source initiative&lt;/a&gt;, back in the day when they were comparing copyleft licenses to a virus. It never took off — access to source code is NOT the point of Open Source / Free Software, but rather the freedom to use that source code, even if you’re making money off of it, even if you’re an evil genius that wants to take over the world with your sharks with freaking laser beams attached to their heads, all powered by FOSS.&lt;/p&gt;

&lt;p&gt;I understand the reasoning given in the blog post, but I disagree with it. Here’s why …&lt;/p&gt;

&lt;p&gt;Akka, like other products that pulled a bait-and-switch (e.g., MongoDB and others), is popular &lt;em&gt;because it was marketed as being Open Source / Free Software&lt;/em&gt;, as developers such as myself would never touch proprietary libraries with a ten-foot pole. Such libraries for me simply don’t exist. There are 2 reasons for it:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I need control of whatever runs in my program, I need the ability to fix it myself, or to have other people fix it for me, people that may not be affiliated with the maker of those tools;&lt;/li&gt;
  &lt;li&gt;Software licenses are expensive, add up, and even in big companies that can afford it, going through the endless bureaucracy of having such expenses approved is freaking painful, which is why FOSS may be even more popular in corporations than it is in startups;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href=&quot;https://alexn.org/blog/2022/09/07/free-software-vs-open-source/&quot;&gt;Open Source is free as in “free market economy.”&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;market-for-open-source&quot;&gt;Market for Open Source&lt;/h2&gt;

&lt;p&gt;Selling support or extra tooling in FOSS sometimes works, because it’s complementary — employees can introduce a FOSS library or tool, without any kind of expense approval from upper management, and then the contract for extra stuff can come later, after it has proven its value.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.joelonsoftware.com/2002/06/12/strategy-letter-v/&quot;&gt;Smart companies try to commoditize their products’ complements&lt;/a&gt;, which is what Lightbend tried, but apparently it didn’t work for them. Probably because a software library makes for a poor complement.&lt;/p&gt;

&lt;p&gt;The blog post mentions that MariaDB also adopted this proprietary license. The claim is misleading, because &lt;a href=&quot;https://mariadb.com/kb/en/licensing-faq/&quot;&gt;MariaDB (the product) is licensed under GPL2 / LGPL2&lt;/a&gt;, just like MySQL before it. It couldn’t be otherwise as, to my knowledge, Oracle hasn’t donated the copyright of MySQL. What MariaDB (the company) is actually doing is to offer complementary products, such as MaxScale, otherwise the core server and clients are still Open Source, under GPL2 and LGPL2 respectively. See their &lt;a href=&quot;https://mariadb.com/projects-using-bsl-11/&quot;&gt;own documentation&lt;/a&gt;. The difference couldn’t be more striking. In embracing this license, MariaDB became more open compared to other companies that are doing the &lt;a href=&quot;https://en.wikipedia.org/wiki/Open-core_model&quot;&gt;open-core model&lt;/a&gt;. Whereas Lightbend is embracing this license for their core, on which infrastructure is already built. MariaDB took nothing away from what we already had, a rock-solid FOSS database. Not to mention that MariaDB is server software, not a library.&lt;/p&gt;

&lt;p&gt;It’s morally wrong to make the product popular, by advertising it as Open Source / Free Software, and then doing a reversal later. Don’t get me wrong, I am sympathetic to the issue that Open Source contributors aren’t getting paid. But in the Java community nobody wants to pay licenses for libraries. If that model ever worked, it was in other ecosystems, such as that of .NET, and that model has been dying there as well. Turns out, trying to monetize software libraries is a losing proposition.&lt;/p&gt;

&lt;h2 id=&quot;contributors-agreements&quot;&gt;Contributor’s agreements&lt;/h2&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;UPDATED (2022-09-08 09:32:18):&lt;/strong&gt; This section was modified to correct some missunderstandings. The previous version of this section is &lt;a href=&quot;https://web.archive.org/web/20220908073048/https://alexn.org/blog/2022/09/07/akka-is-moving-away-from-open-source/#copyright-assignments&quot;&gt;available on archive.org&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;Lightbend developed most of Akka, but due to its popularity, Akka definitely received contributions from the community. I’m fairly sure that the people that have contributed to Akka will not get compensated right now. This is similar to other products that made similar moves, such as MongoDB. And I’d love to be proven wrong, BTW, although I’m not sure what compensation would be appropriate, given that FOSS contributions are often made in the faith that the project will keep being FOSS.&lt;/p&gt;

&lt;p&gt;What makes such license changes possible, even if the project used a copyleft license, is the &lt;a href=&quot;https://www.lightbend.com/contribute/cla&quot;&gt;contributor’s license aggreement (CLA)&lt;/a&gt;, which is very similar to &lt;a href=&quot;https://www.apache.org/licenses/contributor-agreements.html&quot;&gt;Apache’s CLA&lt;/a&gt;, saying:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“&lt;em&gt;Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to the Company and to recipients of software distributed by the Company a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.&lt;/em&gt;” (&lt;a href=&quot;https://downloads.lightbend.com/website/legal/LightbendIndividualContributorLicenseAgreement.pdf&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;IANAL, but contributors grant them the right to &lt;em&gt;“sublicense”&lt;/em&gt;, meaning that they can redistribute your work under a different license. In other words, the project could have used a copyleft license (GPL), and a license change would still have been possible. Granted, it could have been worse, like the FSF requiring &lt;a href=&quot;https://www.gnu.org/licenses/why-assign.en.html&quot;&gt;copyright assignments&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Would a copyleft license help, such as the &lt;a href=&quot;https://www.gnu.org/licenses/lgpl-3.0.en.html&quot;&gt;LGPL&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;It depends. Copyleft licenses would prevent the code from being incorporated into proprietary code. However, the license change is still possible, depending on the contributor’s aggreement being signed.&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
I think copyright assignment in Open Source, or aggreements that grant relicensing rights, are EVIL, in spite of all good reasons for it. I do not like to contribute to FOSS projects that ask for such permissions, and you should avoid it too. A license change should require the explicit approval of all contributors, no matter how hard that is.
&lt;/p&gt;

&lt;h2 id=&quot;will-a-fork-happen&quot;&gt;Will a fork happen?&lt;/h2&gt;

&lt;p&gt;The silver lining is that the code will be made Open Source in 3-4 years time. However, consider that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Once a license change happened, it can happen again; license changes destroy trust in the future of the project;&lt;/li&gt;
  &lt;li&gt;3-4 years is an eternity in Scala’s ecosystem (or for libraries in general), due to all the binary backwards compatibility breakage — consider how Akka took a long time to upgrade to Scala 3, or that whatever bug fixes are coming for the current Akka, we’ll probably need those fixes;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also, older versions are still FOSS, still licensed under APL 2.0. This means that a &lt;a href=&quot;https://en.wikipedia.org/wiki/Fork_(software_development)&quot;&gt;fork&lt;/a&gt; is possible. That’s the primary value of FOSS actually — if you’re not happy with the direction of the project, you can always fork. I guess we shall see. Note that forks are hard, primarily due to the resources needed and the branding. People don’t switch easily. But regardless, the notion that Akka is a FOSS project is now over, which means any potential for outside contributions to Akka proper is gone.&lt;/p&gt;

&lt;p&gt;I do hope for a fork to happen. Will FOSS libraries depending on Akka stick to the old FOSS versions, break compatibility by upgrading to the new and non-FOSS versions, or maintain multiple versions? In my opinion, an unintentional fork will happen regardless, simply because many projects will refuse to upgrade to newer versions. I have no popularity metrics though, my assumption here being that Akka is popular enough.&lt;/p&gt;

&lt;h2 id=&quot;feelings&quot;&gt;Feelings&lt;/h2&gt;

&lt;p&gt;Akka is a great project, and has been one of the major reasons for why people chose Scala, or even Java. We’ve been using it at work, with great success. However, going forward I can no longer recommend any kind of investment in it.&lt;/p&gt;

&lt;p&gt;Again, I understand and have known the struggle that FOSS developers and companies go through. FOSS is just not a good business model. But when making decisions about what libraries to use, or where to invest my time, such concerns are simply not my problem. Consider that before this license change I have recommended Akka, and I may have contributed to Akka in my free time, if I ever found the need for it. But after this change, I can no longer do so without getting paid 🤷‍♂️&lt;/p&gt;

&lt;p&gt;I do want to thank Lightbend, from the bottom of my heart ❤️, for all they have contributed. I always loved their work. And I just wish that whatever this is wouldn’t have happened. But it did, and now we have to deal with it.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/07/akka-is-moving-away-from-open-source/?pk_campaign=rss&quot;&gt;Akka is moving away from Open Source&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 07 Sep 2022 16:31:21 +0000</pubDate>
  <dc:modified>Mon, 19 Sep 2022 16:15:46 +0000</dc:modified>
  <atom:modified>Mon, 19 Sep 2022 16:15:46 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/07/akka-is-moving-away-from-open-source/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/07/akka-is-moving-away-from-open-source/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Open Source</category>
  <category>Programming Rant</category>
  <category>Scala</category>
  </item>


<item>
  <title>Open Source vs Free Software</title>
  <description>You may think that Open Source is about having “access to source code”, whereas Free Software is about freedom. Kids, gather around, let me tell you why that’s wrong.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
You may think that Open Source is about having “&lt;em&gt;access to source code&lt;/em&gt;”, whereas Free Software is about freedom. Kids, gather around, let me tell you why that’s wrong.
&lt;/p&gt;

&lt;p&gt;Open Source is based on the &lt;a href=&quot;https://en.wikipedia.org/wiki/Debian_Free_Software_Guidelines&quot;&gt;Debian Free Software Guidelines&lt;/a&gt;. The DFSG was first published in July 1997, the primary author being Bruce Perens. This was Debian Linux’s social contract. And in 1998 the &lt;a href=&quot;https://en.wikipedia.org/wiki/Open_Source_Initiative&quot;&gt;Open Source Initiative&lt;/a&gt; was born, with “Open Source” being officially coined, although the term &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar&quot;&gt;happened earlier&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Interestingly, DSFG and its successor, the Open Source definition, where not based on the Free Software definition. And the Free Software definition did not contain “freedom zero” (aka Open Source’s rule 6), which was added later, being inspired by OSS’s definition.&lt;/p&gt;

&lt;p&gt;However, the definitions of &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.en.html&quot;&gt;Free Software&lt;/a&gt; and that of &lt;a href=&quot;https://opensource.org/osd&quot;&gt;Open Source&lt;/a&gt; are equivalent. I know of no license that is compatible with Free Software, and not with Open Source, or vice-versa. For all intents and purposes, the 2 definitions are the same, except that the Open Source one seems to be more precise (to this uninformed citizen).&lt;/p&gt;

&lt;p&gt;So what’s the difference?&lt;/p&gt;

&lt;p&gt;The difference is one of ideology … while both emphasize the freedom to do what you wish with a program and its source-code, Free Software is an online movement that believes &lt;strong&gt;proprietary software is immoral&lt;/strong&gt;. And while certain proprietary software may be acceptable for now, it is only acceptable on the path towards it being made Free Software. In other words, Free Software proponents are working towards an ideal world in which all software is Free Software.&lt;/p&gt;

&lt;p&gt;Open Source, on the other hand, leaves these politics behind and focuses on the economics of it — Open Source software should exist because it’s good from an economic standpoint, on its own merits, because it can be better than proprietary software (cheaper to build, more secure, etc.). This mentality is shunned by Free Software advocates, who’d prefer Free Software even if there wouldn’t be any economic advantage to it.&lt;/p&gt;

&lt;p&gt;The Open Source definition exists because businesses wanted to release products as Free Software, but either wanted a more clear social contract, or wanted nothing to do with its politics, or the organization behind it. It’s still about freedom though, but from a slightly different perspective.&lt;/p&gt;

&lt;p&gt;When I say that I prefer Open Source software, I say so because I want complete control over it. I want the ability to inspect it, to fix it (or pay others to fix it), to enhance it, and to freely distribute those changes. Some restrictions on redistribution may apply (e.g., GPL), but “redistribution” is clearly defined by copyright law, and those aren’t restrictions on usage, or on the ability to share the derived work. Freedom is about having control, with the ensuing responsibility.&lt;/p&gt;

&lt;p&gt;Many times I prefer proprietary software; I’m typing this on a MacBook after all. Sometimes I don’t want freedom, I just want to get the job done. But, if I am to build a program, I’d rather build on top of Open Source infrastructure, because it’s a pretty bad idea to depend on the whims of some other company that may not even answer phone calls.&lt;/p&gt;

&lt;p&gt;The difference between Free Software and Open Source does manifest in what people choose to work on. It’s the difference between &lt;a href=&quot;https://en.wikipedia.org/wiki/GNU_Compiler_Collection&quot;&gt;GCC&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/LLVM&quot;&gt;LLVM&lt;/a&gt;. For those unfamiliar, GCC is (was?) a monolith that made it hard for companies, such as Apple, to build proprietary plugins and tools that interact with it, such as Xcode. It wasn’t just the license, as allegedly the code was by design made to interact poorly with tooling such that tooling would have to be distributed under a GPL-compatible license. Or so the saying goes. This is precisely how LLVM grew, being funded by Apple, and I might say that LLVM is now a wildly successful project. You might say that the difference is in the copyright license: copyleft vs liberal, but that would be wrong. For another example, Linux’s ethos is &lt;a href=&quot;https://www.theregister.com/2006/03/10/torvalds_gpl_drm/&quot;&gt;closer to Open Source&lt;/a&gt;, which is why some people still hoped for &lt;a href=&quot;https://en.wikipedia.org/wiki/GNU_Hurd&quot;&gt;GNU Hurd&lt;/a&gt; to arrive, in spite of Linux’s dominance (and no, it’s not GNU/Linux 😜).&lt;/p&gt;

&lt;p&gt;Ever since the movements were born, it attracted many followers amongst computer programmers and sysadmins. As Linux started to dominate Internet servers, and as former junior programmers and sysadmins became seniors with buying power, Open Source gained market-appeal. It’s why we had attempts to redefine it, like Microsoft’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Shared_Source_Initiative&quot;&gt;Shared Source&lt;/a&gt;, which granted access to the source code, but only for non-commercial purposes. You’ll be forgiven if you don’t remember &lt;a href=&quot;https://en.wikipedia.org/wiki/Shared_Source_Common_Language_Infrastructure&quot;&gt;Microsoft’s Rotor&lt;/a&gt;, as nobody cared, and &lt;a href=&quot;https://en.wikipedia.org/wiki/Mono_(software)&quot;&gt;Mono developers&lt;/a&gt; were banned from reading that source code, since Microsoft was threatening the Linux ecosystem with patents lawsuits. This was back when Microsoft compared copyleft licenses to a virus and did everything in their power to stop its spread.&lt;/p&gt;

&lt;p&gt;Keeping to the official &lt;em&gt;Open Source definition&lt;/em&gt; is more than just pedantry. If a license is Open Source, you know exactly what you can do with that software, lawyers rarely needed. When a piece of software is not Open Source, the primary cost is your (economic) freedom, and that’s something you need to take into account when calculating your risk and budget.&lt;/p&gt;

&lt;p&gt;Open Source is free as in “free market economy” 😉&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/07/free-software-vs-open-source/?pk_campaign=rss&quot;&gt;Open Source vs Free Software&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 07 Sep 2022 16:28:56 +0000</pubDate>
  <dc:modified>Thu, 08 Sep 2022 06:12:50 +0000</dc:modified>
  <atom:modified>Thu, 08 Sep 2022 06:12:50 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/07/free-software-vs-open-source/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/07/free-software-vs-open-source/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Politics</category>
  <category>Open Source</category>
  </item>


<item>
  <title>Limiting Toxic Technology</title>
  <description>Toxic usage patterns of technology, begone — inspired by a self-help book 🤷‍♂️ I changed my philosophy and habits regarding the use of technology.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/09/06/limiting-toxic-technology/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-apuseni-mountains.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1400&quot; height=&quot;788&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Apuseni Moutains, Romania, near the Scărișoara Ice Cave&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
Toxic usage patterns of technology, begone — inspired by a &lt;a href=&quot;https://www.calnewport.com/books/digital-minimalism/&quot; target=&quot;_blank&quot;&gt;self-help book&lt;/a&gt; book 🤷‍♂️ I changed my philosophy and habits regarding the use of technology.
&lt;/p&gt;

&lt;p&gt;I’m doing this because it felt like the use of online services, driven by my smartphone, has been consuming me. I might say that I’m a smartphone or an online addict, craving shallow online socializing over meaningful face to face conversations, and wasting time on social media, over productive work. The Covid-19 pandemic has made things worse.&lt;/p&gt;

&lt;h2 id=&quot;social-media-use&quot;&gt;Social Media use&lt;/h2&gt;

&lt;p&gt;In regard to social media use, the only winning move is to not play!&lt;/p&gt;

&lt;p&gt;There are advantages to using services like Twitter or Facebook, but overall social media is a toxic environment. I still want to follow some people, or find out about cool technologies, but drastic changes in my usage patterns are needed.&lt;/p&gt;

&lt;p&gt;On Twitter:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Only follow people talking exclusively of programming (via a limited client, e.g., &lt;a href=&quot;https://github.com/RSS-Bridge/rss-bridge&quot;&gt;RSS Bridge&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;No likes, no retweets, no comments, no private messages, no engagement whatsoever.&lt;/li&gt;
  &lt;li&gt;Some people will fall off my social radar and that’s fine.&lt;/li&gt;
  &lt;li&gt;All of my blog posts will get published automatically (via IFTTT or similar).&lt;/li&gt;
  &lt;li&gt;No engagement analytics checked, ever; as a commitment to this rule, if I ever end up checking the engagement on my blog posts, I’ll give up blogging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On Facebook:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Only follow my family and very close friends.
    &lt;ul&gt;
      &lt;li&gt;Excluding those that talk of politics.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;No likes, no shares, no comments, no engagement.&lt;/li&gt;
  &lt;li&gt;Or I might just go through with its deletion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On Reddit:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Only follow it via an RSS/Atom feed reader, and only programming channels;&lt;/li&gt;
  &lt;li&gt;No likes, comments or other engagement;&lt;/li&gt;
  &lt;li&gt;Use it primarily as a search engine 😉&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I want to send a comment, I’ll pick up the phone, or write an email.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;PRO TIP&lt;/strong&gt; — if you want to delete your social media account right now, to work around the 30 days deletion period in which you can change your mind: change your email address to a “masked” one, using your service of choice (e.g., &lt;a href=&quot;https://www.fastmail.help/hc/en-us/articles/4406536368911-Masked-Email&quot;&gt;FastMail&lt;/a&gt;), change the password to something random, change your username to something random, remove your phone or other contact details from your social account, delete your account, delete your masked email address, then delete all traces of your new username, and password. This should make it next to impossible to recover.
&lt;/p&gt;

&lt;h2 id=&quot;smartphone-use&quot;&gt;Smartphone use&lt;/h2&gt;

&lt;p&gt;The smartphone is a slot-machine. Even if you go off Twitter, the smartphone provides an endless stream of apps that are behaving like slot machines, giving us that dopamine hit we crave for. I actually contemplated switching to a dumb phone, but I still need some smartphone functions that would be hard to replace (e.g., maps, internet hotspot, etc.).&lt;/p&gt;

&lt;p&gt;If I pick up my smartphone, I shouldn’t have any statuses to check, or anything on it to fix my boredom. Therefore, the rules are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No social media;&lt;/li&gt;
  &lt;li&gt;No video entertainment (Netflix, TikTok, YouTube);&lt;/li&gt;
  &lt;li&gt;No games;&lt;/li&gt;
  &lt;li&gt;Browser allowed only for 15 minutes per day;&lt;/li&gt;
  &lt;li&gt;Messaging restricted to essential (team members, close family members);&lt;/li&gt;
  &lt;li&gt;Audiobooks and podcasts allowed, but only if fiction, or about programming;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;laptop-use&quot;&gt;Laptop use&lt;/h2&gt;

&lt;p&gt;The laptop is primarily a work device, and it should remain a work device.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Block all social media, or news websites;&lt;/li&gt;
  &lt;li&gt;No games allowed;&lt;/li&gt;
  &lt;li&gt;Restrict all noisy apps;&lt;/li&gt;
  &lt;li&gt;Restrict app choices (e.g., web browser, text editor, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only way I stay in the loop is via a highly curated list of feeds, to which I subscribe via my self-hosted &lt;a href=&quot;https://github.com/FreshRSS/FreshRSS&quot;&gt;FreshRSS&lt;/a&gt; instance, in combination with &lt;a href=&quot;https://reederapp.com/&quot;&gt;Reeder&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Only subscribe to technical blogs, no politics allowed.&lt;/li&gt;
  &lt;li&gt;Save interesting articles for later;&lt;/li&gt;
  &lt;li&gt;Read those saved articles on the weekend;&lt;/li&gt;
&lt;/ul&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
&lt;strong&gt;WARN:&lt;/strong&gt; the feed reader is a slot machine, too, the reason for why it’s added in the “laptop” section, being banned from my smartphone (via DNS-level blocking, to serve as a useful reminder).
&lt;/p&gt;

&lt;h2 id=&quot;video-entertainment&quot;&gt;Video entertainment&lt;/h2&gt;

&lt;p&gt;My use of Netflix/Disney+/HBO Max tends to be pretty unhealthy too, as I end up watching alone, and during late hours.&lt;/p&gt;

&lt;p&gt;Rules:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No binge-watching, I’m allowed only a single episode per day;&lt;/li&gt;
  &lt;li&gt;Only watch on big screens, no personal devices allowed;&lt;/li&gt;
  &lt;li&gt;Prefer to watch with another family member, as watching movies can be a social activity;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;audio-entertainment&quot;&gt;Audio entertainment&lt;/h2&gt;

&lt;p&gt;For programming, listening to music is useful, as it plays the role of white noise, something to help with concentration. Unfortunately I ended up wearing headphones everywhere else, e.g., while walking on the street, during my commute, during house chores, or while eating.&lt;/p&gt;

&lt;p&gt;That’s not very productive, as it’s anti-social, and it deprives you of just thinking, aka meditation or solitude. Due to in-ear headphones I also ended up with an in-ear irritation that was hard to treat. And the habit eventually evolved to listening podcasts, many times with political topics too. Listening to podcasts or audiobooks is actually tiring, and should be done after work, not before, or during.&lt;/p&gt;

&lt;p&gt;I still like listening to music, or to podcasts, however this habit needs limitations too. I’m yet to figure out some good rules for it, but these days I find myself increasingly without headphones.&lt;/p&gt;

&lt;h2 id=&quot;analog-entertainment&quot;&gt;Analog entertainment&lt;/h2&gt;

&lt;p&gt;A common advice given to addicts of technology is to prefer manual chores as leisure activities. Thankfully, we now live in a house with a yard, which provides an endless stream of things to do.&lt;/p&gt;

&lt;p&gt;Reading books, having meaningful face to face conversations, or just thinking are always good options. I’ve also started running again.&lt;/p&gt;

&lt;p&gt;Boredom is good, actually.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/09/06/limiting-toxic-technology/?pk_campaign=rss&quot;&gt;Limiting Toxic Technology&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 06 Sep 2022 00:00:00 +0000</pubDate>
  <dc:modified>Tue, 06 Sep 2022 18:33:27 +0000</dc:modified>
  <atom:modified>Tue, 06 Sep 2022 18:33:27 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/09/06/limiting-toxic-technology/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/09/06/limiting-toxic-technology/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Personal</category>
  <category>Opinion</category>
  </item>


<item>
  <title>Tracking Side Effects in Scala</title>
  <description>What if we’d use Scala’s type system for tracking side-effects in impure code, too? In the Scala/FP community we use and love effect systems, such as Cats Effect, with its IO data type. “Suspending side-effects” in IO is great, but in Scala it’s either IO or forgoing any kind of type-safety for side-effects, and that’s bad.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/05/23/tracking-effects-in-scala/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala3-unsafe-io.png?202603060940&quot; alt=&quot;&quot; width=&quot;1500&quot; height=&quot;937&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
What if we’d use Scala’s type system for tracking side-effects in impure code, too? In the Scala/FP community we use and love effect systems, such as &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats Effect&lt;/a&gt; with its &lt;code&gt;IO&lt;/code&gt; data type. &lt;em&gt;“Suspending side-effects”&lt;/em&gt; in &lt;code&gt;IO&lt;/code&gt; is great, but in Scala it’s either &lt;code&gt;IO&lt;/code&gt; or forgoing any kind of type-safety for side-effects, and that’s bad.
&lt;/p&gt;

&lt;p&gt;In spite of our wishes to the contrary, integration code or low-level code in Scala is inevitable. Also, there are instances in which impure/imperative code is actually clearer. I still have the feeling that Cats-Effect’s &lt;code&gt;Ref&lt;/code&gt; is harder to understand in practice than &lt;code&gt;AtomicReference&lt;/code&gt;, for example, in spite of all benefits of referential transparency or the decoupling that happens between the declarations of expressions and their evaluation. And software-transactional memory can be worse than &lt;code&gt;Ref&lt;/code&gt;, which is probably why in Scala it never took off, in spite of decent implementations available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For impure code&lt;/strong&gt;, I’d still like to notice the side effects, visually, via types, and I still want the compiler to protect me from leaks. Scala 3 makes this easier, via &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/contextual/context-functions.html&quot;&gt;Context Functions&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// SCALA 3

import scala.io.StdIn
// https://dotty.epfl.ch/docs/reference/experimental/erased-defs
// import scala.language.experimental.erasedDefinitions

/*erased*/ class CanSideEffect
/*erased*/ class CanBlockThreads extends CanSideEffect

type UnsafeIO[+A] = CanSideEffect ?=&gt; A

type UnsafeBlockingIO[+A] = CanBlockThreads ?=&gt; A

def unsafePerformIO[A](f: UnsafeIO[A]): A =
  f(using new CanSideEffect)

def unsafePerformBlockingIO[A](f: UnsafeBlockingIO[A]): A =
  f(using new CanBlockThreads)

//-------

object Console {
  def writeLine(msg: String): UnsafeBlockingIO[Unit] =
    println(msg)

  def readLine: UnsafeBlockingIO[String] =
    StdIn.readLine
}

@main def main(): Unit = {
  unsafePerformBlockingIO {
    Console.writeLine(&quot;Enter your name:&quot;)
    val name = Console.readLine
    Console.writeLine(s&quot;Hello, $name!&quot;)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We might also make use of &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/experimental/erased-defs.html&quot;&gt;erased definitions&lt;/a&gt;, to eliminate any overhead, but this is an experimental feature that’s only available in nightly builds.&lt;/p&gt;

&lt;p&gt;Note that this is possible to do in Scala 2, but less nice, although in libraries we might think of developing for the future, without leaving users of Scala 2 in the dust.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// SCALA 2

class CanSideEffect
class CanBlockThreads extends CanSideEffect

type UnsafeIO[+A] = CanSideEffect =&gt; A

type UnsafeBlockingIO[+A] = CanBlockThreads =&gt; A

def unsafePerformIO[A](f: UnsafeIO[A]): A =
  f(new CanSideEffect)

def unsafePerformBlockingIO[A](f: UnsafeBlockingIO[A]): A =
  f(new CanBlockThreads)

//-------

object Console {
  def writeLine(msg: String)(implicit permit: CanBlockThreads): Unit =
    println(msg)

  def readLine(implicit permit: CanBlockThreads): String =
    StdIn.readLine
}

object Main extends App {
  unsafePerformBlockingIO { implicit permit =&gt;
    Console.writeLine(&quot;Enter your name:&quot;)
    val name = Console.readLine
    Console.writeLine(s&quot;Hello, $name!&quot;)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Scala 3 also introduced an experimental feature for dealing with &lt;em&gt;“checked exceptions”&lt;/em&gt; that makes use of this mechanism, see the &lt;a href=&quot;https://github.com/lampepfl/dotty/pull/11721&quot;&gt;“safer exceptions” PR&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is precedent in Scala 2 for using implicits like this. For example, the &lt;code&gt;Await&lt;/code&gt; utilities that we use for &lt;code&gt;Future&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent._
import scala.concurrent.duration._

//...
Await.result(future, 10.seconds)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The implementation of &lt;code&gt;result&lt;/code&gt; is this one:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object Await {
  // ...
  def result[T](awaitable: Awaitable[T], atMost: Duration): T =
    blocking(awaitable.result(atMost)(AwaitPermission))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is making use of Scala’s &lt;a href=&quot;https://docs.scala-lang.org/overviews/core/futures.html#blocking&quot;&gt;“blocking context”&lt;/a&gt;, being decoupled from Scala’s &lt;code&gt;Future&lt;/code&gt; implementation via this interface:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Awaitable[+T] {
  //...
  def result(atMost: Duration)(implicit permit: CanAwait): T
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In other words, the implementation forces the use of &lt;code&gt;Await.result&lt;/code&gt; via a &lt;code&gt;CanAwait&lt;/code&gt; implicit (which can’t be instantiated from user code). This is also how Monix &lt;a href=&quot;https://github.com/monix/monix/blob/346352380c4b2b12a66f83cf7ca416dbebde357b/monix-execution/js/src/main/scala/monix/execution/schedulers/CanBlock.scala#L78&quot;&gt;disallows blocking I/O&lt;/a&gt; methods to run on top of JavaScript (such as &lt;a href=&quot;https://github.com/monix/monix/blob/346352380c4b2b12a66f83cf7ca416dbebde357b/monix-eval/shared/src/main/scala/monix/eval/Task.scala#L1064&quot;&gt;Task.runSyncUnsafe&lt;/a&gt;) 😉&lt;/p&gt;

&lt;p&gt;Another API that I can remember is &lt;a href=&quot;https://web.archive.org/web/20220523184153/https://nbronson.github.io/scala-stm/quick_start.html&quot;&gt;Scala-STM&lt;/a&gt;, a project that I used back in the day, and that looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def addLast(elem: Int): Unit =
  atomic { implicit txn =&gt;
    val p = header.prev()
    val newNode = new Node(elem, p, header)
    p.next() = newNode
    header.prev() = newNode
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The implementation is keeping track of the current transaction, at compile-time, via that implicit parameter. Although, in this case the implicit isn’t just a “compile-time proof”, but rather something that affects the runtime too.&lt;/p&gt;

&lt;p&gt;I think I’m being inspired by Martin Odersky’s presentation:&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=YXDm3WHZT5g&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/YXDm3WHZT5g/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=YXDm3WHZT5g&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Plain Functional Programming by Martin Odersky
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Do you think tracking side effects like this would be useful in libraries? Monix, for example, also contains impure parts, and could make use of it.&lt;/p&gt;

&lt;p&gt;Would you like it? Any prior art that I’m not aware of?&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/05/23/tracking-effects-in-scala/?pk_campaign=rss&quot;&gt;Tracking Side Effects in Scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 23 May 2022 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2022/05/23/tracking-effects-in-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/05/23/tracking-effects-in-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Monix</category>
  <category>Scala</category>
  <category>Scala 3</category>
  </item>


<item>
  <title>OOP vs Type Classes: Ideology</title>
  <description>This article explores the difference between OOP design, and parametric polymorphism with Type Classes, as both are possible in Scala.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/05/13/oop-vs-type-classes-part-1-ideology/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala-oop-vs-type-classes-ideology.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1500&quot; height=&quot;938&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Jacques-Louis David, The Intervention of the Sabine Women, 1799. Oil on canvas. Paris, musée du Louvre.
&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  This article explores the difference between OOP design, and parametric polymorphism with Type Classes, as both are possible in Scala.
&lt;/p&gt;

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

&lt;p&gt;Scala is a hybrid OOP+FP language. If you love OOP, Scala is one of the best static OOP languages. But Scala also exposes parametric polymorphism and can encode type classes.&lt;/p&gt;

&lt;p&gt;Thus, developers can also choose to use parametric polymorphism restricted by type classes (aka ad hoc polymorphism). As if choosing when to use immutability versus object identity wasn’t bad enough, developers are also faced with a difficult choice when expressing abstractions. Such choices create tension in teams, with the code style depending on the team leader or whoever does the code reviews.&lt;/p&gt;

&lt;p&gt;Let’s go through what is OOP, what is ad hoc polymorphism via type classes, how to design type classes, go through the pros and cons, and establish guidelines for what to pick, depending on the use case.&lt;/p&gt;

&lt;h2 id=&quot;video-presentation-youtube&quot;&gt;Video Presentation (YouTube)&lt;/h2&gt;

&lt;p&gt;I also gave a speech in 2021 at &lt;a href=&quot;https://inthecity.scala.love/&quot;&gt;Scala Love in the City&lt;/a&gt; on this same topic. If you’re more into videos, rather than reading words, you can watch this as an alternative, although note this article series has more details that couldn’t fit in video form.&lt;/p&gt;

&lt;p&gt;Head over to YouTube if you want to watch it:&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=UT2K9c66xCU&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/UT2K9c66xCU/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=UT2K9c66xCU&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;abstraction&quot;&gt;Abstraction&lt;/h2&gt;

&lt;p&gt;We are gifted with a brain that’s great at recognizing patterns. Take a look at these shapes, &lt;a href=&quot;https://www.goodreads.com/book/show/31243369-which-one-doesn-t-belong&quot;&gt;which one doesn’t belong?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/which-one-doesnt-belong-1.png&quot; alt=&quot;A picture of 4 shapes (3 triangles, 2 triangles with a right angle, 2 isosceles triangles, 1 pentagon)&quot; width=&quot;1394&quot; height=&quot;1276&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;&lt;/p&gt;

&lt;p&gt;What’s cool is that there is no right answer, you can point at any one of them, thus grouping the other 3 with some common characteristic. We have above:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;3 triangles;&lt;/li&gt;
  &lt;li&gt;2 triangles with a right angle;&lt;/li&gt;
  &lt;li&gt;2 isosceles triangles;&lt;/li&gt;
  &lt;li&gt;3 shapes containing a right angle;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s another one:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/which-one-doesnt-belong-2.png&quot; alt=&quot;A picture of 4 shapes (3 squares, 1 regular quadrilateral)&quot; width=&quot;1424&quot; height=&quot;1134&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;&lt;/p&gt;

&lt;p&gt;We have:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;3 squares, and 1 regular quadrilateral that’s not a square;&lt;/li&gt;
  &lt;li&gt;1 red square, 3 blue;&lt;/li&gt;
  &lt;li&gt;1 big square, 3 small regular quadrilaterals;&lt;/li&gt;
  &lt;li&gt;1 square with a different orientation than the other 3;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What about standard Scala types, how can you group these?&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/types-cloud.png&quot; alt=&quot;Names of Scala types: SortedSet, List, Array, Vector, Option, String, Future, Try, Long, Either, IO&quot; width=&quot;1600&quot; height=&quot;878&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;Some clues:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Types that have a type parameter;&lt;/li&gt;
  &lt;li&gt;Types that implement &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;flatMap&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;Types that implement &lt;code&gt;foreach&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;Data collections;&lt;/li&gt;
  &lt;li&gt;Collection types that can be indexed efficiently;&lt;/li&gt;
  &lt;li&gt;Collections that have an insertion order;&lt;/li&gt;
  &lt;li&gt;Types meant for signaling errors;&lt;/li&gt;
  &lt;li&gt;Types for managing side effects;&lt;/li&gt;
  &lt;li&gt;Types with a sum/concatenation operation;&lt;/li&gt;
  &lt;li&gt;Types with an “empty” value;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re pretty good at observing similarities, right?&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  For these images, I’m plagiarizing Julie Moronuki’s &lt;a href=&quot;https://argumatronic.com/posts/2018-09-02-effective-metaphor.html&quot;&gt;The Unreasonable Effectiveness of Metaphor&lt;/a&gt;, a keynote and an article that I recommend.
&lt;/p&gt;

&lt;p&gt;So what is abstraction?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“&lt;em&gt;To draw away, withdraw, remove&lt;/em&gt;”, from the Latin &lt;em&gt;“abstractus”&lt;/em&gt;;&lt;/li&gt;
  &lt;li&gt;“&lt;em&gt;To consider as a general object or idea without regard to matter&lt;/em&gt;”;&lt;/li&gt;
  &lt;li&gt;“&lt;em&gt;The act of focusing on one characteristic of an object rather than the object as a whole group of characteristics; the act of separating said qualities from the object or ideas&lt;/em&gt;” (late 16th century);&lt;/li&gt;
  &lt;li&gt;“&lt;em&gt;A member of an idealized subgroup when contemplated according to the abstracted quality which defines the subgroup&lt;/em&gt;”;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the context of &lt;em&gt;software development&lt;/em&gt;, abstraction can mean:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;idealization, removing details that aren’t relevant, working with idealized models that focus on what’s important;&lt;/li&gt;
  &lt;li&gt;generalization, looking at what objects or systems have in common that’s of interest, such that we can transfer knowledge, recipes, proofs;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We do this in order to &lt;strong&gt;&lt;em&gt;manage complexity&lt;/em&gt;&lt;/strong&gt; because abstractions allow us to map the problem domain better, by focusing on the essential, and it also helps us to reuse code.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/man-juggling.jpg&quot; alt=&quot;Picture of a man juggling&quot; width=&quot;1600&quot; height=&quot;1530&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;&lt;/p&gt;

&lt;p&gt;The complexity of software projects only grows over time and there’s only so much we can juggle with in our heads.&lt;/p&gt;

&lt;h3 id=&quot;black-box-abstraction&quot;&gt;Black Box Abstraction&lt;/h3&gt;

&lt;p&gt;A black box is a device, system or object that can be viewed in terms of its inputs and outputs. This means that the input and output are well specified, such that we can form a useful &lt;a href=&quot;https://en.wikipedia.org/wiki/Mental_model#:~:text=A%20mental%20model%20is%20an,own%20acts%20and%20their%20consequences.&quot;&gt;mental model&lt;/a&gt; for how it works. Note that the mental model doesn’t have to be correct, it just has to be useful, such that we can operate the system without breaking it open and taking a look at the implementation:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/black-box.png&quot; alt=&quot;Illustration of the black box concept&quot; width=&quot;1500&quot; height=&quot;330&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;The engineering black box ideal&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;These can be simple functions, associating one output value to one input, but not necessarily. Examples of complicated black boxes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Web services;&lt;/li&gt;
  &lt;li&gt;Automobiles;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The input for an automobile is going to be the steering wheel, the gas and brake pedals. Automobiles are complex machines, but we don’t need to know how they work under the hood in order to drive a car from point A to point B.&lt;/p&gt;

&lt;p&gt;And in software development, a common strategy is to build bigger and bigger systems out of black boxes:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/black-box-multi.png&quot; alt=&quot;Illustration of multiple black boxes connected&quot; width=&quot;1450&quot; height=&quot;676&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;No paradigm has a monopoly on composition. FP developers can talk about functions composing, OOP developers can talk about objects composing. FP has the advantage that composition is more automatic, being governed by common protocols that have laws:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/category-theory.png&quot; class=&quot;transparency-fix&quot; alt=&quot;Image illustrating category theory&quot; width=&quot;1400&quot; height=&quot;1400&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;g&lt;/code&gt; are functions, it’s easy to compose them in a bigger function, &lt;code&gt;g ∘ f&lt;/code&gt;. Things get more complicated when the types involved don’t align. For example when that &lt;code&gt;B&lt;/code&gt; type is a &lt;code&gt;Future[_]&lt;/code&gt; or an &lt;code&gt;IO[_]&lt;/code&gt;. But we can come up with protocols such that we can keep this automatic composition.&lt;/p&gt;

&lt;p&gt;So what are we talking about?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;OOP-driven design is best for building black boxes, connected via &lt;a href=&quot;https://en.wikipedia.org/wiki/Design_Patterns&quot;&gt;design patterns&lt;/a&gt; for ensuring decoupling (the arrows between the boxes);&lt;/li&gt;
  &lt;li&gt;FP-driven design is usually more about white-boxes; and for composing boxes, static FP gives us features such as Type Classes, for describing those design patterns via the type system, maximizing correctness and reusability;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🎤 drop — just kidding 😄&lt;/p&gt;

&lt;h2 id=&quot;what-is-oop&quot;&gt;What is OOP?&lt;/h2&gt;

&lt;p&gt;I like asking this question in interviews, as it’s a little confusing. Ask 10 people, and you’ll probably get 10 different answers, being a question that can be attacked on multiple axes: theory, philosophy, implementation details, best practices and design patterns.&lt;/p&gt;

&lt;p&gt;OOP is a paradigm based on the concept of “objects” and their interactions, objects that contain both data and the code for manipulating that data, objects that communicate via messages. And in terms of provided features, we can talk of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Subtype polymorphism, via &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic_dispatch&quot;&gt;single (dynamic) dispatch&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;Encapsulation (hiding implementation details);&lt;/li&gt;
  &lt;li&gt;Inheritance of classes or prototypes;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there’s one defining feature that defines OOP, that’s subtype polymorphism, everything else flowing from it. Subtype polymorphism gives us the &lt;a href=&quot;https://en.wikipedia.org/wiki/Liskov_substitution_principle&quot;&gt;Liskov subtitution principle&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;if S is a subtype of T, then objects of type T may be replaced with objects of type S&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And note that OOP can be seen in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Actor_model&quot;&gt;actor model&lt;/a&gt;; what are actors if not objects capable of async communication? And of course, web services behave like OOP objects, because OOP does a great job at modeling black boxes.&lt;/p&gt;

&lt;p&gt;A great example of an OOP interface:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Iterable[+A] {
  def iterator: Iterator[A]
}

trait Iterator[+A] {
  def hasNext: Boolean
  def next(): A
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Implemented by most collection types. We’ll come back to it in a future article, to contrast and compare with a Type Class approach.&lt;/p&gt;

&lt;h3 id=&quot;are-oop-and-fp-orthogonal-can-they-mix&quot;&gt;Are OOP and FP orthogonal? Can they mix?&lt;/h3&gt;

&lt;p&gt;FP is about working with &lt;a href=&quot;https://alexn.org/blog/2017/10/15/functional-programming/&quot;&gt;mathematical functions&lt;/a&gt;. Nothing stops objects from being “pure”, with their methods being math functions. For one, objects can perfectly describe immutable data structures, although these are less interesting, since they are just “product types” with names, or records:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class Customer(
  name: FullName,
  emailAddress: EmailAddress,
  pass: PasswordHash
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When contrasted with FP, the notion of &lt;em&gt;object identity&lt;/em&gt; (aka mutability) comes up a lot:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“&lt;em&gt;FP removes one important dimension of complexity — To understand a program part (a function), you need no longer account for the possible executions that can lead to that program part&lt;/em&gt;” — Martin Odersky in &lt;a href=&quot;https://www.youtube.com/watch?v=YXDm3WHZT5g&quot;&gt;Simple Functional Programming&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, this is just an ideal, in practice being often a false statement. Let’s take a mutable interface:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Iterator[+A] {
  def hasNext: Boolean
  def next(): A
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can of course “purify” it via &lt;code&gt;IO&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.IO

trait Iterator[+A] {
  def hasNext: IO[Boolean]
  def next: IO[A]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Is this not compatible with FP? How about this one?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;final class Metrics(counter: AtomicLong) {
  def touch(): Long = counter.incrementAndGet()
}
// FP version
final class Metrics private (ref: Ref[IO, Long]) {
  def touch: IO[Long] = ???
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What’s the difference between that, and this totally pure function?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object Metrics {
  // Note the internals are now exposed, but function output
  // depends entirely on function input FTW /s
  def touch(ref: Ref[IO, Long]): IO[Long] = ???
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Does that not have “identity” too? Of course, it does. Suspending side effects in &lt;code&gt;IO&lt;/code&gt; is cool and useful, but in terms of divorcing a function from its context and history of invocations, that’s easier said than done, and FP won’t save you.&lt;/p&gt;

&lt;p&gt;Classes are, after all, just &lt;em&gt;closures with names&lt;/em&gt;.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  In Scala almost every type definition is a class, and every value is an object, functions included. Interacting with objects happens only via method calls. Turtles all the way down. Scala&apos;s OOP facilities and type system are so powerful that they allow us to encode whatever we want, such as type classes or ML modules.
&lt;/p&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
  OOP may be orthogonal with FP, but the ideologies behind them are often at odds!
  So the answer to the question is: yes, they are orthogonal, but with caveats.
&lt;/p&gt;

&lt;h2 id=&quot;what-are-type-classes&quot;&gt;What are Type Classes?&lt;/h2&gt;

&lt;p&gt;In static FP we have parametric polymorphism. Witness the simplest function possible:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def identity[A](a: A): A = a

// Compare and contrast with this one — how
// many implementations can this have?
def foo(a: String): String
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This &lt;code&gt;identity&lt;/code&gt; function can only have one implementation (unless you use reflection or other runtime tricks). But it would be useful to specify capabilities for that &lt;code&gt;A&lt;/code&gt; type:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def sum[A](list: List[A]): A = ???

// Should work for integers
sum(List(1, 2, 3)) //= 6
// Should work for BigDecimal
sum(List(BigDecimal(1.5), BigDecimal(2.5))) //= 4.0
// Should work for strings
sum(List(&quot;Hello, &quot;, &quot;World&quot;)) //= Hello, World
// Should work for empty lists
sum(List.empty[Int]) //= 0
sum(List.empty[String]) //= &quot;&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Can Scala’s or Java’s standard library provide this OOP interface?&lt;/p&gt;

&lt;p&gt;First try:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Combine {
  def combine(other: Combine): Combine
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yikes, that’s not good. We can’t combine any two objects inheriting from &lt;code&gt;Combine&lt;/code&gt;. We can’t sum up an &lt;code&gt;Int&lt;/code&gt; and a &lt;code&gt;String&lt;/code&gt;, as this isn’t JavaScript 😊 Liskov’s substitution principle actually sucks here, as we care about the type, and we don’t want to lose type safety 🙂&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Combine[Self] { self: Self =&gt;
  def combine(other: Self): Self
}

class String extends Combine[String] { ... }

def sum[A &lt;: Combine[A]](list: List[A]): A = ???
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We are making use of Scala’s &lt;a href=&quot;https://docs.scala-lang.org/tour/self-types.html&quot;&gt;self types&lt;/a&gt;, but as you can see, this barely works for &lt;code&gt;combine&lt;/code&gt;, and we are missing an &lt;code&gt;empty&lt;/code&gt;, the neutral element, “zero” for integers, or the empty string. Java/Scala OOP developers would give up at some point, and those stubborn enough would define this dictionary:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Combinable[A] {
  def combine(x1: A, x2: A): A
  def empty: A
}

def sum[A](list: List[A], fns: Combinable[A]): A =
  list.foldLeft(fns.empty)(fns.combine)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that &lt;code&gt;Combinable&lt;/code&gt; is more or less the shape of that &lt;a href=&quot;https://www.scala-lang.org/api/2.13.4/scala/collection/immutable/List.html#foldLeft[B](z:B)(op:(B,A)=%3EB):B&quot;&gt;foldLeft&lt;/a&gt; operation.&lt;/p&gt;

&lt;p&gt;These dictionaries are defined &lt;strong&gt;per type&lt;/strong&gt;, and not per &lt;strong&gt;object instance&lt;/strong&gt;. But wouldn’t it be cool if we also had &lt;em&gt;automatic discovery&lt;/em&gt;? That’s what &lt;em&gt;implicit parameters&lt;/em&gt; in Scala are for:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Oops, the jig is up
trait Monoid[A] {
  def combine(x1: A, x2: A): A
  def empty: A
}

object Monoid {
  // Visible globally.
  // WARN: multiple monoids are possible for integers ;-)
  implicit object intSumInstance extends Monoid[Int] {
    def combine(x1: Int, x2: Int) = x1 + x2
    def empty = 0
  }
}

///...
def sum[A](list: List[A])(implicit m: Monoid[A]): A =
  list.foldLeft(m.empty)(m.combine)
// Or with some syntactic sugar
def sum[A : Monoid](list: List[A]): A = ???
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Behold Type Classes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Dictionaries of functions, defined per type, plus…&lt;/li&gt;
  &lt;li&gt;A mechanism for the &lt;em&gt;global discovery&lt;/em&gt; of defined instances, provided by the language.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Type-classes can have laws too. The &lt;code&gt;Monoid&lt;/code&gt; here has the following laws:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;combine(x, combine(y, z)) == combine(combine(x, y), z)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;combine(x, empty) == combine(empty, x) == x&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are like a &lt;a href=&quot;https://en.wikipedia.org/wiki/Technology_Compatibility_Kit&quot;&gt;TCK&lt;/a&gt; for testing the compatibility of implementations. Some type classes are lawless, because the laws are hard to specify, or because the signature says it all. That’s fine.&lt;/p&gt;

&lt;p&gt;Let’s go back to this signature:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def sum[A : Monoid](list: List[A]): A
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Can you see how it describes precisely what the function does? It takes a &lt;code&gt;Monoid&lt;/code&gt; and &lt;code&gt;List&lt;/code&gt;. What can it do with those, other than to sum up the list? There aren’t that many implementations possible.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;With parametric polymorphism, coupled with Type Classes, the types dictate the implementation — and this intuition, that the signature describes precisely what the implementation does, is what static FP developers call “&lt;em&gt;parametricity&lt;/em&gt;”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And as we shall see, this gives rise to one of the biggest ideological clashes in computer programming, being right up there with Vim vs Emacs, or tabs vs spaces 😎&lt;/p&gt;

&lt;h2 id=&quot;ideological-clash&quot;&gt;Ideological clash&lt;/h2&gt;

&lt;p&gt;OOP and FP are ideologies — sets of beliefs on how it’s best to build programs and manage the ever-growing complexity. This is much like the political ideologies, like the Left vs Right, Progressives vs Conservatives, Anarchism vs Statism, etc., different sets of beliefs for solving the same problem, promoted by social movements.&lt;/p&gt;

&lt;figure class=&quot;content&quot;&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/yin-yang.png&quot; alt=&quot;Yin and Yang&quot; class=&quot;transparency-fix&quot; width=&quot;1400&quot; height=&quot;1400&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://en.wikipedia.org/wiki/Yin_and_yang&quot;&gt;Yin and yang&lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I’m not using this word lightly, computer science is not advanced as a science (via the scientific method), because computer science is also about communication and collaboration, therefore computer science also involves social problems, much like mathematics, but worse, because we can’t rely only on idealized models and logic. And investigating social issues via the scientific method is hard, therefore we basically rely a lot on philosophy, intuition, experience, and fashion.&lt;/p&gt;

&lt;p&gt;Computer science is only self-correcting based on what fails or succeeds in the market, thus relying on free market competition. If a solution is popular, that means that it found &lt;em&gt;product/market fit&lt;/em&gt;. The downside is that going against the tide is difficult, due to lack of credible scientific evidence. For example “&lt;em&gt;it’s based on math&lt;/em&gt;” doesn’t cut it.&lt;/p&gt;

&lt;p&gt;Two sides of the same metaphorical coin, both ideologies attack the problem of local reasoning and ever-growing complexity, and both have been succeeding, but from two slightly different perspectives.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/fp-oop-procedural.png&quot; alt=&quot;Meme on FP with OOP guys teaming up to attack the Procedural guy&quot; width=&quot;747&quot; height=&quot;334&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;OOP is an evolution on procedural programming by encapsulating side effects, whereas FP shuns side effects.&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;We should learn from both, and we should have some fun while doing it, preferably without anyone getting hurt in the process.&lt;/p&gt;

&lt;h3 id=&quot;oop-values&quot;&gt;OOP values&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;flexibility of implementation&lt;/strong&gt;, meaning that the provider of an API only exposes what they &lt;em&gt;can promise&lt;/em&gt; to support, leaving the door open for &lt;em&gt;multiple implementations&lt;/em&gt;;&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;backwards compatibility&lt;/strong&gt;, think web services — if protocols often change, this is disruptive for teams having to do integration, new development often happens by &lt;em&gt;feature accretion&lt;/em&gt; and not &lt;em&gt;breakage&lt;/em&gt;, and in case of &lt;em&gt;breakage&lt;/em&gt;, developers think of &lt;em&gt;versioning&lt;/em&gt;, &lt;em&gt;migrations&lt;/em&gt; and in-place updates of components such that disruption is minimal (on the downside, this also means web services exposing APIs with JSON documents having a lot of nullable fields 🤕);&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;black boxes&lt;/strong&gt;, components being described in terms of their inputs and outputs, data being coupled with the interpretation of that data (see this &lt;a href=&quot;https://news.ycombinator.com/item?id=11946935&quot;&gt;exchange between Alan Kay and Rich Hickey&lt;/a&gt;);&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;resource management&lt;/strong&gt;, in contrast with FP, which makes resource management the job of the runtime, in OOP languages like Scala we implement our own &lt;code&gt;IO&lt;/code&gt;, our own &lt;code&gt;HashMap&lt;/code&gt; and &lt;code&gt;ConcurrentQueue&lt;/code&gt;, etc., and that’s because we have good encapsulation capabilities, access to low-level platform intrinsics, and we don’t shy away from doing optimizations via all sorts of nasty side effects;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;static-fp-values&quot;&gt;Static FP values&lt;/h3&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  I’m saying &lt;em&gt;static FP&lt;/em&gt; because NOT ALL of these are values of the FP ideology as practiced in dynamic languages. I recommend watching &lt;a href=&quot;https://www.youtube.com/watch?v=oyLBGkS5ICk&quot; target=&apos;_blank&quot;,rel=&quot;nofollow&apos;&gt;Spec-ulation (YouTube)&lt;/a&gt;, a keynote by Rich Hickey.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;flexibility at the call site&lt;/strong&gt;, meaning that an implementation, like a function, should be able to work with as many types as possible, and this is often at odds with &lt;em&gt;flexibility of the implementation&lt;/em&gt;, because it means restricting what the implementation can do via &lt;em&gt;type signatures&lt;/em&gt; (a very subtle point, being a case of &lt;em&gt;pick your poison&lt;/em&gt;);&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;correctness&lt;/strong&gt;, API signatures in static FP being very precise, correctness is awesome, but unfortunately this is at odds with &lt;em&gt;backwards compatibility&lt;/em&gt;; correctness often means breakage in the API; static FP devs pride themselves with their language’s ability for refactoring, but refactoring often means breakage by definition;&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;dumb data structures&lt;/strong&gt; — based on the creed that data lives more than the functions operating on it, and that data structures can be more reusable when they are dumb, with interpretation being a matter of the functions operating on it, which can add or remove restrictions as they like; but this is often at odds with &lt;em&gt;encapsulation&lt;/em&gt; and &lt;em&gt;flexibility of implementation&lt;/em&gt;;
    &lt;ul&gt;
      &lt;li&gt;OOP prefers &lt;strong&gt;black boxes&lt;/strong&gt;, FP prefers &lt;strong&gt;white boxes&lt;/strong&gt;;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;dealing with data&lt;/strong&gt; — FP shines within the I/O boundaries set by the runtime (or by OOP), there’s nothing simpler than a function that manipulates immutable data structures, and such functions can be easily divorced from their underlying context;&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;derivation of laws and implementations&lt;/strong&gt; — static typing is about proving correctness, and static FP languages give us tools for automatically deriving proofs and implementations from available ones; e.g. if you have an &lt;code&gt;Ordering[Int]&lt;/code&gt; you can quickly derive an &lt;code&gt;Ordering[List[Int]]&lt;/code&gt;, which isn’t possible in classic OOP;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;degenerate-cases&quot;&gt;Degenerate cases&lt;/h3&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/degenerate-era.jpg&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    A &quot;black hole&quot;, depiction of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Future_of_an_expanding_universe#Degenerate_Era&quot;&gt;&quot;Degenerate Era&quot;&lt;/a&gt;, taken from &lt;a href=&quot;https://www.youtube.com/watch?v=uD4izuDMUQA&quot; target=&quot;_blank&quot;&gt;&quot;TIMELAPS OF THE FUTURE&quot; (YouTube)&lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Compare the degenerate signature for OOP classes:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Actor {
  def send(message: Any): Unit
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Versus the degenerate signature for parametric functions in static FP:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def identity[A](a: A): A
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a spectrum of course. An &lt;code&gt;Actor&lt;/code&gt; can implement literally anything, but dealing with it is very unsafe, that contract is useless, and all reasoning enabled by static typing goes out the window. And &lt;code&gt;identity&lt;/code&gt; works for any type, maximally usable and composable, but it does absolutely nothing, in practice its utility being only to play “Type Tetris”, i.e. succeeding in the invocations of other functions by making the types match. It’s such a sad little function, in spite of being a star at FP conferences.&lt;/p&gt;

&lt;h3 id=&quot;what-do-you-want&quot;&gt;What do you want?&lt;/h3&gt;

&lt;p&gt;These are the questions you have to ask yourself, and they are equivalent:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Whom do you want to constrain, the provider or the client of an API?&lt;/li&gt;
  &lt;li&gt;What do you prioritize, backwards compatibility or correctness?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What we want is everything, but we can only get some balance, depending on use-case. &lt;em&gt;“It depends”&lt;/em&gt; is a boring answer, but the only correct one.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
Everything I just said is the conflict of visions that also applies whenever we talk of the merits of dynamically typed versus statically typed languages 😎 It&apos;s a conflict of visions born from the problem domains and the compromises that people have had to make, which are then modeling their opinions. This conflict is always present, and people have to be aware of it when picking tools, techniques or languages, and when designing their programs, as these visions transcend the tools used or the programming languages and their features.
&lt;/p&gt;

&lt;h2 id=&quot;coming-up-next&quot;&gt;Coming up next…&lt;/h2&gt;

&lt;p&gt;I hope you liked my 1&lt;sup&gt;st&lt;/sup&gt; article on this topic, as more is coming. Watch this space 😎&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/05/13/oop-vs-type-classes-part-1-ideology/?pk_campaign=rss&quot;&gt;OOP vs Type Classes: Ideology&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 13 May 2022 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2022/05/13/oop-vs-type-classes-part-1-ideology/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/05/13/oop-vs-type-classes-part-1-ideology/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>OOP</category>
  <category>FP</category>
  <category>Scala</category>
  </item>


<item>
  <title>Implicit vs Scala 3&#39;s Given</title>
  <description>I don’t like given, as an alternative to implicit in Scala 3. The more I try working with it, the more it annoys me; and my understanding may be superficial, but I don’t like this direction. Here’s a comparisson between given and implicit, that I hope is fair…</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
I don’t like &lt;code&gt;given&lt;/code&gt;, as an alternative to &lt;code&gt;implicit&lt;/code&gt; in &lt;nobr&gt;Scala 3&lt;/nobr&gt;. The more I try working with it, the more it annoys me; and my understanding may be superficial, but I don’t like this direction. Here’s a comparisson between &lt;code&gt;given&lt;/code&gt; and &lt;code&gt;implicit&lt;/code&gt;, that I hope is fair…
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
This article uses Scala &lt;code&gt;3.1.2&lt;/code&gt;, which is the most recent version at the time of writing. I just played around, and may have an incomplete understanding — so instead of doing thorough research, I prefer to complain, in order to have others jump in and correct my misunderstandings 😜 Take this with a grain of salt.
&lt;/p&gt;

&lt;h2 id=&quot;evaluation&quot;&gt;Evaluation&lt;/h2&gt;

&lt;p&gt;Let’s define a type-safe alias for representing email addresses,
and we’d like to implement &lt;a href=&quot;https://typelevel.org/cats/typeclasses/show.html&quot;&gt;cats.Show&lt;/a&gt;
and &lt;a href=&quot;https://typelevel.org/cats/typeclasses/eq.html&quot;&gt;cats.Eq&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Scala 2.13 we’d define the &lt;em&gt;“type-class instances”&lt;/em&gt; in the class’s
&lt;a href=&quot;https://docs.scala-lang.org/overviews/scala-book/companion-objects.html&quot;&gt;companion object&lt;/a&gt;, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;package data

import cats._
import cats.syntax.all._

final case class EmailAddress(value: String)

object EmailAddress {
  implicit val show: Show[EmailAddress] = {
    println(&quot;Initializing Show&quot;)
    v =&gt; v.value
  }

  implicit val equals: Eq[EmailAddress] = {
    println(&quot;Initializing Eq&quot;)
    (x, y) =&gt; x.value === y.value
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we’d like to use these instances, they are available in the
“global scope”, so we can do:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;package main // another package

import cats.syntax.all._
import data.EmailAddress

object Main extends App {
  val email = EmailAddress(&quot;noreply@alexn.org&quot;)

  println(&quot;------&quot;)
  println(s&quot;Show: ${email.show}&quot;)
  println(s&quot;Is equal to itself: ${email === email}&quot;)

  println(&quot;\nMemoized?\n-------&quot;)
  println(s&quot;show: ${implicitly[Show[EmailAddress]] == implicitly[Show[EmailAddress]]}&quot;)
  println(s&quot;equals: ${implicitly[Eq[EmailAddress]] == implicitly[Eq[EmailAddress]]}&quot;)
  println()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which would print:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Initializing Show
Initializing Eq
------
Show: noreply@alexn.org
Is equal to itself: true

Memoized?
-------
show: true
equals: true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let’s switch to &lt;code&gt;given&lt;/code&gt;, which should replace the &lt;code&gt;implicit&lt;/code&gt; flag on these instances. In the official &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/contextual/givens.html&quot;&gt;Scala 3 documentation&lt;/a&gt;, the &lt;code&gt;given&lt;/code&gt; definitions are given outside the companion object, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//...

final case class EmailAddress(value: String)

given show: Show[EmailAddress] = {
  println(&quot;Initializing Show&quot;)
  v =&gt; v.value
}

given equals: Eq[EmailAddress] = {
  println(&quot;Initializing Eq&quot;)
  (x, y) =&gt; x.value === y.value
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is because in Scala 3 the “package objects” don’t need syntax, so you can just dump such definitions in a file.  There’s just one problem — these instances are no longer global, so when we try compiling our project, the compiler now says:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[error]    |no implicit argument of type cats.Show[example.EmailAddress] was found for parameter e of method implicitly in object Predef
[error]    |
[error]    |The following import might fix the problem:
[error]    |
[error]    |  import example.show
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, there is one thing about Scala 3 that I love here: the errors on missing implicits are awesome, because they suggest the possible imports ❤️&lt;/p&gt;

&lt;p&gt;But if you want global visibility, and you should, you still have to place them in a companion object; so the official documentation is a little confusing right now.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//...

final case class EmailAddress(value: String)

object EmailAddress {
  given show: Show[EmailAddress] = {
    println(&quot;Initializing Show&quot;)
    v =&gt; v.value
  }

  given equals: Eq[EmailAddress] = {
    println(&quot;Initializing Eq&quot;)
    (x, y) =&gt; x.value === y.value
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now it works, but there’s a difference:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;------
Initializing Show
Initialized: noreply@alexn.org
Initializing Eq
Equal to itself: true

Memoized?
-------
show: true
equals: true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These &lt;code&gt;given&lt;/code&gt; instances are defined as &lt;code&gt;lazy val&lt;/code&gt;, in fact. The documentation even has this sample:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;given global: ExecutionContext = ForkJoinPool()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Kind of makes sense for this to be lazily evaluated, but consider how you’d define this value in Scala 2.x:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;implicit lazy val global: ExecutionContext = ForkJoinPool()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To me, in a strictly evaluated language like Scala, this definition is much clearer, whereas the &lt;code&gt;given&lt;/code&gt; definition “complects” storage / evaluation, which to me is a separate concern. In a language like Scala, how our values get initialized is a pretty big problem that we always care about.&lt;/p&gt;

&lt;p&gt;But wait, is a &lt;code&gt;given&lt;/code&gt; always a &lt;code&gt;lazy val&lt;/code&gt;? What if we add a type parameter?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;final case class EmailAddress(value: String)

object EmailAddress {
  //...
  // Forcing a type parameter that doesn&apos;t do anything:
  given equals[T &lt;: EmailAddress]: Eq[T] = {
    println(&quot;Initializing Eq&quot;)
    (x, y) =&gt; x.value === y.value
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you’re probably going to guess, the answer is no — adding a
simple type parameter turns this &lt;code&gt;given&lt;/code&gt; definition into a &lt;code&gt;def&lt;/code&gt;,
so now we get this output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;------
Initializing Show
Initialized: noreply@alexn.org
Initializing Eq
Equal to itself: true

Memoized?
-------
show: true
Initializing Eq
Initializing Eq
equals: false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This isn’t obvious at all, because in fact the object reference
for this &lt;code&gt;Eq&lt;/code&gt; instance could be reused, this being perfectly safe:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object EmailAddress {
  //...
  given equals[T &lt;: EmailAddress]: Eq[T] =
    // This cast is perfectly safe due to
    // contra-variance of function parameters 😉
    eqRef.asInstanceOf[Eq[T]]

  private val eqRef: Eq[EmailAddress] = {
    println(&quot;Initializing Eq&quot;)
    (x, y) =&gt; x.value === y.value
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, compare and contrast with usage of &lt;code&gt;implicit&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;implicit def equals[T &lt;: EmailAddress]: Eq[T]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which signature is easier to read?&lt;/p&gt;

&lt;p&gt;But what if we don’t want the &lt;code&gt;lazy val&lt;/code&gt;? What if we always want the behavior of a &lt;code&gt;def&lt;/code&gt;? The &lt;code&gt;lazy val&lt;/code&gt; implies synchronization behavior that we may want to avoid.&lt;/p&gt;

&lt;p&gt;Scala 3 supports an &lt;code&gt;inline&lt;/code&gt; keyword, which is pretty cool, and does what you’d expect:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;//...
object EmailAddress {
  //...
  inline given equals: Eq[EmailAddress] = {
    println(&quot;Initializing Eq&quot;)
    (x, y) =&gt; x.value === y.value
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But that’s not quite the same as a &lt;code&gt;def&lt;/code&gt;. Inlining functions is cool, sometimes, for performance reasons, but other times &lt;a href=&quot;https://en.wikipedia.org/wiki/Inline_expansion#Effect_on_performance&quot;&gt;the effects are unpredictable&lt;/a&gt; and should be used with care.&lt;/p&gt;

&lt;p&gt;Compare and contrast:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;implicit def equals: Eq[EmailAddress]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this context, the only advantage of using &lt;code&gt;given&lt;/code&gt; is in eliminating the name of those values:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object EmailAddress {
  given Show[EmailAddress] =
    v =&gt; v.value

  given Eq[EmailAddress] =
    (x, y) =&gt; x.value === y.value
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sure, this looks cool. Kind of a high price to pay though. And there’s more …&lt;/p&gt;

&lt;h2 id=&quot;final&quot;&gt;Final&lt;/h2&gt;

&lt;p&gt;Consider this example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;final case class TypeInfo[T](
  typeName: String,
  packageName: String,
)

trait Newtype[Src] {
  opaque type Type = Src

  implicit val typeInfo: TypeInfo[Type] = {
    val raw = getClass
    TypeInfo(
      typeName = raw.getSimpleName.replaceFirst(&quot;[$]$&quot;, &quot;&quot;),
      packageName = raw.getPackageName,
    )
  }
}

object FullName extends Newtype[String] {
  // Override, as the default logic may not be suitable;
  override implicit val typeInfo =
    TypeInfo(
      typeName = &quot;FullName&quot;,
      packageName = &quot;example&quot;,
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’m using this same pattern in &lt;a href=&quot;https://github.com/monix/newtypes&quot;&gt;monix/newtypes&lt;/a&gt;, this being an instance in which an implicit value is provided by a trait, but we leave the possibility of overriding it, and for good reasons.&lt;/p&gt;

&lt;p&gt;What if we’d use &lt;code&gt;given&lt;/code&gt;?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Newtype[Src] {
  opaque type Type = Src

  given typeInfo: TypeInfo[Type] = {
    val raw = getClass
    TypeInfo(
      typeName = raw.getSimpleName.replaceFirst(&quot;[$]$&quot;, &quot;&quot;),
      packageName = raw.getPackageName,
    )
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, that doesn’t work, because the declared &lt;code&gt;given&lt;/code&gt; is a &lt;code&gt;final&lt;/code&gt; member, therefore we can no longer override it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[error] -- [E164] Declaration Error: ...
[error] 22 |  override implicit val typeInfo =
[error]    |                        ^
[error]    |error overriding given instance typeInfo in trait Newtype of type example.TypeInfo[example.FullName.Type];
[error]    |  value typeInfo of type example.TypeInfo[example.FullName.Type] cannot override final member given instance typeInfo in trait Newtype
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So finally, this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;given typeInfo: TypeInfo[Type]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Is actually equivalent with this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;implicit final lazy val typeInfo: TypeInfo[Type]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yikes; that’s not obvious 😏&lt;/p&gt;

&lt;h2 id=&quot;vocabulary&quot;&gt;Vocabulary&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/contextual/givens.html&quot;&gt;documentation&lt;/a&gt; can definitely improve, but I don’t think the documentation is the problem.&lt;/p&gt;

&lt;p&gt;As a &lt;strong&gt;vocabulary preference&lt;/strong&gt;, I don’t see how &lt;code&gt;given&lt;/code&gt; makes things easier to understand, especially for beginners, but this is a subjective opinion, and it may be a matter of learned taste. It’s exactly the same concept, though, using &lt;code&gt;given&lt;/code&gt; and &lt;code&gt;using&lt;/code&gt; does not make things easier to understand, unless the power of implicits is limited, implicits being hard to understand due to their power, not due to their naming. And I don’t see how beginners could be given an explanation that doesn’t use the term &lt;em&gt;“implicit parameters”&lt;/em&gt;, something that &lt;em&gt;“givens”&lt;/em&gt; obscures. But I concede that I may lack imagination for teaching 🤷‍♂️&lt;/p&gt;

&lt;p&gt;I will argue that the existence of both &lt;code&gt;implicit&lt;/code&gt; and &lt;code&gt;given&lt;/code&gt; introduces more Perl-like &lt;a href=&quot;https://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it&quot;&gt;TIMTOWTDI&lt;/a&gt;, but in a bad way (I’m saying this as a guy that loves TIMTOWTDI, usually). If &lt;code&gt;given&lt;/code&gt; is the future, I’d like to say that &lt;code&gt;implicit&lt;/code&gt; should be deprecated, but given the current behavior of &lt;code&gt;given&lt;/code&gt;, I hope &lt;code&gt;implicit&lt;/code&gt; stays 🤨&lt;/p&gt;

&lt;p&gt;Does &lt;code&gt;given&lt;/code&gt; have any redeeming quality that I’m not seeing? Maybe any good design reasons for why it forces the current behavior?&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/05/11/implicit-vs-scala-3-given/?pk_campaign=rss&quot;&gt;Implicit vs Scala 3&apos;s Given&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 11 May 2022 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2022/05/11/implicit-vs-scala-3-given/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/05/11/implicit-vs-scala-3-given/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Programming Rant</category>
  <category>Scala</category>
  <category>Scala 3</category>
  </item>


<item>
  <title>Scala OOFP Design Sample</title>
  <description>Scala is considered a multi-paradigm language, for better or worse, being one of the best OOP languages, which is why it’s so versatile. Let’s do a design exercise, going from OOP to static FP, and back. Let’s understand the various techniques promoted in the community, and understand why the OOP design isn’t just “idiomatic” for Scala, but can be superior to alternatives.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/04/18/scala-oop-design-sample/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-04-oofp.png?202603060940&quot; alt=&quot;&quot; width=&quot;1400&quot; height=&quot;787&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
Scala is considered a multi-paradigm language, for better or worse, being one of the best OOP languages, which is why it&apos;s so versatile. Let&apos;s do a design exercise, going from OOP to static FP, and back. Let&apos;s understand the various techniques promoted in the community, and understand why the OOP design isn&apos;t just “idiomatic” for Scala, but can be superior to alternatives.
&lt;/p&gt;

&lt;h2 id=&quot;the-design-problem&quot;&gt;The design problem&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Design a &lt;em&gt;“queue of delayed messages.”&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Should you choose to accept this challenge, the queue should be similar to using a message broker like IBM-MQ, or a Kafka topic, but with the ability to schedule messages to be &lt;em&gt;delivered at exact timestamps in the future&lt;/em&gt;. It also has to support an acknowledgement mechanism, with messages becoming invisible when pulled from the queue, and if the acknowledgement doesn’t happen, then messages have to reappear on the queue after a timeout.&lt;/p&gt;

&lt;p&gt;As an underlying implementation, we could use a RDBMS database via JDBC — in our project (at $work) we use MS-SQL. But we could also have an in-memory implementation, which is actually super useful, and not just as a mock in tests. And we could migrate to a NoSQL database, such as MongoDB, or Redis, or maybe even Cassandra — anything that can do &lt;a href=&quot;https://en.wikipedia.org/wiki/Compare-and-swap&quot;&gt;atomic compare-and-swap operations&lt;/a&gt; (on keys) should work.&lt;/p&gt;

&lt;p&gt;Using a real-world example can be boring, due to all the concerns involved, bear with me…&lt;/p&gt;

&lt;h2 id=&quot;classic-and-impure-oop-design&quot;&gt;Classic and impure OOP design&lt;/h2&gt;

&lt;p&gt;In classic OOP (e.g. Java) we could work with an interface like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import java.util.UUID
import java.time.Instant
import scala.concurrent.Future

trait DelayedQueue[A] {
  /** Schedules new messages on the queue. */
  def offer(m: OfferedMessage[A]): Future[OfferOutcome]
  /** Returns messages ready to be processed. */
  def tryPoll: Future[Option[ReceivedMessage[A]]]
  /** Deletes messages from the queue. */
  def discard(key: String): Future[Unit]
}

enum OfferOutcome { // Scala 3&apos;s tagged unions
  case Created
  case Updated
  case Ignored
}

final case class OfferedMessage[+A](
  key: String,
  payload: A,
  scheduleAt: Instant,
  canUpdate: Boolean,
)

final case class ReceivedMessage[+A](
  message: A,
  messageID: UUID,
  receivedAt: Instant,
  acknowledge: () =&gt; Future[Unit],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using this API, to illustrate its usage for building consumers:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent.ExecutionContext

def drain[A](queue: DelayedQueue[A])(using ExecutionContext): Future[Unit] =
  queue.tryPoll.flatMap {
    case None =&gt; Future.unit
    case Some(msg) =&gt;
      println(s&quot;Received: ${msg.message}&quot;)
      // Acknowledge it, or it will reappear after a timeout;
      msg.acknowledge()
        .flatMap(_ =&gt; drain(queue)) // process next
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are many subtle design choices exposed by this API, which make it an acceptable one. Let’s enumerate …&lt;/p&gt;

&lt;p&gt;1) Given the OOP context, we should already have an intuition that &lt;strong&gt;this interface does I/O&lt;/strong&gt;, because there aren’t many good reasons for why open-world OOP interfaces are needed, the primary reason being that we need to abstract away implementation details that involve I/O;&lt;/p&gt;

&lt;p&gt;2) We are using &lt;code&gt;Future&lt;/code&gt;, so &lt;strong&gt;the I/O can be asynchronous&lt;/strong&gt;. And &lt;code&gt;Future&lt;/code&gt; can be completed with exceptions, so code should install generic exception handlers that do logging or whatever it is that you do with unexpected exceptions;&lt;/p&gt;

&lt;p&gt;3) Messages get persisted based on a &lt;code&gt;key: String&lt;/code&gt;, because when scheduling messages in advance, we may want to also get rid of them in advance; this “delayed queue” could then be used to trigger timeout exceptions for asynchronous operations that fail to yield a result; it’s why we have a &lt;code&gt;discard(key)&lt;/code&gt; operation, which may seem redundant with &lt;code&gt;acknowledge&lt;/code&gt; from &lt;code&gt;ReceivedMessage&lt;/code&gt;, but isn’t;&lt;/p&gt;

&lt;p&gt;4) The generic parameter in &lt;code&gt;DelayedQueue[A]&lt;/code&gt; means &lt;strong&gt;we are forced to have a queue per message-type&lt;/strong&gt;, which is a best practice, and avoids implementation leaks (more on that below);&lt;/p&gt;

&lt;p&gt;5) &lt;strong&gt;All actionable “error” conditions are expressed in the returned types&lt;/strong&gt; — in the case of &lt;code&gt;tryPoll&lt;/code&gt; via the returned &lt;code&gt;Option&lt;/code&gt;, and in the case of &lt;code&gt;offer&lt;/code&gt; via the &lt;code&gt;OfferOutcome&lt;/code&gt; union type; they don’t seem like errors, because they are &lt;em&gt;“designed away”&lt;/em&gt;; in this sample we don’t need &lt;code&gt;Either&lt;/code&gt; or Java’s checked exceptions (more on that below);&lt;/p&gt;

&lt;p&gt;The interface does have flaws — for example, &lt;code&gt;tryPoll&lt;/code&gt; is an operation that has to be repeated, in order to keep the channel open and ready to process messages. If we sleep between successive &lt;code&gt;tryPoll&lt;/code&gt; operations, this might be an implementation detail as well. And it can be improved, but how we handle streaming isn’t the purpose of this article.&lt;/p&gt;

&lt;h3 id=&quot;beware-constraints-can-be-implementation-leaks&quot;&gt;Beware: constraints can be implementation leaks&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Leaky_abstraction&quot;&gt;Leaky abstractions&lt;/a&gt; are common when designing abstract APIs. If you don’t have at least 2 very different implementations, the API isn’t really abstract. And in these abstract OOP interfaces, the constraints placed on parameter types lead to leaky abstractions. But let’s put this to the test…&lt;/p&gt;

&lt;p&gt;Let’s say we don’t want the &lt;code&gt;A&lt;/code&gt; type parameter on the interface, so we could have it per method. But having it per method requires introducing a constraint for serialization/deserialization. Let’s design the type-class:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import monix.newtypes.TypeInfo

class ParsingException(message: String) extends RuntimeException(message)

/**
  * Type-class for serializing and deserializing to and from `String`.
  */
trait ValueCodec[A] {
  def kind: TypeInfo[A]
  def serialize(a: A): String
  def deserialize(s: String): Either[ParsingException, A]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://newtypes.monix.io/api/monix/newtypes/TypeInfo.html&quot;&gt;TypeInfo&lt;/a&gt; is from &lt;a href=&quot;https://github.com/monix/newtypes&quot;&gt;monix-newtypes&lt;/a&gt;, but you can replace it with a plain &lt;code&gt;String&lt;/code&gt; — we are making the &lt;em&gt;name of the type&lt;/em&gt; be part of the persisted key, otherwise we can end up with conflicts when reusing the same database table / queue for multiple data types;&lt;/li&gt;
  &lt;li&gt;Serialization should never return an error; but deserialization can end in error because we are losing information in the serialization process, thus we cannot force validations via the type system, and this error needs to be very explicitly modeled via the type system, as it’s not just an “exception”;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on this codec, our interface could become:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait DelayedQueue {
  def offer[A: ValueCodec](m: OfferedMessage[A]): Future[OfferOutcome]
  def tryPoll[A: ValueCodec]: Future[Option[ReceivedMessage[A]]]
  def discard[A: ValueCodec](key: String): Future[Unit]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see how this sucks:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We are encouraging the usage of a single queue for multiple message types;&lt;/li&gt;
  &lt;li&gt;The call-sites of those methods are awkward;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Serialization method is an implementation leak;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Serializing the values to string makes no sense for an in-memory implementation. It’s also restrictive, as your database might support a binary serialization format that’s more efficient than string (e.g. protocol buffers).&lt;/p&gt;

&lt;p&gt;NOTE — our &lt;code&gt;ValueCodec&lt;/code&gt; isn’t useless. We can still use it for our RDBMS implementation:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;final class DelayedQueueJDBC[A: ValueCodec] private (
  connection: DataSource,
  //...
) extends DelayedQueue[A] {
  //...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice how the constraint is now part of the class’s &lt;em&gt;constructor&lt;/em&gt;, and by being a constructor parameter, it doesn’t have to be part of the abstract interface.&lt;/p&gt;

&lt;h2 id=&quot;suspending-side-effects&quot;&gt;Suspending side effects&lt;/h2&gt;

&lt;p&gt;We can improve our interface by working with an &lt;code&gt;IO&lt;/code&gt; datatype, such as that of &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats Effect&lt;/a&gt;, replacing our usage of &lt;code&gt;Future&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.IO

trait DelayedQueue[A] {
  def offer(m: OfferedMessage[A]): IO[OfferOutcome]
  def tryPoll: IO[Option[ReceivedMessage[A]]]
  def discard(key: String): IO[Unit]
}

final case class ReceivedMessage[+A](
  //...
  acknowledge: IO[Unit],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Our IO-driven API is definitely an improvement. Due to the usage of &lt;code&gt;IO&lt;/code&gt;, it’s even more clear that we are modelling I/O operations with side effects involved. And the applications of these functions are &lt;a href=&quot;https://en.wikipedia.org/wiki/Referential_transparency&quot;&gt;referentially transparent&lt;/a&gt;. We are now proudly making use of FP. For more details on how &lt;code&gt;IO&lt;/code&gt; is better than &lt;code&gt;Future&lt;/code&gt;, I recommend this presentation:&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=qgfCmQ-2tW0&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/qgfCmQ-2tW0/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=qgfCmQ-2tW0&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;And, I would argue that usage of &lt;code&gt;IO&lt;/code&gt; in this API can be the best you can do in Scala 😉&lt;/p&gt;

&lt;h3 id=&quot;beware-io-in-our-api-is-a-constraint&quot;&gt;Beware: IO in our API is a constraint!&lt;/h3&gt;

&lt;p&gt;By specifying &lt;code&gt;IO&lt;/code&gt; we mean that &lt;em&gt;“implementations are free to launch rockets to Mars.”&lt;/em&gt; And that’s good in the OOP sense, as we allow for flexibility of implementation, while keeping the protocol abstract enough that we can understand what’s going on.&lt;/p&gt;

&lt;p&gt;Static FP proponents usually don’t like this (more details below), but I disagree.&lt;/p&gt;

&lt;h2 id=&quot;tagless-final&quot;&gt;Tagless Final&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;IO&lt;/code&gt; can become a type parameter:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait DelayedQueue[F[_], A] {
  def offer(m: OfferedMessage[A]): F[OfferOutcome]
  def tryPoll: F[Option[ReceivedMessage[F, A]]]
  def discard(key: String): F[Unit]
}

final case class ReceivedMessage[F[_], +A](
  //...
  acknowledge: F[Unit],
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;F[_]&lt;/code&gt; is a placeholder for what we call &lt;em&gt;“an effect”&lt;/em&gt;. An effect in the context of FP isn’t a side effect — think of “effects” as anything other than returning the result of a computation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Either&lt;/code&gt; are modeling effects too. NOT side effects, but the main effects. In the English language, an effect is something that has a cause, and in our programming language we model causality via &lt;code&gt;flatMap&lt;/code&gt;. So, as an incomplete and wrong intuition, effects in Scala are modeled via monadic data-types (types that implement a lawful &lt;code&gt;flatMap&lt;/code&gt; and constructor pair, aka &lt;code&gt;Monad&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;By making &lt;code&gt;DelayedQueue&lt;/code&gt; work with any &lt;code&gt;F[_]&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;we could use alternative &lt;code&gt;IO&lt;/code&gt; data type implementations;&lt;/li&gt;
  &lt;li&gt;we could use monad stacks, e.g. &lt;code&gt;EitherT[IO, *]&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;we could use &lt;a href=&quot;https://typelevel.org/cats/datatypes/id.html&quot;&gt;cats.Id&lt;/a&gt; for really simple and pure tests;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And &lt;em&gt;“tagless final”&lt;/em&gt; is a technique that’s equivalent to usage of OOP interfaces, except that the interfaces we get are parametrized by &lt;code&gt;F[_]&lt;/code&gt;, aka the “effect type”.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
There are better places on the web that explain tagless final, and I’m likely doing a bad job. For those wanting to learn more about &lt;em&gt;tagless final&lt;/em&gt; and its correspondence to object algebras, I recommend &lt;a href=&quot;https://www.cs.utexas.edu/~wcook/projects/oa/oa.pdf&quot;&gt;“Extensibility for the Masses: Practical Extensibility with Object Algebras”&lt;/a&gt; and &lt;a href=&quot;https://oleksandrmanzyuk.wordpress.com/2014/06/18/from-object-algebras-to-finally-tagless-interpreters-2/&quot;&gt;“From Object Algebras to Finally Tagless Interpreters”&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;In “tagless final” we define capabilities via OOP-like interfaces (also called “algebras”):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Logger[F[_]] {
  def info(message: String): F[Unit]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then to model our consumer, we can combine multiple algebras:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.Monad
import cats.syntax.all._

def drain[F[_], A](using // Scala 3&apos;s `implicit`
  Monad[F],
  Logger[F],
  DelayedQueue[F, A]
): F[Unit] =
  summon[DelayedQueue[F, A]].tryPoll.flatMap {
    case None =&gt;
      Applicative[F].unit
    case Some(msg) =&gt;
      summon[Logger[F]].info(s&quot;Received: ${msg.message}&quot;)
        .flatMap(_ =&gt; msg.acknowledge) // deletes the message
        .flatMap(_ =&gt; drain[F, A]) // next please
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let’s ignore the implementation and zoom in on this function’s signature:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def drain[F[_], A](using
  Monad[F],
  Logger[F],
  DelayedQueue[F, A]
): F[Unit]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We are saying that we want &lt;code&gt;F[_]&lt;/code&gt; to implement:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code&gt;Monad&lt;/code&gt;: which means a sequencing/chaining of steps is involved, via &lt;code&gt;flatMap&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;Logger&lt;/code&gt;: which means we want to log something;&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;DelayedQueue&lt;/code&gt;: our queuing capability;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what’s called &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Parametricity&quot;&gt;“parametricity”&lt;/a&gt;&lt;/em&gt; in static FP circles: by looking at the function’s signature, we have a pretty good idea of what it does, because the function is so generic that it’s hard for it to do anything else.&lt;/p&gt;

&lt;p&gt;And yet there’s something amiss for any seasoned OOP architect — let’s zoom back on the API:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait DelayedQueue[F[_], A] {
  def offer(m: OfferedMessage[A]): F[OfferOutcome]
  def tryPoll: F[Option[ReceivedMessage[F, A]]]
  def discard(key: String): F[Unit]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this example, we aren’t talking of any &lt;code&gt;F[_]&lt;/code&gt; effect type. It’s ridiculous to think that we can use &lt;code&gt;Either&lt;/code&gt; or &lt;code&gt;Option&lt;/code&gt; here. If we use &lt;code&gt;Id&lt;/code&gt;, we only use it for demonstrative purposes, with absolutely no value.&lt;/p&gt;

&lt;p&gt;We say &lt;code&gt;F[_]&lt;/code&gt; in this API, but as its authors, we know that we are talking of a data type that encapsulates / suspends side effects, but without saying so. This is the opposite of parametricity, and in this context usage of this style is not good API design, unless you really, really want tagless final in your project, and thus rely on conventions (e.g. whenever you see &lt;code&gt;F[_]&lt;/code&gt;, you see &lt;code&gt;IO&lt;/code&gt;). The danger being that readers of this code might not get a good mental model of using this API, because there’s information missing, and that’s bad.&lt;/p&gt;

&lt;p&gt;To be clear — &lt;strong&gt;this isn’t good API design because &lt;code&gt;F[_]&lt;/code&gt; is left unspecified&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To be fair, we could restrict &lt;code&gt;F[_]&lt;/code&gt; to the &lt;a href=&quot;https://typelevel.org/cats-effect/docs/typeclasses/concurrent&quot;&gt;cats.effect.Concurrent&lt;/a&gt; type-class, but at that point we might as well work with &lt;code&gt;IO&lt;/code&gt; directly. And if we’d revert to the IO-driven API, we could have:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def drain[A](
  logger: Logger,
  queue: DelayedQueue[A]
): IO[Unit]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The big difference, in terms of “parametricity”, is that executing an &lt;code&gt;IO&lt;/code&gt; could launch rockets to Mars for all we know, so we can’t really restrict the implementation of this function to depend entirely on its input. But this is Scala for you. On top of the JVM we can do anything, anywhere, anyway, relying somewhat on good practices and conventions for not triggering side effects, or using shared mutable state. And while using &lt;code&gt;F[_]&lt;/code&gt; can make violations of parametricity harder, it doesn’t make it impossible, and those violations have the potential to be worse, since without &lt;code&gt;IO&lt;/code&gt;, you definitely end up with unsuspended side effects.&lt;/p&gt;

&lt;p&gt;There is also another difference … implicit parameters mean that we are using only one instance in the whole project. We have only one &lt;code&gt;Logger&lt;/code&gt; instance, and only one &lt;code&gt;DelayedQueue[A]&lt;/code&gt; instance. This is a best practice. As another example, instances of type-classes need to be unique, because type-classes need &lt;em&gt;coherence&lt;/em&gt;, i.e. if you can’t rely on a single instance being available in the whole project, then the code can lead to bugs, due to function calls yielding different results for the same parameters, depending on the call-site.&lt;/p&gt;

&lt;p&gt;Nothing stops you from converting to implicit parameters, even without &lt;code&gt;F[_]&lt;/code&gt;. I think people abuse implicit parameters, I prefered to reserve use of implicit parameters for type-class instances, but that battle was lost, as with tagless final these “algebras” aren’t necessarily type-classes anyway:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def drain[A](using
  logger: Logger,
  queue: DelayedQueue[A]
): IO[Unit]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For me (&lt;em&gt;personal opinion warning!&lt;/em&gt;), this version is pretty damn explicit about what it does, I don’t see much of a difference in my understanding of it, certainly not a difference that’s big enough to outweigh the cost of introducing higher-kinded types and type-classes. If you’ve been on any medium-sized project, a project that’s regularly looking for promising beginners, I’m pretty sure the concern did come up repeatedly – how in the world are beginners going to cope with learning the use of &lt;code&gt;F[_]&lt;/code&gt; with type-classes and everything related? This on top of everything else, which can increase the barrier to entry significantly. And I think the experience of the job market varries based on the available talent.&lt;/p&gt;

&lt;h2 id=&quot;monad-transformers-zio--are-useless-here&quot;&gt;Monad Transformers, ZIO … are useless here&lt;/h2&gt;

&lt;p&gt;If we’d like to get fancy, we could work with a type that handles “dependency injection” and explicit errors, equivalent to Java’s “checked exceptions”:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type ZIO[-Env, +Error, +Result] =
  Env =&gt; IO[Either[Error, Result]]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We could work with this, but we have to be careful because the JVM doesn’t do tail-calls optimizations (TCO), so this could be memory unsafe. Also, we need &lt;code&gt;Monad&lt;/code&gt; and other type-classes and utilities defined for it, so if using Cats, we could work with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.data.{EitherT, Kleisli}

type ZIO[Env, Error, Result] =
  Kleisli[[A] =&gt;&gt; EitherT[IO, Error, A], Env, Result]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We are combining multiple &lt;a href=&quot;https://en.wikipedia.org/wiki/Monad_transformer&quot;&gt;monad transformers&lt;/a&gt;, and so we have a &lt;em&gt;“monad transformers stack”&lt;/em&gt;. And to express this type, we are using &lt;a href=&quot;https://docs.scala-lang.org/scala3/reference/new-types/type-lambdas.html&quot;&gt;type lambdas&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;NOTE:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the &lt;code&gt;Env&lt;/code&gt; is the “environment”, which specifies what’s needed for the execution of the operation — for example, we might need a JDBC &lt;code&gt;DataSource&lt;/code&gt; or a &lt;code&gt;Logger&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;the &lt;code&gt;Error&lt;/code&gt; type parameter is for signaling errors that must be handled;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This type is equivalent to &lt;a href=&quot;https://zio.dev/version-1.x/datatypes/core/zio&quot;&gt;ZIO[R, E, A]&lt;/a&gt;. A data-type like &lt;code&gt;ZIO&lt;/code&gt; is nicer if you use it everywhere, however I prefer the monad transformers from &lt;a href=&quot;https://typelevel.org/cats/&quot;&gt;Cats&lt;/a&gt;, because they are more composable, and we only pay this price where needed … which in my case is almost never 🤷‍♂️&lt;/p&gt;

&lt;p&gt;Can we have …&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;An explicit environment that makes sense in an abstract API?&lt;/li&gt;
  &lt;li&gt;An explicit error type that signals currently unspecified error conditions?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The answer is NO and NO, because in both cases we are talking of &lt;a href=&quot;https://en.wikipedia.org/wiki/Leaky_abstraction&quot;&gt;implementation leaks&lt;/a&gt;. It doesn’t prevent us from trying, though:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait DelayedQueue[A] {
  def offer(m: OfferedMessage[A]): ZIO[DataSource, SQLException, OfferOutcome]
  def tryPoll: ZIO[DataSource, SQLException, Option[ReceivedMessage[F, A]]]
  def discard(key: String): ZIO[DataSource, SQLException, Unit]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;DataSource&lt;/code&gt; or &lt;code&gt;SQLException&lt;/code&gt; are only relevant for the JDBC-powered implementation, otherwise they are implementation leaks.&lt;/p&gt;

&lt;p&gt;For one, I’m always amazed by the people’s struggle to introduce various automated dependency injection techniques in their project, given we have OOP encapsulation and OOP constructors. Haskell’s monad transformer stacks have always felt off, and it isn’t just Scala’s more limited type inference. Haskell is just not very good at encapsulation, as it’s not a very good OOP language, most features and most of its culture conspiring against OOP-like encapsulation. In Scala, if you have dependencies that you’d like to avoid as explicit parameters, the first strategy is to give them as parameters in a class constructor that’s only called once, then pass that object around. Anything else feels like a hack in Scala, IMO, even if constructor-based dependency injection has its drawbacks.&lt;/p&gt;

&lt;p&gt;As for errors, one can argue that &lt;code&gt;SQLException&lt;/code&gt; is important, and not declaring it in the output type is simply an unspecified error condition. But I’d argue that if it is important, then your API and your application’s design is probably screwed (with exceptions).&lt;/p&gt;

&lt;p&gt;I’m repeating myself — we have no important error type that wasn’t already captured in the return types of our API:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code&gt;Option&lt;/code&gt; is an effect type that signals &lt;code&gt;None&lt;/code&gt; in case there are no messages available; in which case you can stop, or you can retry later;&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;OfferOutcome&lt;/code&gt; is a union data type that tells us if our offering has succeeded or not, taking into account other concurrent offerings;
    &lt;ul&gt;
      &lt;li&gt;But in most cases, it doesn’t matter what this result even is, because after this call is executed, we know for a fact that there is a message scheduled with its corresponding key; so the result itself could be ignored;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this context the usage of &lt;code&gt;ZIO&lt;/code&gt;, to enhance the return types, would violate an important OOP principle:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“Program to an interface, not to an implementation.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the equivalent of &lt;em&gt;“parametricity”&lt;/em&gt;, except it refers to encapsulating implementation details, and use flexible interfaces in your logic. Abstraction, as a general concept, is not just about observing groups of data types that can be operated in the same way. Abstraction is also about ignoring the non-essential, which is what OOP’s encapsulation and subtype polymorphism are doing.&lt;/p&gt;

&lt;p&gt;There is nothing about this &lt;code&gt;ZIO&lt;/code&gt; data type that improves our API in any way, quite the contrary, what it brings to the table is only going to obscure what we’re trying to express, as now we are forced to fill in those type parameters with something:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait DelayedQueue[-Env, A] {
  def offer(m: OfferedMessage[A]): ZIO[Env, Nothing, OfferOutcome]
  def tryPoll: ZIO[Env, Nothing, Option[ReceivedMessage[F, A]]]
  def discard(key: String): ZIO[Env, Nothing, Unit]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that &lt;code&gt;IO[A]&lt;/code&gt; from Cats Effect is the equivalent of &lt;code&gt;ZIO[Any, Nothing, A]&lt;/code&gt; (no, the explicit error type isn’t &lt;code&gt;Throwable&lt;/code&gt;). So we have to parametrize the environment and ignore the error type. Or use both as parameters, but that’s just awful.&lt;/p&gt;

&lt;h2 id=&quot;error-handling&quot;&gt;Error Handling&lt;/h2&gt;

&lt;p&gt;As said multiple times, the important error conditions are already baked into the API. But that’s not entirely accurate — what we did was to design them away. Remember this good principle of software design:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“Design the errors out of existence.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An &lt;em&gt;“error”&lt;/em&gt;, in the English language, means a mistake, an action which is inaccurate or incorrect. This can happen in our programming due to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;incomplete or incorrect input;&lt;/li&gt;
  &lt;li&gt;runtime conditions that are outside of our program’s control;&lt;/li&gt;
  &lt;li&gt;bugs;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our programs mostly care about the happy path, but we have to treat errors too. &lt;em&gt;“Designing errors out of existence”&lt;/em&gt; means that, if you care about an error, then it shouldn’t be an error. This means:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Model an output data type that expresses the “error” in a way that is hard to ignore — e.g. the result of a parsing function is either the parsed result, or some message that needs to be displayed; but this only works for input errors of functions whose result we depend on (i.e. we have a &lt;em&gt;data dependency&lt;/em&gt;), otherwise …&lt;/li&gt;
  &lt;li&gt;Make the errors impossible, such that the caller of your API no longer has the responsibility of dealing with those errors;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Question&lt;/strong&gt; — what can you do with an &lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/sql/SQLException.html&quot;&gt;SQLException&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer: mostly nothing!&lt;/strong&gt; The right place to treat an &lt;code&gt;SQLException&lt;/code&gt; is in the encapsulated implementation of your API. The lower-level it is, the better. Once you stream that to the client, it’s already too late to do anything about it.&lt;/p&gt;

&lt;p&gt;Both Cats’ &lt;a href=&quot;https://typelevel.org/cats/datatypes/eithert.html&quot;&gt;EitherT&lt;/a&gt; and &lt;a href=&quot;https://zio.dev/version-1.x/datatypes/core/zio&quot;&gt;ZIO&lt;/a&gt; exist in order to make errors hard to ignore in instances in which they’d be easy to ignore:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def offer(m: OfferedMessage[A]): IO[Either[SQLException, OfferOutcome]]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this case that &lt;code&gt;SQLException&lt;/code&gt; can be easy to ignore, as we may not care about the &lt;code&gt;OfferOutcome&lt;/code&gt;, so you can easily end up with this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;for {
  _ &lt;- queue.offer(message) // oops!
  _ &lt;- log(&quot;done&quot;)
} yield ()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As a band-aid you can make it more difficult to ignore such exceptions by usage of monad transformers, or related data types. The purpose here being to make that &lt;code&gt;flatMap&lt;/code&gt; less forgiving:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// cats.EitherT
def offer(m: OfferedMessage[A]): EitherT[IO, SQLException, OfferOutcome]
// ZIO
def offer(m: OfferedMessage[A]): ZIO[Any, SQLException, OfferOutcome]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Except this is bad software design. Not only is &lt;code&gt;SQLException&lt;/code&gt; an implementation leak, the bigger problem is that there are only 2 courses of action:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;you can shrug and re-throw it like any other &lt;code&gt;Throwable&lt;/code&gt;, such that the process can log it and do whatever it does for unknown exceptions;&lt;/li&gt;
  &lt;li&gt;you can retry the operation — and here’s the rub — a retry is best left as an implementation detail, because the retry logic depends on the resource type;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And to make matters worse, it’s really hard to parse an &lt;code&gt;SQLException&lt;/code&gt;. Anyone that has ever done it knows that these exceptions aren’t standard at all, and sometimes we end up parsing its &lt;code&gt;message&lt;/code&gt; in order to ascertain whether the transaction can be retried, or not. And there are multiple policies possible:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;in case a concurrent update happened, with the transaction failing, it’s often best for the retry to happen immediately, although it depends on the contention, and it’s good to keep in mind that RDBMS databases don’t do well with many concurrent updates hitting the same table;&lt;/li&gt;
  &lt;li&gt;in case the connection is down, or in case of timeouts, using an &lt;a href=&quot;https://en.wikipedia.org/wiki/Exponential_backoff&quot;&gt;exponential backoff&lt;/a&gt; strategy might be wise;&lt;/li&gt;
  &lt;li&gt;in case of an SQL syntax error, no retry is possible, of course, so you need to bail out as fast as possible;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that we probably have to parse &lt;code&gt;SQLException&lt;/code&gt; in our implementation, in order to return a usable &lt;code&gt;OfferOutcome&lt;/code&gt;. As an API author, if you take the time to parse &lt;code&gt;SQLException&lt;/code&gt; such that you can discriminate between such cases, then why not take care of the retry logic yourself? Designing errors out of existence, in this case, means that the user of the API shouldn’t care.&lt;/p&gt;

&lt;p&gt;If you’re designing a light-weight API that just wraps JDBC, by all means, expose &lt;code&gt;SQLException&lt;/code&gt;, although I’ll be eternally grateful for any JDBC wrapper that avoids exposing &lt;code&gt;SQLException&lt;/code&gt; and gives me something more usable, because it is goddamn awful.&lt;/p&gt;

&lt;h2 id=&quot;epilogue&quot;&gt;Epilogue&lt;/h2&gt;

&lt;p&gt;In application code, in a Scala project, I’d argue that nothing beats the clarity and flexibility of interfaces like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.IO

trait DelayedQueue[A] {
  def offer(m: OfferedMessage[A]): IO[OfferOutcome]

  def tryPoll: IO[Option[ReceivedMessage[A]]]

  def discard(key: String): IO[Unit]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For library code, using an &lt;code&gt;F[_]&lt;/code&gt; type parameter for the effect type might be better, as it allows people to come up with their monad transformers stack, or a different &lt;code&gt;IO&lt;/code&gt; implementation. Such library code allows for a “tagless final” approach, like we’ve seen here, and I admit, people have some good reasons for liking it. However, this doesn’t come without cost, a cost that needs to be balanced by great documentation.&lt;/p&gt;

&lt;p&gt;Scala isn’t Haskell, and for me the &lt;em&gt;tagless final&lt;/em&gt; approach (powered by implicit parameters / type-classes, or even monad transformers), or ZIO, both proved to be anti-OOP. An “idiomatic” Scala style should use its OOP features for OOP polymorphism, as that’s the &lt;em&gt;“path of least resistance”&lt;/em&gt;. And tagless final isn’t incompatible with this approach, but I fear that usage of &lt;code&gt;F[_]&lt;/code&gt; or of advanced language features end up obscuring the APIs exposed — compared to just passing IO-driven OOP interfaces around, as simple parameters.&lt;/p&gt;

&lt;p&gt;These techniques and advanced features have their place in our toolbox, for sure, and the stronger the types, the better, but nothing beats good taste, or design that focuses on ease of use and the &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Design_of_Everyday_Things&quot;&gt;user’s mental model&lt;/a&gt;, and such skills have less to do with static typing, or the application of math.&lt;/p&gt;

&lt;p&gt;Designing good APIs requires empathy for the users of your API. Don’t get me wrong, when you inflict pain on your users, it’s better if that pain is strongly typed, but it would be much better to not inflict that pain at all.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/04/18/scala-oop-design-sample/?pk_campaign=rss&quot;&gt;Scala OOFP Design Sample&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 18 Apr 2022 00:00:00 +0000</pubDate>
  <dc:modified>Tue, 06 Jun 2023 12:19:40 +0000</dc:modified>
  <atom:modified>Tue, 06 Jun 2023 12:19:40 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/04/18/scala-oop-design-sample/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/04/18/scala-oop-design-sample/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>OOP</category>
  <category>Scala</category>
  <category>Scala 3</category>
  </item>


<item>
  <title>Scala&#39;s Gitter to Discord migration mistake</title>
  <description>The Scala community is increasingly using Discord for “real-time chat”. This was announced in December, and the community page lists several Discord “servers”, one of them belonging to Typelevel. I think this move from Gitter to Discord is probably a mistake.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/04/09/scala-gitter-discord-mistake/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
The Scala community is increasingly using Discord for “real-time chat”. This was &lt;a href=&quot;https://www.scala-lang.org/blog/2021/12/21/discord.html&quot;&gt;announced in December&lt;/a&gt;, and the &lt;a href=&quot;https://www.scala-lang.org/community/&quot;&gt;community page&lt;/a&gt; lists several Discord “servers”, one of them belonging to Typelevel. I think this move from Gitter to Discord is probably a mistake.
&lt;/p&gt;

&lt;p&gt;I participated in &lt;a href=&quot;https://typelevel.org/blog/2021/05/05/discord-migration.html&quot;&gt;Typelevel’s migration&lt;/a&gt; as well. The migration was done out of genuine concern for the health of the community, and I considered Discord as a good experiment to have. One can also argue that the community simply went to where the users wanted to be, although in our case it was definitely a decision pushed forward by a committee that helped the migration. Can’t speak for others, but I went after a couple of contributors to convince them to join Discord.&lt;/p&gt;

&lt;p&gt;When comparing Gitter to Discord, the main reasons for why I now believe Gitter is better is because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Information on Gitter is public, it does not require an account to read;&lt;/li&gt;
  &lt;li&gt;Information on Gitter can be linked from across the web;&lt;/li&gt;
  &lt;li&gt;Information on Gitter being public, is indexed by search engines and is being archived;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By contrast, Discord is an information black hole, Discord is a closed ecosystem, Discord is anti-web. It doesn’t matter how much Gitter’s client used to annoy you, these reasons alone make Gitter better than Discord, with Discord unable to have any redeeming quality that make it better for Open Source contributors that want to provide support or to spread knowledge.&lt;/p&gt;

&lt;p&gt;If engagement of new people is a concern, Discord can’t be better because it can’t be read without having an account. If the slowed growth of the community is a concern, I don’t think Gitter was to blame, or that Discord made things better. I could be convinced with numbers, but I don’t think those numbers exist.&lt;/p&gt;

&lt;p&gt;If per-repo silos are a concern, Discord can’t be better because its servers and channels can’t be linked from across the web. Compare the discoverability of &lt;a href=&quot;https://gitter.im/typelevel/cats&quot;&gt;https://gitter.im/typelevel/cats&lt;/a&gt; or &lt;a href=&quot;https://gitter.im/http4s/http4s&quot;&gt;https://gitter.im/http4s/http4s&lt;/a&gt; with &lt;a href=&quot;https://discord.gg/XF3CXcMzqD&quot;&gt;https://discord.gg/XF3CXcMzqD&lt;/a&gt;. On Gitter, people in the &lt;code&gt;scala/scala&lt;/code&gt; Gitter chat room could be redirected to the &lt;code&gt;http4s/http4s&lt;/code&gt; chat room, via web links (an outstanding technology). On Discord, however, that’s not how it works, because Scala-lang and Typelevel have different servers. You must convince people to jump between servers, and to join a server you need an invitation. Discord servers are islands, which makes them silos in a way that Gitter chat rooms have never been.&lt;/p&gt;

&lt;p&gt;As an Open Source contributor, to open a support channel, your project has to be either very popular, or be part of / related to Scalameta, or Typelevel, or ZIO, or Play Framework. Otherwise, you’ll have an uphill battle to convince people in joining Discord, or if they already are Discord users, to convince them to join your server. And creating a support channel on a server that you don’t own means giving up control of that channel to the server’s admins, which has pros and cons. Giving up control means there’s better enforcement of a code of conduct, making people feel safer however, I’m not convinced that the chat rooms are nicer/safer than they were on Gitter.&lt;/p&gt;

&lt;p&gt;Maybe I’m wrong, and moderation is indeed a soul-wrecking job made by unsung heroes. I will also add that there is value in having a Gitter channel per repo, with separate moderators, because in big communities the moderation isn’t a job that can be done by one or a couple of individuals. Not without it leading to burnout. We are burning out our most valuable contributors by pushing them to pick up administrative tasks.&lt;/p&gt;

&lt;p&gt;If inclusivity is a concern, usage of Discord discriminates against those that cannot or will not use Discord, either because Discord blocks them, or because of privacy concerns. Discord’s Terms of Service has been controversial, and they are known for having banned people for discussing cheats in games. AFAIK, they once banned a server that discussed anti-cheating solutions. It also asks for phone numbers if it detects VPNs or Tor, and their app does not work from behind our corporate VPN/proxy, which I believe is a deliberate strategy, not a bug.  If you live in a country that’s problematic for the US, which of Discord or Gitter do you think is more likely to ban you?&lt;/p&gt;

&lt;p&gt;I was triggered by the news that &lt;a href=&quot;https://matrix.org/blog/2022/04/08/this-week-in-matrix-2022-04-08#thunderbird&quot;&gt;Thunderbird&lt;/a&gt; now supports Matrix. Matrix is an &lt;a href=&quot;https://matrix.org/&quot;&gt;open standard for decentralized chat&lt;/a&gt;. &lt;a href=&quot;https://element.io/blog/gitter-is-joining-element/&quot;&gt;Gitter has joined Element&lt;/a&gt;, and it &lt;a href=&quot;https://matrix.org/blog/2020/12/07/gitter-now-speaks-matrix&quot;&gt;speaks Matrix&lt;/a&gt;, which means you can use the &lt;a href=&quot;https://element.io/&quot;&gt;Element app&lt;/a&gt; to connect to it. It’s not perfect, but it works.&lt;/p&gt;

&lt;p&gt;Open Source needs open platforms for teaching. We need the web to stay decentralized. And decentralization is always inconvenient at first, solutions evolve more slowly, but think of how pervasive and awesome email or the web are. I’m not even advertising for Gitter, I’m just anti-Discord. Personally, I’d wish for &lt;a href=&quot;https://www.discourse.org/&quot;&gt;Discourse.org&lt;/a&gt; servers to be more common in the community. Shout-out to &lt;a href=&quot;https://users.scala-lang.org/&quot;&gt;users.scala-lang.org&lt;/a&gt;, &lt;a href=&quot;https://contributors.scala-lang.org/&quot;&gt;contributors.scala-lang.org&lt;/a&gt; or &lt;a href=&quot;https://discuss.lightbend.com/&quot;&gt;discuss.lightbend.com&lt;/a&gt;. Real-time chat isn’t good for providing support or for spreading knowledge, IMO, but that’s a personal preference that wouldn’t exclude people out of the conversation or lock information behind proprietary walls.&lt;/p&gt;

&lt;p&gt;If you’re an Open Source contributor, or user, what I ask of you is to not give up on the open web. That ship may have sailed, but one can hope.&lt;/p&gt;

&lt;h2 id=&quot;update&quot;&gt;Update:&lt;/h2&gt;

&lt;p&gt;To answer one concern — Gitter may not be good for finding information in it, however we are comparing a technical problem with a system that is “defective by design”, just &lt;a href=&quot;https://en.wikipedia.org/wiki/Defective_by_Design&quot;&gt;like DRM is&lt;/a&gt;. There is nothing you can do to fix DRM’s issues, just like there is nothing that can be done to fix Discord.&lt;/p&gt;

&lt;p&gt;I remember legendary conversations that happened on Gitter, and they are still accessible. The web is filled, for example, with bits of wisdom by Fabio Labella (SystemFw) — here’s where he exposed his ideas for what became Cats-Effect 3’s new interruption model:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://gitter.im/typelevel/cats-effect?at=5c5f1a2fef98455ea4096756&quot;&gt;gitter.im/typelevel/cats-effect?at=5c5f1a2fef98455ea4096756&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Such bits may be hard to find, but there, I just pointed you to a useful conversation on Gitter, which is accessible, and you don’t have to have a Discord account in order for you to read it. When comparing how much they suck, they aren’t in the same league.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/04/09/scala-gitter-discord-mistake/?pk_campaign=rss&quot;&gt;Scala&apos;s Gitter to Discord migration mistake&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sat, 09 Apr 2022 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2022/04/09/scala-gitter-discord-mistake/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/04/09/scala-gitter-discord-mistake/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Open Source</category>
  <category>Opinion</category>
  <category>Scala</category>
  </item>


<item>
  <title>On Typelevel and Monix</title>
  <description>Planning the future is difficult, but can bring clarity and purpose. I’m stepping down from the Typelevel Steering Committee. I also have plans for Monix’s future.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/04/05/future-monix-typelevel/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/2022-04-monix.png?202603060940&quot; alt=&quot;&quot; width=&quot;1052&quot; height=&quot;587&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
Planning the future is difficult, but can bring clarity and purpose. See &lt;a href=&quot;https://alexn.org/blog/2022/03/30/focus/&quot;&gt;Finding Focus in Harsh Times&lt;/a&gt; for context.
&lt;/p&gt;

&lt;h2 id=&quot;on-typelevel&quot;&gt;On Typelevel&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://typelevel.org/&quot;&gt;Typelevel&lt;/a&gt; is a great community of builders that want to practice FP in Scala. Its “&lt;em&gt;steering committee&lt;/em&gt;” (&lt;a href=&quot;https://github.com/typelevel/governance/blob/main/STEERING-COMMITTEE.md&quot;&gt;link&lt;/a&gt; / &lt;a href=&quot;https://web.archive.org/web/20220405203006/https://github.com/typelevel/governance/blob/main/STEERING-COMMITTEE.md&quot;&gt;archive&lt;/a&gt;) is a group of brilliant and kind people that are doing great work in keeping the community welcoming and inclusive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I’m stepping down from the Typelevel “Steering Committee”.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Moderating and leading a community is gruesome work made by unsung heroes, and I can’t be a part of it anymore. For some time now I’ve been absent, with my only contributions to steering having been rants, and frankly I’d rather get back to coding or other contributions to Open Source that I can manage.&lt;/p&gt;

&lt;p&gt;Typelevel is growing, and you can make a difference. If you feel you’re a fit, get involved, as there’s a &lt;a href=&quot;https://typelevel.org/blog/2022/04/01/call-for-steering-committee-members.html&quot;&gt;call for ‘steering committee’ members&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-future-of-monix&quot;&gt;The Future of Monix&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://monix.io&quot;&gt;Monix&lt;/a&gt; has been my love project, but due to events unfolding since 2019, with life and the world going mad, I’ve been on an unplanned hiatus from Open Source contributions. I did contribute &lt;a href=&quot;https://github.com/monix/newtypes&quot;&gt;monix-newtypes&lt;/a&gt;, as contributing a new project, scratching an immediate itch, felt easier 🙂&lt;/p&gt;

&lt;p&gt;I’ll be forever grateful to Piotr Gawryś, who helped in maintaining and developing Monix, but eventually development stalled. Development of Monix was stalled primarily because small, incremental improvements are no longer possible. And this happened due to the release of Cats-Effect 3.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats Effect 3&lt;/a&gt; is an awesome new version of an already good library. But while being a necessary upgrade, it fundamentally &lt;a href=&quot;https://github.com/typelevel/cats-effect/discussions/1979&quot;&gt;changes the concurrency model&lt;/a&gt; it was based on. The changes are so profound that it’s arguably an entirely new library, and upgrading Monix isn’t easy, because compatibility means updating &lt;em&gt;everything&lt;/em&gt;. This means not just &lt;code&gt;Task&lt;/code&gt;, but also &lt;code&gt;Cancelable&lt;/code&gt;, &lt;code&gt;CancelableFuture&lt;/code&gt;, &lt;code&gt;Observable&lt;/code&gt;, &lt;code&gt;Iterant&lt;/code&gt;, and I mean everything.&lt;/p&gt;

&lt;p&gt;When Monix started, it had the goal of having “&lt;em&gt;zero dependencies&lt;/em&gt;”. Having no dependencies is a virtue, precisely because those dependencies can seriously break compatibility. There is no way for Monix and CE 3 to currently coexist in the same project, due to JVM’s limitations and the decision for Monix to depend directly on Cats-Effect. If Monix were independent of such base dependencies, it could coexist while its maintainers could afford a hiatus.&lt;/p&gt;

&lt;p&gt;I’m always reminded of Rich Hickey’s thoughts from his &lt;a href=&quot;https://www.youtube.com/watch?v=oyLBGkS5ICk&quot;&gt;Spec-ulation Keynote&lt;/a&gt;. TLDR — when you break compatibility, maybe it’s better to change the namespace too. Given in static FP we care about correctness a lot, how to evolve APIs is a really tough problem. I’m still thinking that Monix’s major versions should be allowed to coexist by changing the package name (e.g. &lt;code&gt;monix.v4&lt;/code&gt;), but few other projects are doing it.&lt;/p&gt;

&lt;p&gt;I will be resuming the work on Monix, and will be calling for volunteers. And I hope I won’t let people down again. My current plan is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Monix will be upgraded to the Cats-Effect 3 model, which will include project-wide changes;&lt;/li&gt;
  &lt;li&gt;The dependency on Cats and Cats-Effect 3, however, will probably be separated in different subprojects; while this involves “orphaned instances”, this decision is made easier by tooling (modularity, ftw):
    &lt;ul&gt;
      &lt;li&gt;the Scala compiler supports custom implicit imports via &lt;code&gt;-Yimports&lt;/code&gt;; I don’t recommend it, but the option is there;&lt;/li&gt;
      &lt;li&gt;Scala 3 automatically suggests possible imports for missing implicits;&lt;/li&gt;
      &lt;li&gt;IntelliJ IDEA too automatically suggests imports;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;I’d like to make &lt;a href=&quot;https://github.com/monix/monix-bio&quot;&gt;monix-bio&lt;/a&gt; be part of the main project;&lt;/li&gt;
  &lt;li&gt;I have some new functionality in mind that will make Monix an unbeatable replacement for &lt;code&gt;scala.concurrent&lt;/code&gt;, RxJava, Akka Streams, and the middle-ground that people need in adopting FP in Scala;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking forward to having fun, I’m very excited about it, actually 🤩&lt;/p&gt;

&lt;p&gt;If you’d like to help in building the next version of Monix, contact me.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/04/05/future-monix-typelevel/?pk_campaign=rss&quot;&gt;On Typelevel and Monix&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 05 Apr 2022 00:00:00 +0000</pubDate>
  <dc:modified>Tue, 05 Apr 2022 21:16:52 +0000</dc:modified>
  <atom:modified>Tue, 05 Apr 2022 21:16:52 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/04/05/future-monix-typelevel/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/04/05/future-monix-typelevel/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Monix</category>
  <category>Personal</category>
  <category>Typelevel</category>
  </item>


<item>
  <title>A Return to Blogging</title>
  <description>I like writing about my personal projects and about programming in general. Helping others learn programming seems to be my calling. I rarely write on this blog, however, but I’m trying to change that. You should have a blog too.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2022/04/01/blogging/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/writing.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1300&quot; height=&quot;746&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
I like writing about my personal projects and about programming in general. Helping others learn programming seems to be my calling. I rarely write on this blog, however, but I&apos;m trying to change that.
&lt;/p&gt;

&lt;p&gt;When writing, &lt;strong&gt;perfect is the enemy of good&lt;/strong&gt;. I’ve noticed this time and time again: the need for an article to be perfect, the need to go in depth, is what’s preventing me from creating more content. And &lt;strong&gt;social media is antithetical to good writing&lt;/strong&gt;, pushing us to regurgitate shallow thoughts that have no lasting value. It’s back to blogging for me.&lt;/p&gt;

&lt;p&gt;So expect more … words, words about &lt;em&gt;programming, personal projects and the life of a software developer&lt;/em&gt;, published on this blog.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
This blog is undergoing a re-organization/simplification. For those that follow my RSS feeds, I apologize if your feed reader is seeing older items as unread.
&lt;/p&gt;

&lt;p&gt;If you’re a software developer, &lt;strong&gt;you should have a technical blog&lt;/strong&gt;. Technical writing improves code documentation and all your communications with colleagues or customers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write on your own domain name&lt;/strong&gt;. My domain is 13 years old by now, and online platforms have risen and fallen during this time, while my blog is still here and will still be here in another decade, happily receiving visitors that find it via search engines.&lt;/p&gt;

&lt;p&gt;And remember, &lt;a href=&quot;https://www.w3.org/Provider/Style/URI&quot;&gt;cool URIs don’t change!&lt;/a&gt; Don’t let your website die, or its articles vanish. Treat your website as a long term personal project that pays dividends. &lt;strong&gt;Choose cheap and long-lasting hosting&lt;/strong&gt; — you want your website to wait for you while you’re on a break. For this reason alone, websites compiled with a static website generator (e.g. Jekyll, Hugo) are the best for us.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/04/01/blogging/?pk_campaign=rss&quot;&gt;A Return to Blogging&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 01 Apr 2022 00:00:00 +0000</pubDate>
  <dc:modified>Sat, 09 Apr 2022 08:25:41 +0000</dc:modified>
  <atom:modified>Sat, 09 Apr 2022 08:25:41 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/04/01/blogging/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/04/01/blogging/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Blogging</category>
  <category>Opinion</category>
  <category>Personal</category>
  </item>


<item>
  <title>Finding Focus in Harsh Times</title>
  <description>Since 2020 world events have obliterated my ability to focus, and anxiety has gone through the roof. This is a personal reflection and a plan for recovery.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;Current events have obliterated my ability to focus, both at work, or in my personal projects. Since the beginning of 2020, I&apos;ve had bouts of helplessness, anger, or feelings of isolation. When the war started at our borders, I felt brain fog that lasted for days, my heart sinking for all those innocent people that are under fire. On top of the pandemic, we&apos;re now dealing with war, and the related anxiety. Yikes!&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;
    &lt;em&gt;“Looking for tips on how to keep focus at work while the world is burning”&lt;/em&gt;
    — &lt;a href=&quot;https://x.com/alexelcu/status/1504749134376488962&quot; target=&quot;_blank&quot;&gt;@alexelcu / March 18, 2022&lt;/a&gt;
  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I should feel privileged. My close family and friends are well and healthy, Covid-19 has spared us for now, financially we’ve been thriving. Life has been good for us, yet this privilege seems fleeting.&lt;/p&gt;

&lt;p&gt;I’m probably depressed, because the world around us seems to be burning, and the suffering of others makes me suffer. The symptoms of depression may be subtle for the uninitiated — it’s not just feeling sad, as that comes and goes in short episodes. It’s also boredom, inability to focus, itching for the next news cycle, lack of energy, changes in appetite, loss of joy.&lt;/p&gt;

&lt;p&gt;I’m not qualified to give advice, I’m not even over the current events. This is mostly advice given to myself…&lt;/p&gt;

&lt;p&gt;Is it time to &lt;strong&gt;talk with a mental health professional?&lt;/strong&gt; I don’t know. If you’re in the same situation as I am, maybe you should. Post-2020, maybe we all need to explore our feelings, and even treat any chemical imbalances if given a prescription. Right now, though, I’m exploring changes in my behavior, as some things are under our control.&lt;/p&gt;

&lt;p&gt;The first step in any recovery is &lt;strong&gt;admitting the problem&lt;/strong&gt;, and focusing on why it needs to be fixed.&lt;/p&gt;

&lt;p&gt;While my standing is secure, I’m my family’s provider, my family is depending on me, I can’t afford to disappoint them, a persistent thought that’s always with me. &lt;strong&gt;Having responsibilities towards others is good&lt;/strong&gt;, as loving oneself is easier said than done. I always said that my responsibilities as a husband and father have kept me on my toes. In general, helping others helps us thrive, not just because of karma, but because it makes us feel needed, and being needed makes us happier. I am privileged to have a family that depends on me. And maybe I need to do more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://thomasjbevan.substack.com/p/all-news-is-bad-news?s=r&quot;&gt;No News Is Good News&lt;/a&gt;&lt;/strong&gt; (&lt;a href=&quot;https://web.archive.org/web/20220330064159/https://thomasjbevan.substack.com/p/all-news-is-bad-news?s=r&quot;&gt;archive&lt;/a&gt;). TLDR — the author of this article advocates for disconnecting from news, because nothing important will happen without you finding out about it. Political discourse and virtue signaling on social media doesn’t help, righteous fury doesn’t help, it only contributes to the noise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Donations help, punditry doesn’t.&lt;/strong&gt; I’ve committed to a recurring donation to UNICEF until this war is over. Put your money where your mouth and mind are. If there’s going to be any physical or mental effort, that effort needs to count.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worry about things that are in our control.&lt;/strong&gt; We can’t stop the war, we can’t stop the pandemic, these aren’t in our control. It’s counterproductive to worry about things that we can’t control. I’m trying to embrace stoicism, as you can see 🙂 Like all philosophies, this comes with practice.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;
    &lt;em&gt;“
      Things in our control are opinion, pursuit, desire, aversion, and, in a word, whatever are our own actions. Things not in our control are body, property, reputation, command, and, in a word, whatever are not our own actions.”&lt;/em&gt;
    — opening paragraph of &lt;a href=&quot;https://en.wikipedia.org/wiki/Enchiridion_of_Epictetus&quot;&gt;Enchiridion&lt;/a&gt;, a handbook of &lt;a href=&quot;https://en.wikipedia.org/wiki/Stoicism&quot;&gt;Stoicism&lt;/a&gt;.
  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Find your sense of spirituality.&lt;/strong&gt; Did I ever mention that I’m an Agnostic Theist? I don’t know if there is a God, but I’m not an atheist either. Like many millennials, I have my own spirituality. I certainly believe in a soul, and in the need to take good care of it. Humans crave religion, because science is limited in scope and doesn’t have answers or even questions for our spirit. There are multiple types of atheists in our society, and most believe in a religion that can be worse than Christianity with its ethics. And in theory nihilism can be optimistic and constructive, but I don’t believe it. This may be a good time to search for your god — which is another way of saying to go find meaning in life.&lt;/p&gt;

&lt;p&gt;In Romania, we are going through &lt;a href=&quot;https://en.wikipedia.org/wiki/Great_Lent&quot;&gt;Orthodox Lent&lt;/a&gt;, which is a 40 days period of fasting before Easter. This is a period of soul cleansing. And so I’m implementing a great fast that includes abstinence from all animal products, abstinence from absolutely all news, and abstinence from politics. Fasting from news is not going great, my fingers are twitching to get my phone, and see the live stream of recent events, or political commentary. But I’m pulling through, and it’s immensely refreshing to start the day without a doomscroll each morning.&lt;/p&gt;

&lt;p&gt;To implement this I’ve blocked (via &lt;a href=&quot;https://nextdns.io&quot;&gt;DNS&lt;/a&gt; and browser extensions): Twitter, Facebook, Reddit, and all news outlets I could think of. This ensures that I stop and think whenever I get a craving for news, instead of mindlessly pulling my phone and starting to doomscroll. The only news I get is from low-traffic blogs, mostly on programming, that I follow via my RSS/Atom feed reader.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The best therapy in dark times is probably work and routine.&lt;/strong&gt; We are designed to be active, to build and to think, so we can try (in no particular order):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Being more present at our $job, helping our colleagues, creating value;&lt;/li&gt;
  &lt;li&gt;Writing in one’s blog or personal diary;&lt;/li&gt;
  &lt;li&gt;Contributing to Open Source;&lt;/li&gt;
  &lt;li&gt;Gardening, other hobbies;&lt;/li&gt;
  &lt;li&gt;Exercise;&lt;/li&gt;
  &lt;li&gt;Meditation;&lt;/li&gt;
  &lt;li&gt;More social interactions, preferably face to face;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To my shame, my social interactions are low, I haven’t been doing exercises during winter, I haven’t been doing any meditation, I rarely write on my blog or in a diary nowadays, I have a long hiatus from Open Source, and I don’t really have hobbies, not ones that involve physical activity anyway. Hopefully I can do something about it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Being around other people helps.&lt;/strong&gt; Forget old grudges, especially with friends and family. This is the time to strengthen our relationships, to give and forgive, as there’s strength in numbers. A primary effect of this pandemic has been dehumanization. Companies asking employees to get back to the office can be a good thing, if all this remote work has led to our isolation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seasons always change.&lt;/strong&gt; During summer, it feels like winter will never come back, and during winter, it feels like summer will never come back.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/magnolia-v2.jpg&quot; alt=&quot;&quot; width=&quot;1400&quot; height=&quot;788&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    My neighbour&apos;s magnolia tree.
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Spring and summer always come after winter, and the world tends to change for the better if we wait long enough, so &lt;strong&gt;trust that all will be well in the end&lt;/strong&gt;, doing our part in the meantime. We deserve our spring, though, it’s been a long time coming.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/03/30/focus/?pk_campaign=rss&quot;&gt;Finding Focus in Harsh Times&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 30 Mar 2022 14:08:01 +0000</pubDate>
  <dc:modified>Sat, 18 May 2024 07:19:18 +0000</dc:modified>
  <atom:modified>Sat, 18 May 2024 07:19:18 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/03/30/focus/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2022/03/30/focus/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Personal</category>
  </item>


<item>
  <title>Cleanup Scala/Java project</title>
  <description>Snippet for cleaning up a Scala project’s directory of all compiled files.</description>
  <content:encoded>&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;#!/usr/bin/env bash
set -e

DIR_TO_CLEAN=&quot;$1&quot;

if [ -z &quot;$DIR_TO_CLEAN&quot; ]; then
  echo &quot;ERROR: path was not given!&quot;
  exit 1
elif ! [[ -d &quot;$DIR_TO_CLEAN&quot; ]]; then
  echo &quot;ERROR: path given is not a directory!&quot;
  exit 2
fi

cd &quot;$DIR_TO_CLEAN&quot; || exit 1

# Deletes the project&apos;s &quot;target&quot; directories,
# except for stuff in ./project or in dot dirs (.bloop)
find . -name target -type d \
  -not \( -path &apos;./project*&apos; -o -path &apos;./.*&apos; \) \
  -print \
  -prune \
  -exec rm -rf &quot;{}&quot; \;

# Deletes all empty directories, except for stuff in dot dirs (.git)
find . -type d -empty \
  -not \( -path &apos;./.*&apos; -o -path &apos;./project*&apos; \) \
  -print \
  -prune \
  -exec rm -r &quot;{}&quot; \;
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2022/01/22/cleanup-scala-project/?pk_campaign=rss&quot;&gt;Cleanup Scala/Java project&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sat, 22 Jan 2022 00:00:00 +0000</pubDate>
  <dc:modified>Tue, 17 Jan 2023 11:17:48 +0000</dc:modified>
  <atom:modified>Tue, 17 Jan 2023 11:17:48 +0000</atom:modified>
  <link>https://alexn.org/blog/2022/01/22/cleanup-scala-project/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2022/01/22/cleanup-scala-project/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>CLI</category>
  <category>Scala</category>
  <category>Shell</category>
  </item>


<item>
  <title>VSCode workplace recommended extensions</title>
  <description>You can recommend the required VSCode extensions per repository to your fellow programmers. This is what VSCode calls “workspace recommended extensions”.</description>
  <content:encoded>&lt;p&gt;You can recommend the required &lt;a href=&quot;https://code.visualstudio.com/&quot; target=&apos;_blank&quot;,rel=&quot;nofollow&apos;&gt;VSCode&lt;/a&gt; extensions per repository to your fellow programmers. This is what VSCode calls “&lt;a href=&quot;http://go.microsoft.com/fwlink/?LinkId=827846&quot; target=&quot;_blank&quot;&gt;workspace recommended extensions&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;For example, if your project is a &lt;a href=&quot;https://www.scala-lang.org/&quot; target=&quot;_blank&quot;&gt;Scala&lt;/a&gt; project, maybe you want to recommend the extension for syntax highlighting, &lt;a href=&quot;https://scalameta.org/metals/&quot;&gt;Metals&lt;/a&gt;, and others.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;.vscode/extensions.json&lt;/code&gt; to your repository:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// .vscode/extensions.json
{
  // See http://go.microsoft.com/fwlink/?LinkId=827846
  // for the documentation about the extensions.json format
  &quot;recommendations&quot;: [
    // Scala IDE: https://scalameta.org/metals/
    &quot;scalameta.metals&quot;,

    // This package is already included by Metals (above), but if people
    // don&apos;t like Metals, then at least recommend syntax highlighting
    &quot;scala-lang.scala&quot;,

    // Scaladex search for software dependencies
    &quot;baccata.scaladex-search&quot;,
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On opening the workspace, VSCode will recognize the file and ask if you want to install the recommended extensions:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/snippets/recommended-extensions.png&quot; width=&quot;1318&quot; height=&quot;740&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;VSCode asking you if you want to install the recommended extensions.&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/08/29/vscode-recommended-extensions-vscode-extensions-json/?pk_campaign=rss&quot;&gt;VSCode workplace recommended extensions&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 29 Aug 2021 00:00:00 +0000</pubDate>
  <dc:modified>Mon, 19 Sep 2022 16:11:59 +0000</dc:modified>
  <atom:modified>Mon, 19 Sep 2022 16:11:59 +0000</atom:modified>
  <link>https://alexn.org/blog/2021/08/29/vscode-recommended-extensions-vscode-extensions-json/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2021/08/29/vscode-recommended-extensions-vscode-extensions-json/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Unsafe Lazy Resource.scala</title>
  <description>Snippet for an impure way (no IO) to create a resource that can later be closed.</description>
  <content:encoded>&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;em&gt;I need an impure way (no IO) to create a resource atomically only once and later be able to know if it was created or not, so I can close this resource safely. 🤔&lt;/em&gt;&lt;br&gt;&lt;br&gt;Jules Ivanic (@guizmaii) ⬇️ &lt;a href=&quot;https://x.com/guizmaii/status/1422111131556974592&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;August 2, 2021&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.util.control.NonFatal

/** Builds a &quot;closeable&quot; resource that&apos;s initialized on-demand.
  *
  * Works like a `lazy val`, except that the logic for closing
  * the resource only happens in case the resource was initialized.
  *
  * NOTE: it&apos;s called &quot;unsafe&quot; because it is side-effecting.
  * See homework.
  */
final class UnsafeLazyResource[A](
  initRef: () =&gt; A,
  closeRef: A =&gt; Unit,
) extends AutoCloseable {

  /** Internal state that works like a FSM:
    *  - `null` is for pre-initialization
    *  - `Some(_)` is an active resource
    *  - `None` is the final state, a closed resource
    */
  @volatile private[this] var ref: Option[A] = null

  /**
    * Returns the active resources. Initializes it if necessary.
    *
    * @return `Some(resource)` in case the resource is available,
    *         or `None` in case [[close]] was triggered.
    */
  def get(): Option[A] =
    ref match {
      case null =&gt;
        // https://en.wikipedia.org/wiki/Double-checked_locking
        this.synchronized {
          if (ref == null) {
            try {
              ref = Some(initRef())
              ref
            } catch {
              case NonFatal(e) =&gt;
                ref = None
                throw e
            }
          } else {
            ref
          }
        }
      case other =&gt;
        other
    }

  override def close(): Unit =
    if (ref ne None) {
      val res = this.synchronized {
        val old = ref
        ref = None
        old
      }
      res match {
        case null | None =&gt; ()
        case Some(a) =&gt; closeRef(a)
      }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import java.io._

def openFile(path: File): UnsafeLazyResource[InputStream] =
  new UnsafeLazyResource(
    () =&gt; new FileInputStream(path),
    in =&gt; in.close()
  )

val lazyInput = openFile(new File(&quot;/tmp/file&quot;))
// .. later
try {
  val in = lazyInput.get().getOrElse(
    throw new IllegalStateException(&quot;File already closed&quot;)
  )
  //...
} finally {
  lazyInput.close()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;homework&quot;&gt;Homework&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Try using an &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html&quot; target=&quot;_blank&quot;&gt;AtomicReference&lt;/a&gt; instead of synchronizing a &lt;code&gt;var&lt;/code&gt; — not as obvious as you’d think — initialization needs protection, you’ll need an indirection 😉&lt;/li&gt;
  &lt;li&gt;Try designing a pure API with Cats Effect’s &lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/resource&quot; target=&quot;_blank&quot;&gt;Resource&lt;/a&gt; (you might need &lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/ref&quot; target=&quot;_blank&quot;&gt;Ref&lt;/a&gt; and &lt;a href=&quot;https://typelevel.org/cats-effect/docs/std/deferred&quot; target=&quot;_blank&quot;&gt;Deferred&lt;/a&gt; for your internals too)&lt;/li&gt;
&lt;/ol&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/08/02/unsafelazyresource-scala/?pk_campaign=rss&quot;&gt;Unsafe Lazy Resource.scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 02 Aug 2021 00:00:00 +0000</pubDate>
  <dc:modified>Sat, 18 May 2024 07:19:17 +0000</dc:modified>
  <atom:modified>Sat, 18 May 2024 07:19:17 +0000</atom:modified>
  <link>https://alexn.org/blog/2021/08/02/unsafelazyresource-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2021/08/02/unsafelazyresource-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Combining the terminal (iTerm) with the IDE</title>
  <description>⌘+Click on a file path triggers my terminal to open that file inside my IDE, and that helps a lot.</description>
  <content:encoded>&lt;p&gt;&lt;code&gt;⌘+Click&lt;/code&gt; on a file path triggers my terminal to open that file inside my IDE, and that helps a lot:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/iterm-semantic-history-demo.gif&quot; alt=&quot;&quot; width=&quot;877&quot; height=&quot;548&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;Demo of iTerm&apos;s semantic history&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I’m a terminal-first, IDE-second guy. Whatever I can get quickly done in the terminal, I do in the terminal.&lt;/p&gt;

&lt;p&gt;When doing software development, if you compile and test the code in the terminal, going back and forth between the terminal and your IDE has friction. A lot of people just open a terminal from within their IDE, but personally I don’t like that, I think the terminal with the build tool should run separately from the IDE, because you then have the flexibility to restart them independently, or switch IDEs when in the mood.&lt;/p&gt;

&lt;p&gt;I’m using &lt;a href=&quot;https://iterm2.com/&quot;&gt;iTerm&lt;/a&gt;, the macOS terminal emulator. And I do a lot of &lt;a href=&quot;https://scala-lang.org/&quot;&gt;Scala&lt;/a&gt; programming, spending a lot of time in &lt;a href=&quot;https://www.scala-sbt.org/&quot;&gt;sbt&lt;/a&gt;, its build tool, for compiling at testing the project. As IDEs I use &lt;a href=&quot;https://www.jetbrains.com/idea/&quot;&gt;IntelliJ IDEA&lt;/a&gt; or &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VS Code&lt;/a&gt; + &lt;a href=&quot;https://scalameta.org/metals/&quot;&gt;Metals&lt;/a&gt; interchangeably.&lt;/p&gt;

&lt;p&gt;iTerm can be configured to open files in your editor or IDE of choice via its &lt;a href=&quot;https://iterm2.com/documentation-preferences-profiles-advanced.html&quot;&gt;Semantic History&lt;/a&gt; feature. My difficulty is that I want to use two IDEs, not just one. IntelliJ IDEA is very heavy, and I want files opened in it only when it’s running. Another problem is that IntelliJ requires a problematic command parameter if you want to specify the line number. So here’s how to workaround that …&lt;/p&gt;

&lt;p&gt;Create a file in &lt;code&gt;~/bin/iterm-goto&lt;/code&gt; and copy/paste this script:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/usr/bin/env bash

GOTO_FILE=&quot;$1&quot;
GOTO_LINE=&quot;$2&quot;
GOTO_CHAR=&quot;$3&quot;

if ! [ -f &quot;$GOTO_FILE&quot; ]; then
    echo &quot;ERROR: file path missing or invalid!&quot; &gt;&amp;2
    exit 1
fi

pgrep -x &quot;idea&quot; &gt; /dev/null
IDEA_RUNNING=$?

if [[ &quot;$GOTO_FILE&quot; =~ ^.*\.(scala|sbt)$ ]] &amp;&amp; [ $IDEA_RUNNING -eq 0 ]; then
    EDITOR_PATH=&quot;$(which idea)&quot;
    if [ -z &quot;$IDEA_PATH&quot; ]; then
        EDITOR_PATH=&quot;/usr/local/bin/idea&quot;
    fi

    if ! [ -z &quot;$GOTO_LINE&quot; ]; then
        exec &quot;$EDITOR_PATH&quot; --line &quot;$GOTO_LINE&quot; &quot;$GOTO_FILE&quot;
    else
        exec &quot;$EDITOR_PATH&quot; &quot;$GOTO_FILE&quot;
    fi
else
    EDITOR_PATH=&quot;$(which code)&quot;
    if [ -z &quot;$EDITOR_PATH&quot; ]; then
        EDITOR_PATH=&quot;/usr/local/bin/code&quot;
    fi

    if ! [ -z &quot;$GOTO_CHAR&quot; ]; then
        exec &quot;$EDITOR_PATH&quot; --goto &quot;$GOTO_FILE:$GOTO_LINE:$GOTO_CHAR&quot;
    elif ! [ -z &quot;$GOTO_LINE&quot; ]; then
        exec &quot;$EDITOR_PATH&quot; --goto &quot;$GOTO_FILE:$GOTO_LINE&quot;
    else
        exec &quot;$EDITOR_PATH&quot; &quot;$GOTO_FILE&quot;
    fi
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Make sure to make it executable:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;chmod +x ~/bin/iterm-goto
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then configure iTerm by:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open its settings (&lt;code&gt;Cmd+,&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Go into &lt;code&gt;Profiles &gt; Advanced &gt; Semantic History&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;Select &lt;code&gt;Run command...&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;Copy/paste: &lt;code&gt;$HOME/bin/iterm-goto \1 \2&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It should look like this:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/iterm-semantic-history.png&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;1075&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    Picture showing iTerm&apos;s Semantic History setting.
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Enjoy~&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/07/18/iterm-open-file-cmd-click-ide-semantic-history/?pk_campaign=rss&quot;&gt;Combining the terminal (iTerm) with the IDE&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 18 Jul 2021 12:23:50 +0000</pubDate>
  <link>https://alexn.org/blog/2021/07/18/iterm-open-file-cmd-click-ide-semantic-history/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2021/07/18/iterm-open-file-cmd-click-ide-semantic-history/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>macOS</category>
  <category>Scala</category>
  </item>


<item>
  <title>Tolerance</title>
  <description>I just refactored a piece of code. I deleted 6 source code files, and rebuilt the functionality with a bunch of dirty OOP classes shoved in a single file 😱</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  I just refactored a piece of code. I deleted 6 source code files, and rebuilt the functionality with a bunch of dirty OOP classes shoved in a single file 😱
&lt;/p&gt;

&lt;p&gt;I used OOP for simplification, and in the process I got rid of type parameters, type classes, and implicit parameters. Plain-old OOP design saved the day, i.e. shove those side effects behind an interface, and pass those objects around, blissfully unaware as to what they do (launching rockets A-OK). &lt;em&gt;It was glorious!&lt;/em&gt; I can’t remember the last time it felt this good.&lt;/p&gt;

&lt;p&gt;Then it dawned on me that I wrote that code to begin with. This piece already underwent a major refactoring, having introduced extra complexity, without catching the subtleties, or smelling the stench of my own doing. What’s going on?&lt;/p&gt;

&lt;p&gt;I started blaming the COVID-19 pandemic, it’s been a year since I’ve been lethargic (aka mild to moderate depression), missing the creative energy that I remember since before the world went mad. But then I started giving myself some credit, because the truth is … as I grow old, I tolerate people more, while tolerating BS in programming less.&lt;/p&gt;

&lt;p&gt;Here’s some science&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/tolerance.png&quot; alt=&quot;&quot; class=&quot;transparency-fix&quot; width=&quot;1400&quot; height=&quot;700&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;The normal distribution of BS tolerance, it&apos;s all downhill after 30, yikes!&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This is another way of saying that you should never forget &lt;em&gt;YAGNI&lt;/em&gt;&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, &lt;em&gt;KISS&lt;/em&gt;&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, the &lt;em&gt;Principle of Least Surprise&lt;/em&gt;&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, or whatever kids call it these days. Just because you can, doesn’t mean you should, with great power comes great responsibility, learn from my mistakes, etc, etc. Most importantly, sometimes &lt;em&gt;DRY&lt;/em&gt;&lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; is a bad philosophy, monomorphic code is sometimes the best code, copy/paste that shit.&lt;/p&gt;

&lt;hr&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Babies have no tolerance obviously, when they are hungry or sleepy they won’t take no for an answer. Babies eventually get suckered into accepting life’s compromises. When looking at what helps us fulfil our potential, the ability to eat shit is an obvious confounding factor. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it&quot;&gt;You Ain’t Gonna Need It&lt;/a&gt; is what agile developers crave for. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/KISS_principle&quot;&gt;Keep It Simple Stupid&lt;/a&gt; was a hip phrase back in my Ruby days, but searching “KISS Ruby” on Google yielded some strange results, so unfortunately I couldn’t get some of that groove back. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;OOP and FP developers actually understand different things by the &lt;a href=&quot;https://en.wikipedia.org/wiki/Rule_of_least_power&quot;&gt;rule of least power&lt;/a&gt; 🤷‍♂️ &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Don%27t_repeat_yourself&quot;&gt;Don’t Repeat Yourself&lt;/a&gt; is not the mantra of Go developers. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/03/30/tolerance/?pk_campaign=rss&quot;&gt;Tolerance&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 30 Mar 2021 20:12:35 +0000</pubDate>
  <link>https://alexn.org/blog/2021/03/30/tolerance/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2021/03/30/tolerance/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>OOP</category>
  <category>Personal</category>
  <category>Programming Rant</category>
  </item>


<item>
  <title>Atom/RSS Feeds are the Best Way to Consume the Web</title>
  <description>I stay connected to websites I care about via an RSS/Atom feed reader. It’s better than social media for finding out what’s new because it’s clutter-free. By following RSS/Atom feeds, I discover wonderful gems that otherwise would be lost in the noise.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2021/03/29/atom-rss-feeds-are-the-best-way-to-consume-the-web/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/highway.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1400&quot; height=&quot;935&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I stay connected to websites I care about via an RSS/Atom feed reader. It’s better than social media for finding out what’s new because it’s clutter-free. By following RSS/Atom feeds, I discover wonderful gems that otherwise would be lost in the noise.
&lt;/p&gt;

&lt;h2 id=&quot;rss-is-not-dead&quot;&gt;RSS is not dead&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Web_syndication&quot;&gt;Web syndication&lt;/a&gt; is alive and kicking. A vast majority of websites and online services expose RSS/Atom feeds, and you can find workarounds for those that don’t.&lt;/p&gt;

&lt;p&gt;When I like individuals on the web, I tend to like pretty much everything that they write. Even when I connect to a fire hose, the RSS/Atom feeds are all content. Even when following pundits, you get long-form writing on websites instead of shallow opinions that must fit in 280 chars. Websites or even YouTube channels, compared with social media, are outlets in which people usually put more thought when expressing themselves.&lt;/p&gt;

&lt;p&gt;My RSS/Atom feed reader is the best way to follow:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Hacker News, via &lt;a href=&quot;http://hnapp.com/&quot;&gt;hnapp.com&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;Twitter accounts that are important, via a self-hosted &lt;a href=&quot;https://github.com/RSS-Bridge/rss-bridge&quot;&gt;rss-bridge&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;Library releases, via &lt;a href=&quot;https://docs.github.com/en/rest/reference/activity&quot;&gt;GitHub’s atom feeds&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;Podcasts&lt;/li&gt;
  &lt;li&gt;Reddit (a fire hose, but I can filter by subjects I care about)&lt;/li&gt;
  &lt;li&gt;Programming communities (Scala, Haskell, etc)&lt;/li&gt;
  &lt;li&gt;YouTube&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;news-aggregators-rss-readers&quot;&gt;News aggregators (RSS readers)&lt;/h2&gt;

&lt;p&gt;Web hosted:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://newsblur.com&quot;&gt;Newsblur&lt;/a&gt; (managed, the best IMO)&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://freshrss.org/&quot;&gt;FreshRSS&lt;/a&gt; (easy to self-host)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Native:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://reederapp.com/&quot;&gt;Reeder&lt;/a&gt; (macOS, iOS)&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.seazon.feedme&amp;hl=en_US&amp;gl=US&quot;&gt;FeedMe&lt;/a&gt; (Android)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;for-your-blog&quot;&gt;For your blog&lt;/h2&gt;

&lt;p&gt;Own your audience!&lt;/p&gt;

&lt;p&gt;If you’re cool enough to have your own blog, maybe you’ve built your website with a static website generator, such as Jekyll, but please don’t forget to expose an RSS/Atom feed. Those of us using a news aggregator will thank you ❤️ And if you expose an RSS feed, you can then build an automated newsletter from it too 😉&lt;/p&gt;

&lt;p&gt;Here’s some cool stuff to get you going:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/jekyll/jekyll-feed&quot;&gt;jekyll-feed&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mailchimp.com/features/rss-to-email/&quot;&gt;Mailchimp RSS to Email&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy 😎&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/03/29/atom-rss-feeds-are-the-best-way-to-consume-the-web/?pk_campaign=rss&quot;&gt;Atom/RSS Feeds are the Best Way to Consume the Web&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 29 Mar 2021 19:58:29 +0000</pubDate>
  <link>https://alexn.org/blog/2021/03/29/atom-rss-feeds-are-the-best-way-to-consume-the-web/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2021/03/29/atom-rss-feeds-are-the-best-way-to-consume-the-web/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Blogging</category>
  <category>Jekyll</category>
  <category>Web</category>
  </item>


<item>
  <title>ING Scala Meetup on Scala 3 (live coding session)</title>
  <description>Online meetup on Scala 3’s newly introduced types and features for encoding type classes.</description>
  <content:encoded>&lt;p&gt;We’ve had an &lt;a href=&quot;https://www.meetup.com/Tech-Meetups-ING/&quot;&gt;ING Scala Meetup&lt;/a&gt; last night.&lt;/p&gt;

&lt;p&gt;In the first half of the meetup, Ayush Mittal did a live presentation on the newly introduced types of Scala 3 — enums, intersection types, untagged union types.&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=qqqfImDtduE&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/ing-meetup-working-with-dotty-2.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=qqqfImDtduE&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      The types of Scala 3 — Ayush Mittal
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;In the second half of the meetup, I did a live coding session on implementing Type Classes in Scala 3, and what this major version of the compiler brings new to the table for helping us to encode type classes — presentation starts from beginner level but then progresses to advanced 😅&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=qqqfImDtduE&amp;autoplay=1&amp;t=4963&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/ing-meetup-working-with-dotty-1.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=qqqfImDtduE&amp;autoplay=1&amp;t=4963&quot; target=&quot;_blank&quot;&gt;
      Type Classes in Scala 3 — Alexandru Nedelcu
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/02/26/type-classes-in-scala-3-live-coding-session/?pk_campaign=rss&quot;&gt;ING Scala Meetup on Scala 3 (live coding session)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 26 Feb 2021 06:30:07 +0000</pubDate>
  <link>https://alexn.org/blog/2021/02/26/type-classes-in-scala-3-live-coding-session/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2021/02/26/type-classes-in-scala-3-live-coding-session/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Scala 3</category>
  <category>Video</category>
  </item>


<item>
  <title>Implementing a CountDownLatch (async and dirty)</title>
  <description>Yo dawg, I heard you liked concurrency primitives. Let’s implement our own asynchronous, dirty CountDownLatch.</description>
  <content:encoded>&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=R6pl91IRVaI&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/countdownlatch-async-dirty.png?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=R6pl91IRVaI&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Yo dawg, I heard you liked concurrency primitives. Let’s implement our own asynchronous, dirty &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html&quot;&gt;CountDownLatch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just to be clear, what we are implementing here is probably not production ready (please do some testing first, as I didn’t 😅). Also this is not functional programming, and it’s not using &lt;a href=&quot;https://monix.io&quot;&gt;Monix&lt;/a&gt; or &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats-Effect&lt;/a&gt;, or any other libraries that might have helped. This is implemented using just the standard library.&lt;/p&gt;

&lt;p&gt;Also, you might want the classic &lt;code&gt;java.util.concurrent.CountDownLatch&lt;/code&gt;, which is pretty awesome, and it might be exactly what you need, although this one is useful too.&lt;/p&gt;

&lt;p&gt;Why implement one? Because we can 💪&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Watch the &lt;a href=&quot;https://www.youtube.com/watch?v=R6pl91IRVaI&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;YouTube video&lt;/a&gt; for full explanations&lt;/li&gt;
  &lt;li&gt;Checkout the following code for digesting it at your own pace&lt;/li&gt;
  &lt;li&gt;See the usage examples at the end&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;the-code&quot;&gt;The Code&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import java.util.concurrent.{Executors, RejectedExecutionException}
import java.util.concurrent.atomic.AtomicReference
import scala.annotation.tailrec
import scala.concurrent.duration.{Duration, FiniteDuration}
import scala.concurrent.{ExecutionContext, Future, Promise, TimeoutException}

final class AsyncCountDownLatch(count: Int)(implicit ec: ExecutionContext)
  extends AutoCloseable {

  // Shared mutable state, managed by my favorite
  // synchronization primitive
  private[this] val state = new AtomicReference(State(count, Set.empty))
  private final case class State(
    count: Int,
    tasks: Set[Promise[Unit]]
  )

  /**
    * INTERNAL — scheduler for managing timeouts, must be destroyed
    * internally too. Note that this isn&apos;t the only possible design,
    * we could of course take this as a parameter in the class&apos;s
    * constructor, or use a globally shared one 🤷‍
    *
    * One cool alternative is to use Monix&apos;s `Scheduler` instead of
    * `ExecutionContext` (`monix.execution.Scheduler`).
    */
  private[this] val scheduler =
    Executors.newSingleThreadScheduledExecutor((r: Runnable) =&gt; {
      val th = new Thread(r)
      th.setDaemon(true)
      th.setName(s&quot;countdownlatch-${hashCode()}&quot;)
      th
    })

  /**
    * INTERNAL — Given a `Promise`, install a timeout for it.
    */
  private def installTimeout(p: Promise[Unit], timeout: FiniteDuration): Unit = {
    // Removing the promise from our internal `state` is necessary to avoid leaks.
    @tailrec def removePromise(): Unit =
      state.get() match {
        case current @ State(_, tasks) =&gt;
          val update = current.copy(tasks = tasks - p)
          if (!state.compareAndSet(current, update))
            removePromise()
        case null =&gt;
          () // countDown reached zero
      }
    // Keeping this as a value in order to avoid duplicate work
    val ex = new TimeoutException(
      s&quot;AsyncCountDownLatch.await($timeout)&quot;
    )
    val timeoutTask: Runnable = () =&gt; {
      // Timeout won, get rid of promise from our state
      removePromise()
      p.tryFailure(ex)
    }
    try {
      // Finally, installing our timeout, w00t!
      val cancelToken = scheduler.schedule(
        timeoutTask, 
        timeout.length, 
        timeout.unit
      )
      // Canceling our timeout task, if primary completes first
      p.future.onComplete { r =&gt;
        // Avoiding duplicate work
        if (r.fold(_ != ex, _ =&gt; true))
          cancelToken.cancel(false)
      }
    } catch {
      case _: RejectedExecutionException =&gt;
        // This exception can happen due to a race condition:
        // When countDown() reaches zero, the scheduler is being
        // shut down, however while that happens we may be in
        // the process of installing a timeout — but this is no
        // longer necessary, since the promise will be completed;
        // NOTE — for extra-safety, we might want to check the
        // promise&apos;s state, to ensure that it is complete, and
        // a happens-before relationship probably exists (TBD)
        ()
    }
  }

  override def close(): Unit = {
    state.lazySet(null) // GC purposes
    scheduler.shutdown()
  }

  /**
    * Decrements the count of the latch, releasing all waiting
    * consumers if the count reaches zero.
    *
    * If the current count is already zero, then nothing happens.
    */
  @tailrec def countDown(): Unit =
    state.get() match {
      case current @ State(count, tasks) if count &gt; 0 =&gt;
        val update = State(count - 1, tasks)
        if (!state.compareAndSet(current, update))
          countDown() // retry
        else if (update.count == 0) {
          // Deferring execution to another thread, as it might 
          // be expensive (TBD if this is a good idea or not)
          ec.execute(() =&gt; {
            for (r &lt;- tasks) r.trySuccess(())
            // Releasing resources
            close()
          })
        }
      case _ =&gt;
        ()
    }

  /**
    * Causes the consumer to wait until the latch has counted down 
    * to zero, or the specified waiting time elapses.
    *
    * If the timeout gets triggered, then the returned `Future`
    * will complete with a `TimeoutException`.
    */
  @tailrec def await(timeout: Duration): Future[Unit] =
    state.get() match {
      case current @ State(count, tasks) if count &gt; 0 =&gt;
        val p = Promise[Unit]()
        val update = State(count, tasks + p)
        timeout match {
          case d: FiniteDuration =&gt; installTimeout(p, d)
          case _ =&gt; ()
        }
        if (!state.compareAndSet(current, update))
          await(timeout) // retry
        else
          p.future
      case _ =&gt;
        Future.unit
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Usage sample of the classic &lt;code&gt;java.util.concurrent.CountDownLatch&lt;/code&gt; that we’re trying to mimic:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import java.util.concurrent.CountDownLatch
import scala.concurrent.ExecutionContext.Implicits.global

val threadCount = 4
val iterations = 10000
var results = Map.empty[Int, Int]

for (_ &lt;- 0 until iterations) {
  val consumersStarted = new CountDownLatch(threadCount)
  val mainThreadProceed = new CountDownLatch(1)
  val consumersFinished = new CountDownLatch(threadCount)
  var sharedState = 0

  for (_ &lt;- 0 until threadCount)
    global.execute(() =&gt; {
      consumersStarted.countDown()
      mainThreadProceed.await()
      sharedState += 1
      consumersFinished.countDown()
    })

  consumersStarted.await()
  mainThreadProceed.countDown()
  consumersFinished.await()

  results = results.updated(sharedState, results.getOrElse(sharedState, 0) + 1)
}

println(&quot;Done ... &quot;)
println(results)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Usage sample of our &lt;code&gt;AsyncCountDownLatch&lt;/code&gt;, again, testing faulty concurrent update:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Await, Future, TimeoutException}
import scala.concurrent.duration._

val threadCount = 4
val iterations = 100000
var results = Map.empty[Int, Int]

for (_ &lt;- 0 until iterations) {
  val consumersStarted = new AsyncCountDownLatch(threadCount)
  val mainThreadProceed = new AsyncCountDownLatch(1)
  val consumersFinished = new AsyncCountDownLatch(threadCount)
  var sharedState = 0

  for (_ &lt;- 0 until threadCount) {
    for {
      _ &lt;- Future.unit
      _ = consumersStarted.countDown()
      _ &lt;- mainThreadProceed.await(Duration.Inf)
    } yield {
      sharedState += 1
      consumersFinished.countDown()
    }
  }

  val await = for {
    _ &lt;- consumersStarted.await(Duration.Inf)
    _ = mainThreadProceed.countDown()
    _ &lt;- consumersFinished.await(1.millis)
  } yield {
    results = results.updated(sharedState, results.getOrElse(sharedState, 0) + 1)
  }
  Await.result(await, Duration.Inf)
}

println(&quot;Done ... &quot;)
println(results)
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/02/22/countdownlatch-async-dirty/?pk_campaign=rss&quot;&gt;Implementing a CountDownLatch (async and dirty)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 22 Feb 2021 13:39:35 +0000</pubDate>
  <link>https://alexn.org/blog/2021/02/22/countdownlatch-async-dirty/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2021/02/22/countdownlatch-async-dirty/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Concurrency</category>
  <category>JVM</category>
  <category>Multithreading</category>
  <category>Scala</category>
  <category>Video</category>
  </item>


<item>
  <title>Matomo (Analytics) Hosting via Docker</title>
  <description>Docker setup for self-hosting Matomo, an open-source alternative to Google Analytics.</description>
  <content:encoded>&lt;p&gt;For self-hosting &lt;a href=&quot;https://matomo.org/&quot;&gt;Matomo&lt;/a&gt;, a FOSS alternative to Google Analytics — via &lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;docker-compose&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;version: &apos;3.3&apos;

services:
  db:
    container_name: mariadb
    image: mariadb:10.5
    ports:
      - &quot;3306:3306&quot;
    labels:
      - &quot;com.centurylinklabs.watchtower.enable=true&quot;
    command: --max-allowed-packet=64MB
    restart: unless-stopped
    volumes:
      - db:/var/lib/mysql
    env_file:
      - ./envs/mysql.env
    networks:
      - main
  
  redis:
    container_name: redis
    image: redis:6-alpine
    restart: unless-stopped
    command: redis-server --appendonly yes
    labels:
      - &quot;com.centurylinklabs.watchtower.enable=true&quot;
    volumes:
      - redis:/data
    networks:
      - main
    sysctls: # https://github.com/docker-library/redis/issues/191#issuecomment-528693994
      - net.core.somaxconn=511
        
  matomo:
    container_name: matomo
    image: matomo:4-fpm-alpine
    links:
      - db
      - redis
    restart: unless-stopped
    expose: 
      - &quot;9000&quot;
    ports:
      - &quot;9000:9000&quot;
    labels:
      - &quot;com.centurylinklabs.watchtower.enable=true&quot;
    volumes:
      - /var/www/matomo:/var/www/html
    networks:
      - main
    environment:
      - MATOMO_DATABASE_HOST=db
    env_file:
      - ./envs/mysql.env
      - ./envs/matomo.env
    user: &quot;$WWW_UID:$WWW_GID&quot;
    
networks:
  main:
    external:
      name: main

volumes:
  db:
  redis:
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/02/22/matomo-hosting-via-docker/?pk_campaign=rss&quot;&gt;Matomo (Analytics) Hosting via Docker&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 22 Feb 2021 00:00:00 +0000</pubDate>
  <dc:modified>Sun, 29 Sep 2024 09:21:59 +0000</dc:modified>
  <atom:modified>Sun, 29 Sep 2024 09:21:59 +0000</atom:modified>
  <link>https://alexn.org/blog/2021/02/22/matomo-hosting-via-docker/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2021/02/22/matomo-hosting-via-docker/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Blogging</category>
  <category>Self Hosting</category>
  <category>Web</category>
  </item>


<item>
  <title>Scala&#39;s List has a Secret</title>
  <description>OOP couples the data with the methods operating on it, and this is considered bad in FP circles. But is it?</description>
  <content:encoded>&lt;p&gt;OOP couples the “data” with the methods operating on it, and that’s considered bad in FP circles, because supposedly data outlives the functions operating on it. Also in static FP circles, dumb data structures are reusable, so it’s a good idea to make them generic, and add restrictions on the functions themselves.&lt;/p&gt;

&lt;p&gt;Few data structures could be simpler than an immutable &lt;code&gt;List&lt;/code&gt; definition, right? At least as far as recursive data structures go 🙂 For the standard &lt;code&gt;List&lt;/code&gt; you’d expect the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed abstract class List[+A]

final case class :: [+A](head: A, tail: List[A])
  extends List[A]

case object Nil extends List[Nothing]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh boy, I’ve got news for you — this is the actual definition from Scala’s standard library:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed abstract class List[+A]

final case class :: [+A](
  head: A, 
  // mutable var 😱
  private[scala] var next: List[A @uncheckedVariance]) 
  extends List[A] {
 
  // 😱 memory barrier
  releaseFence()
}

case object Nil extends List[Nothing]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yikes, that private &lt;code&gt;next&lt;/code&gt; value is a &lt;code&gt;var&lt;/code&gt;. They added it as a &lt;code&gt;var&lt;/code&gt; such that &lt;a href=&quot;https://www.scala-lang.org/api/current/scala/collection/mutable/ListBuffer.html&quot;&gt;ListBuffer&lt;/a&gt; can build a list more efficiently, because an immutable &lt;code&gt;List&lt;/code&gt; is in essence a &lt;a href=&quot;https://en.wikipedia.org/wiki/Stack_(abstract_data_type)&quot;&gt;Stack&lt;/a&gt;, so to build a new list from an existing one, you’d need to do an &lt;code&gt;O(n)&lt;/code&gt; reversal at the end.&lt;/p&gt;

&lt;p&gt;With the pure definition, we’d build &lt;code&gt;List&lt;/code&gt; values like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def map[A, B](self: List[A])(f: A =&gt; B): List[B] = {
  var buffer = List.empty[B]
  for (elem &lt;- self) { buffer = f(elem) :: buffer  }
  // Extra O(n) tax if that list would be pure, no way around it
  // (legend has it that this is a computer science issue related to stacks)
  buffer.reverse
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But with &lt;code&gt;ListBuffer&lt;/code&gt;, due to making use of that &lt;code&gt;var&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def map[A, B](self: List[A])(f: A =&gt; B): List[B] = {
  val buffer = ListBuffer.empty[B]
  for (elem &lt;- self) { buffer += f(elem)  }
  // O(1), no inefficiency
  buffer.toList
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Contrary to popular opinion, this means &lt;code&gt;List&lt;/code&gt; does not benefit from &lt;code&gt;final&lt;/code&gt; (&lt;code&gt;val&lt;/code&gt; in Scala) visibility guarantees by the &lt;a href=&quot;https://en.wikipedia.org/wiki/Java_memory_model&quot;&gt;Java Memory Model&lt;/a&gt;. So it might have visibility issues in a multi-threaded context (e.g. you might end up with a &lt;code&gt;tail&lt;/code&gt; being &lt;code&gt;null&lt;/code&gt; when it shouldn’t be). Which is probably why we see this in both the class constructor and in &lt;code&gt;ListBuffer#toList&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;override def toList: List[A] = {
  aliased = nonEmpty
  // We&apos;ve accumulated a number of mutations to `List.tail` by this stage.
  // Make sure they are visible to threads that the client of this ListBuffer might be about
  // to share this List with.
  releaseFence()
  first
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yikes, they are adding manual &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_barrier&quot;&gt;memory barriers&lt;/a&gt; everywhere 😲 I guess it beats an added &lt;code&gt;O(n)&lt;/code&gt; penalty when building new lists. But this goes to show the necessity of coupling data structures with the methods operating on them.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;FP developers don’t care about resources, because of the expectation that resources should be handled by the runtime, but sometimes that isn’t possible or optimal — even dumb data structures are resources and sometimes need special resource management, for efficiency reasons. In which case coupling the data with the methods operating on it is healthy 😉&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  I don&apos;t like manual memory barriers BTW. They are expensive and a design based on proper acquisition and release (reads and writes in volatiles) would be better, as it lets the JVM do its magic. Don&apos;t copy their design here without knowing what you&apos;re doing.
&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/02/12/scala-list-secret/?pk_campaign=rss&quot;&gt;Scala&apos;s List has a Secret&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 12 Feb 2021 11:32:33 +0000</pubDate>
  <link>https://alexn.org/blog/2021/02/12/scala-list-secret/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2021/02/12/scala-list-secret/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Multithreading</category>
  <category>Scala</category>
  </item>


<item>
  <title>Tail Recursive Functions (in Scala)</title>
  <description>Turning imperative algorithms to tail-recursive functions isn’t necessarily obvious. In this article (and video) I’m showing you the trick you need, and in doing so, we’ll discover the Zen of Functional Programming.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      
&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=Ua1iMD4icLU&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/tail-recursive-functions.png?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=Ua1iMD4icLU&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Turning imperative algorithms to tail-recursive functions isn’t necessarily obvious. In this article (and video) I’m showing you the trick you need, and in doing so, we’ll discover the Zen of Functional Programming.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  Choose between watching the video on YouTube (linked above), or reading the article (below), or both.
&lt;/p&gt;

&lt;h2 id=&quot;the-trick&quot;&gt;The Trick&lt;/h2&gt;

&lt;p&gt;Let’s start with a simple function that calculates the length of a list:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def len(l: List[_]): Int =
  l match {
    case Nil =&gt; 0
    case _ :: tail =&gt; len(tail) + 1
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’s a recursive function with a definition that is mathematically correct. However, if we try to test it, this will fail with a &lt;code&gt;StackOverflowError&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;len(List.fill(100000)(1))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The problem is that the input list is too big. And because the VM still has work to do after that recursive call, needing to do a &lt;code&gt;+ 1&lt;/code&gt;, the call isn’t in “tail position”, so the &lt;a href=&quot;https://en.wikipedia.org/wiki/Call_stack&quot; target=&quot;_blank&quot;&gt;call-stack&lt;/a&gt; must be used. A &lt;code&gt;StackOverflowError&lt;/code&gt; is a memory error, and in this case it’s a correctness issue, because the function will fail on reasonable input.&lt;/p&gt;

&lt;p&gt;First let’s describe it as a dirty &lt;code&gt;while&lt;/code&gt; loop instead:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def len(l: List[_]): Int = {
  var count = 0
  var cursor = l

  while (cursor != Nil) {
    count += 1
    cursor = cursor.tail
  }
  count
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;THE TRICK for turning such functions into tail-recursions is to turn those variables, holding state, into &lt;em&gt;function parameters&lt;/em&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def len(l: List[_]): Int = {
  // Using an inner function to encapsulate this implementation
  @tailrec
  def loop(cursor: List[_], count: Int): Int =
    cursor match {
      // Our end condition, copied after that while
      case Nil =&gt; count
      case _ :: tail =&gt;
        // Copying the same logic from that while statement
        loop(cursor = tail, count = count + 1)
    }
  // Go, go, go
  loop(l, 0)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this version is fine. Note the use of the &lt;code&gt;@tailrec&lt;/code&gt; annotation — all this annotation does is to make the compiler throw an error in case the function is not actually tail-recursive. That’s because that call is error-prone, and it needs repeating, this is an issue of correctness.&lt;/p&gt;

&lt;p&gt;Let’s do a more complex example to really internalize this. Let’s calculate the N-th number in the Fibonacci sequence — here’s the memory unsafe recursive version:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def fib(n: Int): BigInt =
  if (n &lt;= 0) 0
  else if (n == 1) 1
  else fib(n - 1) + fib(n - 2)

fib(0) // 0
fib(1) // 1
fib(2) // 1
fib(3) // 2
fib(4) // 3
fib(5) // 5

fib(100000) // StackOverflowError (also, really slow)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First turn this into a dirty &lt;code&gt;while&lt;/code&gt; loop:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def fib(n: Int): BigInt = {
  // Kids, don&apos;t do this at home 😅
  if (n &lt;= 0) return 0
  // Going from 0 to n, instead of vice-versa
  var a: BigInt = 0 // instead of fib(n - 2)
  var b: BigInt = 1 // instead of fib(n - 1)
  var i = n

  while (i &gt; 1) {
    val tmp = a
    a = b
    b = tmp + b
    i -= 1
  }
  b
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then turn its 3 variables into function parameters:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def fib(n: Int): BigInt = {
  @tailrec
  def loop(a: BigInt, b: BigInt, i: Int): BigInt =
    // first condition
    if (i &lt;= 0) 0
    // end of while loop
    else if (i == 1) b
    // logic inside while loop statement
    else loop(a = b, b = a + b, i = i - 1)

  loop(0, 1, n)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;actual-recursion&quot;&gt;(Actual) Recursion&lt;/h2&gt;

&lt;p&gt;Tail-recursions are just loops. But some algorithms are actually &lt;em&gt;recursive&lt;/em&gt;, and can’t be described via a &lt;code&gt;while&lt;/code&gt; loop that uses constant memory. What makes an algorithm actually recursive is &lt;em&gt;usage of a stack&lt;/em&gt;. In imperative programming, for low-level implementations, that’s how you can tell if recursion is required … does it use a manually managed stack or not?&lt;/p&gt;

&lt;p&gt;But even in such cases we can use a &lt;code&gt;while&lt;/code&gt; loop, or a &lt;code&gt;@tailrec&lt;/code&gt; function. Doing so has some advantages. Let’s start with a &lt;code&gt;Tree&lt;/code&gt; data-structure:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed trait Tree[+A]

case class Node[+A](value: A, left: Tree[A], right: Tree[A])
  extends Tree[A]
case object Empty
  extends Tree[Nothing]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Defining a fold, which we could use to sum-up all values for example, will be challenging:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def foldTree[A, R](tree: Tree[A], seed: R)(f: (R, A) =&gt; R): R =
  tree match {
    case Empty =&gt; seed
    case Node(value, left, right) =&gt;
      // Recursive call for the left child
      val leftR = foldTree(left, f(seed, value))(f)
      // Recursive call for the right child
      foldTree(right, leftR)(f)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the simple version. And it should be clear that the size of the call-stack will be directly proportional to &lt;em&gt;the height of the tree&lt;/em&gt;. And turning it into a &lt;code&gt;@tailrec&lt;/code&gt; version means we need to &lt;em&gt;manually manage a stack&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def foldTree[A, R](tree: Tree[A], seed: R)(f: (R, A) =&gt; R): R = {
  @tailrec def loop(stack: List[Tree[A]], state: R): R =
    stack match {
      // End condition, nothing left to do
      case Nil =&gt; state
      // Ignore empty elements
      case Empty :: tail =&gt; loop(tail, state)
      // Step in our loop
      case Node(value, left, right) :: tail =&gt;
        // Adds left and right nodes to stack, evolves the state
        loop(left :: right :: tail, f(state, value))
    }
  // Go, go, go!
  loop(List(tree), seed)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  If you want to internalize this notion — recursion == usage of a stack — a great exercise is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Backtracking&quot;&gt;backtracking algorithm&lt;/a&gt;. Implement it with recursive functions, or with dirty loops and a manually managed stack, and compare. The plot thickens for backtracking solutions using 2 stacks 🙂
&lt;/p&gt;

&lt;p&gt;Does this manually managed stack buy us anything?&lt;/p&gt;

&lt;p&gt;Well yes, if you need such recursive algorithms, such a stack can take up your whole heap memory, which means it can handle a bigger input. But note that with the right input, your process can still blow up, this time with an out-of-memory error (OOM).&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  NOTE — in real life, shining examples of algorithms using manually managed stacks are &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats-Effect’s IO&lt;/a&gt; and &lt;a href=&quot;https://monix.io/&quot;&gt;Monix’s Task&lt;/a&gt;, since they literally replace the JVM’s call-stack 😄
&lt;/p&gt;

&lt;h2 id=&quot;zen-of-functional-programming&quot;&gt;Zen of Functional Programming?&lt;/h2&gt;

&lt;p&gt;In FP, you turn variables into (immutable) function parameters. And state gets evolved via function calls 💡&lt;/p&gt;

&lt;p&gt;That’s it, that’s all there is to FP (plus the design patterns, and the pain of dealing with I/O 🙂).&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/01/26/tail-recursive-functions-in-scala/?pk_campaign=rss&quot;&gt;Tail Recursive Functions (in Scala)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 26 Jan 2021 19:49:35 +0000</pubDate>
  <link>https://alexn.org/blog/2021/01/26/tail-recursive-functions-in-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2021/01/26/tail-recursive-functions-in-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Algorithms</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Video</category>
  </item>


<item>
  <title>Snippet: Tagless Final vs OOP</title>
  <description>Snippet of code discussing Tagless Final vs OOP-style dependency injection.</description>
  <content:encoded>&lt;p&gt;These may as well be interview questions for Scala developers:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Which signature do you prefer?&lt;/li&gt;
  &lt;li&gt;Just looking at the signature, what can potentially be wrong with the “tagless final” version?&lt;/li&gt;
  &lt;li&gt;Also discuss the 2 type-class approaches, what are the potential design problems there?&lt;/li&gt;
&lt;/ol&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// -----------------
// Tagless final
def registerUser[F[_]: UserDB: EmailService: Monad](user: User): F[Unit]

// -----------------
// ReaderT (Kleisli) &amp; OOP
def registerUser[F[_]: Monad](
  user: User): Kleisli[F, (UserDB[F], EmailService[F]), Unit]

// -----------------
// Plain function parameters &amp; OOP
def registerUser[F[_]: Monad](
  db: UserDB[F], 
  es: EmailService[F],
  user: User): F[Unit]

// -----------------
// OOP class
final class RegistrationService[F[_]: Monad](
  db: UserDB[F], 
  es: EmailService[F]) {

  def registerUser(user: User): F[Unit]
}

// -----------------
// OOP interface
trait RegistrationService[F[_]] {
  def registerUser(user: User): F[Unit]
}

object RegistrationService {
  def apply[F[_]: Monad](
    db: UserDB[F], 
    es: EmailService[F]): RegistrationService[F] = ???
}

// -----------------
// Type Class (1) — two type params
trait RegistrationService[F[_], Env] {
  def registerUser(env: Env, user: User): F[Unit]
}

object RegistrationService {
  implicit def instance[F[_]: Monad]
    : RegistrationService[F, (UserDB[F], EmailService[F])] = ???
}

// -----------------
// Type Class (2) — single type param
trait RegistrationService[Env[_[_]]] {
  def registerUser[F[_]: Monad](env: Env[F], user: User): F[Unit]
}

object RegistrationService {
  type Env[F[_]] = (UserDB[F], EmailService[F])
  implicit val instance: RegistrationService[Env] = ???
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/01/20/tagless-final-vs-oop/?pk_campaign=rss&quot;&gt;Snippet: Tagless Final vs OOP&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 20 Jan 2021 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 12:55:01 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 12:55:01 +0000</atom:modified>
  <link>https://alexn.org/blog/2021/01/20/tagless-final-vs-oop/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2021/01/20/tagless-final-vs-oop/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>OOP</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Snippet: Remove blank lines from text</title>
  <description>Just a regular expression.</description>
  <content:encoded>&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;text.replaceAll(&quot;(?m)(^\\s*$\\r?\\n)+&quot;, &quot;&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or via &lt;code&gt;Pattern&lt;/code&gt; objects:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import java.util.regex.Pattern

Pattern
  .compile(&quot;(^\\s*$\\r?\\n)+&quot;, Pattern.MULTILINE)
  .matcher(text)
  .replaceAll(&quot;&quot;)
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2021/01/14/remove-blank-lines/?pk_campaign=rss&quot;&gt;Snippet: Remove blank lines from text&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 14 Jan 2021 00:00:00 +0000</pubDate>
  <dc:modified>Mon, 19 Sep 2022 16:11:17 +0000</dc:modified>
  <atom:modified>Mon, 19 Sep 2022 16:11:17 +0000</atom:modified>
  <link>https://alexn.org/blog/2021/01/14/remove-blank-lines/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2021/01/14/remove-blank-lines/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Java</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Execute shell commands in F#</title>
  <description>Snippet in plain F# with no dependencies. Features a neat shebang.</description>
  <content:encoded>&lt;pre&gt;&lt;code class=&quot;language-fsharp&quot;&gt;#!/usr/bin/env -S dotnet fsi

open System
open System.Diagnostics
open System.Threading.Tasks

type CommandResult =
  { ExitCode: int
    StandardOutput: string
    StandardError: string }

let executeCommand executable args =
  async {
    let! ct = Async.CancellationToken

    let startInfo = ProcessStartInfo()
    startInfo.FileName &lt;- executable
    startInfo.RedirectStandardOutput &lt;- true
    startInfo.RedirectStandardError &lt;- true
    startInfo.UseShellExecute &lt;- false
    startInfo.CreateNoWindow &lt;- true
    for a in args do
      startInfo.ArgumentList.Add(a)

    use p = new Process()
    p.StartInfo &lt;- startInfo
    p.Start() |&gt; ignore

    let outTask =
      Task.WhenAll([|
        p.StandardOutput.ReadToEndAsync(ct);
        p.StandardError.ReadToEndAsync(ct) |])

    do! p.WaitForExitAsync(ct) |&gt; Async.AwaitTask
    let! out = outTask |&gt; Async.AwaitTask

    return
      { ExitCode = p.ExitCode
        StandardOutput = out.[0]
        StandardError = out.[1] }
  }

let executeShellCommand command =
  executeCommand &quot;/usr/bin/env&quot; [ &quot;-S&quot;; &quot;bash&quot;; &quot;-c&quot;; command ]

// Invocation sample
let r = executeShellCommand &quot;ls -alh&quot; |&gt; Async.RunSynchronously

if r.ExitCode = 0 then
  printfn &quot;%s&quot; r.StandardOutput
else
  eprintfn &quot;%s&quot; r.StandardError
  Environment.Exit(r.ExitCode)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you create the file &lt;code&gt;test.fsi&lt;/code&gt; with the code above, under Linux you can make it executable:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;# Make it executable
chmod +x ./test.fsi

# Execute it
./test.fsi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, see: &lt;a href=&quot;https://alexn.org/blog/2022/10/03/execute-shell-commands-in-java-scala-kotlin/&quot;&gt;Execute Shell Commands in Java/Scala/Kotlin&lt;/a&gt;.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/12/06/execute-shell-command-in-fsharp/?pk_campaign=rss&quot;&gt;Execute shell commands in F#&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 06 Dec 2020 00:00:00 +0000</pubDate>
  <dc:modified>Sun, 05 Nov 2023 17:26:44 +0000</dc:modified>
  <atom:modified>Sun, 05 Nov 2023 17:26:44 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/12/06/execute-shell-command-in-fsharp/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/12/06/execute-shell-command-in-fsharp/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Shell</category>
  <category>dotNet</category>
  <category>FSharp</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Using ScalaTest for Effects</title>
  <description>Helpers for integrating with cats.effect.IO.</description>
  <content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.scalatest.org/&quot;&gt;ScalaTest&lt;/a&gt; helpers for testing effects (e.g. &lt;code&gt;cats.effect.IO&lt;/code&gt;, &lt;code&gt;monix.eval.Task&lt;/code&gt;). This is similar to &lt;a href=&quot;https://alexn.org/blog/2020/10/15/generic-ioapp-alternative/&quot;&gt;PureApp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirement:&lt;/strong&gt; &lt;a href=&quot;https://alexn.org/blog/2020/10/12/effect-runtime/&quot;&gt;EffectRuntime&lt;/a&gt; (snippet)&lt;/p&gt;

&lt;p&gt;Usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object Fns {
  def fireMissiles[F[_]: Sync]: F[Int] =
    Sync[F].delay {
      println(&quot;Firing missiles...&quot;)
      Random.nextInt(100) + 1
    }
}

class MyTestSuite extends EffectTestSuite.ForIO {
  testEffect(&quot;fire missiles&quot;) {
    for {
      count &lt;- Fns.fireMissiles
    } yield {
      assert(count &gt; 0)
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Implementation:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect._
import org.scalactic.source
import org.scalatest.compatible.Assertion
import org.scalatest.funsuite.AsyncFunSuiteLike
import org.scalatest.{ BeforeAndAfterAll, Tag }
import scala.concurrent.Promise
import scala.concurrent.duration._

trait EffectTestSuite[F[_]] extends AsyncFunSuiteLike {
  protected def effectTimeout: FiniteDuration = 30.seconds

  protected def testEffect(testName: String, testTags: Tag*)(
    testFun: =&gt; F[Assertion]
  )(implicit F: ConcurrentEffect[F], timer: Timer[F], pos: source.Position): Unit = {
    test(testName, testTags: _*) {
      val task = Concurrent.timeout(testFun, effectTimeout)
      val p = Promise[Assertion]()
      F.runAsync(task)(r =&gt; F.delay { p.complete(r.toTry); () }
      p.future
    }
  }
}

object EffectTestSuite {
  /** For working with `cats.effect.IO`
    */
  trait ForIO extends EffectTestSuite[IO] with BeforeAndAfterAll {
    protected def runtimeFactory: Resource[SyncIO, EffectRuntime[IO]] = {
      // This should be a concrete implementation
      ???
    }

    protected final lazy val (runtimeRef, runtimeCancel) = {
      runtimeFactory
        .allocated
        .unsafeRunSync()
    }

    override protected def beforeAll(): Unit = {
      super.beforeAll()
      // forces initialization
      runtimeRef; ()
    }

    override protected def afterAll(): Unit = {
      super.afterAll()
      runtimeCancel.unsafeRunSync()
    }

    protected implicit lazy val contextShift: EffectRuntime[IO] =
      runtimeRef

    protected implicit lazy val F: ConcurrentEffect[IO] =
      IO.ioConcurrentEffect(contextShift)

    protected implicit lazy val timer: Timer[IO] =
      runtimeRef.timer(F)
  }
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/11/22/effecttestsuite-scala/?pk_campaign=rss&quot;&gt;Using ScalaTest for Effects&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 22 Nov 2020 00:00:00 +0000</pubDate>
  <dc:modified>Mon, 19 Sep 2022 16:11:13 +0000</dc:modified>
  <atom:modified>Mon, 19 Sep 2022 16:11:13 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/11/22/effecttestsuite-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/11/22/effecttestsuite-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Cats Effect</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Best practice for natural Ordering</title>
  <description>Definitions of scala.math.Ordering MUST BE consistent with equals, an often overlooked law that can lead to problems.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2020/11/17/best-practice-for-ordering-comparable/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/ordering.png?202603060940&quot; alt=&quot;&quot; width=&quot;1608&quot; height=&quot;1000&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Scala has &lt;a href=&quot;https://www.scala-lang.org/api/2.13.3/scala/math/Ordering.html&quot;&gt;scala.math.Ordering&lt;/a&gt;, Java has &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html&quot;&gt;java.lang.Comparable&lt;/a&gt;. These are interfaces used for defining a natural order, which can then be used to sort lists of elements, or in data structures implemented via binary search trees, such as &lt;a href=&quot;https://www.scala-lang.org/api/2.13.3/scala/collection/SortedSet.html&quot;&gt;SortedSet&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;This is what it looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Ordering[A] {
  def compare(x: A, y: A): Int
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That function is supposed to define a “total order”, by returning a number that’s:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;strictly negative if &lt;code&gt;x &lt; y&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;strictly positive if &lt;code&gt;x &gt; y&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;0&lt;/code&gt; in case &lt;code&gt;x == y&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What’s often overlooked is that — ordering has to be &lt;em&gt;consistent with equals&lt;/em&gt;, as a law, or in other words:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;compare(x, y) == 0 &lt;-&gt; x == y
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.math.Ordering

final case class Contact(
  lastName: String,
  firstName: String,
  phoneNumber: String
)

object Contact {
  // WRONG — never do this!
  implicit val ordering: Ordering[Contact] =
    (x: Contact, y: Contact) =&gt;
      x.lastName.compareTo(y.lastName)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This might seem reasonable if you were building some sort of contacts agenda, but isn’t. Some reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;data-structures backed by binary-search trees can use just &lt;code&gt;compare&lt;/code&gt; when searching for keys&lt;/li&gt;
  &lt;li&gt;the result of sorting a list should not depend on its initial ordering&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example of what can happen when sorting lists:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val agenda1 = List(
  Contact(&quot;Nedelcu&quot;, &quot;Alexandru&quot;, &quot;0738293904&quot;),
  Contact(&quot;Nedelcu&quot;, &quot;Amelia&quot;, &quot;0745029304&quot;),
)

agenda1.sorted
//=&gt; List(Contact(Nedelcu,Alexandru,0738293904), Contact(Nedelcu,Amelia,0745029304))

val agenda2 = List(
  Contact(&quot;Nedelcu&quot;, &quot;Amelia&quot;, &quot;0745029304&quot;),
  Contact(&quot;Nedelcu&quot;, &quot;Alexandru&quot;, &quot;0738293904&quot;),
)

agenda2.sorted
//=&gt; List(Contact(Nedelcu,Amelia,0745029304), Contact(Nedelcu,Alexandru,0738293904))

agenda1.sorted == agenda2.sorted
//=&gt; false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Example of what happens when using &lt;code&gt;SortedSet&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.collection.immutable.SortedSet

val set1 = SortedSet(agenda1:_*)
//=&gt; TreeSet(Contact(Nedelcu,Alexandru,0738293904))

val set2 = SortedSet(agenda2:_*)
//=&gt; TreeSet(Contact(Nedelcu,Amelia,0745029304))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;SortedSet&lt;/code&gt;, being a &lt;code&gt;Set&lt;/code&gt; implementation, is not duplicating items, and as you can see here, it basically eliminates all contacts with the same &lt;code&gt;lastName&lt;/code&gt;, except for the first one it saw.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  If you’ve ever defined your ordering like this, don’t feel bad, as it happens to many of us. I was bitten by this just last week, in spite of knowing what I was doing … I defined a &lt;code&gt;private&lt;/code&gt; ordering and figured that it won’t get used improperly. Except that after a refactoring, by yours truly, it did end up being used improperly. Which is why definitions have to always be correct, as their correctness has to survive refactorings, even when it’s just you operating on that codebase.
&lt;/p&gt;

&lt;p&gt;The correct definition for our &lt;code&gt;Ordering&lt;/code&gt; would be:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object Contact {
  implicit val ordering: Ordering[Contact] =
    (x: Contact, y: Contact) =&gt; {
      x.lastName.compareTo(y.lastName) &lt;||&gt;
      x.firstName.compareTo(y.firstName) &lt;||&gt;
      x.phoneNumber.compareTo(y.phoneNumber)
    }

  // Just to help us out, this time
  private implicit class IntExtensions(val num: Int) extends AnyVal {
    def `&lt;||&gt;`(other: =&gt; Int): Int =
      if (num == 0) other else num
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don’t take shortcuts, don’t do anything less than this, even if you think that you currently don’t need it. Because one of your colleagues, or even your future self, might reuse this definition without knowing that it’s broken.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/11/17/best-practice-for-ordering-comparable/?pk_campaign=rss&quot;&gt;Best practice for natural Ordering&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 17 Nov 2020 09:02:13 +0000</pubDate>
  <link>https://alexn.org/blog/2020/11/17/best-practice-for-ordering-comparable/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/11/17/best-practice-for-ordering-comparable/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Best Practices</category>
  <category>Scala</category>
  </item>


<item>
  <title>Managing Database Migrations in Scala</title>
  <description>The database schema should be described as code, in your repository. And you should be able to semi-automatically update your database schema on new deployments.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2020/11/15/managing-database-migrations-scala/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/db-migrations-scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1400&quot; height=&quot;700&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  The database schema should be described as code, in your repository. And you should be able to semi-automatically update your database schema on new deployments.
&lt;/p&gt;

&lt;p&gt;A very popular Java library for handling migrations is &lt;a href=&quot;https://flywaydb.org/&quot;&gt;Flyway&lt;/a&gt;. We’ll combine that with &lt;a href=&quot;https://github.com/lightbend/config&quot;&gt;Typesafe Config (aka HOCON)&lt;/a&gt; for configuration, along with &lt;a href=&quot;https://github.com/pureconfig/pureconfig&quot;&gt;PureConfig&lt;/a&gt; for parsing it. And &lt;a href=&quot;https://github.com/typelevel/cats-effect&quot;&gt;Cats Effect&lt;/a&gt; for describing our effects, because we love FP, right? 😎&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  This is a complete solution, that’s customizable and easy to implement (couple of lines of code), that can be used in multi-project builds, and that doesn’t tie you to a &lt;a href=&quot;https://www.playframework.com/documentation/2.8.x/Evolutions&quot;&gt;particular framework&lt;/a&gt;, or a &lt;a href=&quot;http://www.lihaoyi.com/mill/page/contrib-modules.html#flyway&quot;&gt;particular build tool&lt;/a&gt;, or an &lt;a href=&quot;https://www.liquibase.org/&quot;&gt;enterprise solution&lt;/a&gt; solving problems that you don’t have.
&lt;/p&gt;

&lt;h2 id=&quot;1-setup-mysql-on-localhost&quot;&gt;1. Setup MySQL on localhost&lt;/h2&gt;

&lt;p&gt;We’re going to use &lt;a href=&quot;https://mariadb.org/&quot;&gt;MariaDB (MySQL)&lt;/a&gt; as our database, but this works with any relational database.&lt;/p&gt;

&lt;p&gt;To start a MariaDB instance on your localhost, you could use Docker:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;# NOTE: --rm means the container gets deleted after shutdown;
# if you want to keep the container around, then remove it

docker run --rm \
  --name mariadb \
  -e MYSQL_ROOT_PASSWORD=pass \
  -p 3306:3306 \
  mariadb:10.4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then to create our initial database:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;docker exec -it mariadb mysql -uroot -ppass \
  -e &quot;CREATE DATABASE MyAwesomeApp&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;warn-bubble&quot;&gt;
  &lt;strong&gt;WARN:&lt;/strong&gt; as a best practice, the &lt;code&gt;CREATE DATABASE&lt;/code&gt; statement should not be in your database migrations. The database, from production at least, must be created manually. Do not create or refer to specific databases in your migrations!
&lt;/p&gt;

&lt;h2 id=&quot;2-initial-project-setup&quot;&gt;2. Initial project setup&lt;/h2&gt;

&lt;p&gt;Start a new project with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sbt new scala/scala-seed.g8
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then add these library dependencies to your &lt;code&gt;build.sbt&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;lazy val root = (project in file(&quot;.&quot;))
  .settings(
    //... add these ...
    libraryDependencies ++= Seq(
      &quot;org.typelevel&quot; %% &quot;cats-effect&quot; % &quot;2.2.0&quot;,
      &quot;com.github.pureconfig&quot; %% &quot;pureconfig&quot; % &quot;0.14.0&quot;,
      &quot;org.flywaydb&quot; % &quot;flyway-core&quot; % &quot;7.2.0&quot;,
      &quot;mysql&quot; % &quot;mysql-connector-java&quot; % &quot;8.0.22&quot;,
      &quot;com.typesafe.scala-logging&quot; %% &quot;scala-logging&quot; % &quot;3.9.2&quot;,
    )
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;3-configuration&quot;&gt;3. Configuration&lt;/h2&gt;

&lt;p&gt;The app’s configuration is best described as concrete types in your project. Add something like this for the JDBC connection parameters, in &lt;code&gt;src/main/resources/application.conf&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;example.jdbc {
  driver = &quot;com.mysql.cj.jdbc.Driver&quot;

  host = &quot;127.0.0.1&quot;
  host = ${?DB_HOST}

  port = &quot;3306&quot;
  port = ${?DB_PORT}

  dbName = &quot;MyAwesomeApp&quot;
  dbName = ${?DB_NAME}

  url = &quot;jdbc:mysql://&quot;${example.jdbc.host}&quot;:&quot;${example.jdbc.port}&quot;/&quot;${example.jdbc.dbName}
  url = ${?DB_CONNECTION_URL}

  user = &quot;root&quot;
  user = ${?DB_USER}

  password = &quot;pass&quot;
  password = ${?DB_PASS}

  migrations-table = &quot;FlywaySchemaHistory&quot;

  migrations-locations = [
    &quot;classpath:example/jdbc&quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which is modelled by a type like this on the Scala side:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;package example
package jdbc

import cats.effect.Sync
import com.typesafe.config.{ Config, ConfigFactory }
import pureconfig.{ ConfigConvert, ConfigSource }
import pureconfig.generic.semiauto._

final case class JdbcDatabaseConfig(
  url: String,
  driver: String,
  user: Option[String],
  password: Option[String],
  migrationsTable: String,
  migrationsLocations: List[String]
)

object JdbcDatabaseConfig {
  def loadFromGlobal[F[_]: Sync](configNamespace: String): F[JdbcDatabaseConfig] =
    Sync[F].suspend {
      val config = ConfigFactory.load()
      load(config.getConfig(configNamespace))
    }

  def load[F[_]: Sync](config: Config): F[JdbcDatabaseConfig] =
    Sync[F].delay {
      ConfigSource.fromConfig(config).loadOrThrow
    }

  // Integration with PureConfig
  implicit val configConvert: ConfigConvert[JdbcDatabaseConfig] =
    deriveConvert
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;NOTES:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code&gt;migrations-table&lt;/code&gt; specifies the name of the table auto-created by Flyway, used to keep track of what migrations have been executed thus far;&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;migrations-locations&lt;/code&gt; is a list of locations for our migrations, most often a list of packages available on the classpath;&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;F[_]&lt;/code&gt; here is a datatype for managing I/O, such as &lt;code&gt;cats.effect.IO&lt;/code&gt; or &lt;code&gt;monix.eval.Task&lt;/code&gt;, but there’s no reason to not make these functions generic, such that you can later use whatever you want; see the documentation for &lt;a href=&quot;https://typelevel.org/cats-effect/typeclasses/sync.html&quot;&gt;Cats Effect’s Sync&lt;/a&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I chose this design because we may have a &lt;a href=&quot;https://www.scala-sbt.org/1.x/docs/Multi-Project.html&quot;&gt;multi-project build&lt;/a&gt;, and we may want to run database migrations for all projects in one go.&lt;/p&gt;

&lt;h2 id=&quot;4-flyway-library-integration&quot;&gt;4. Flyway library integration&lt;/h2&gt;

&lt;p&gt;We can now make use of &lt;a href=&quot;https://github.com/flyway/flyway&quot;&gt;Flyway&lt;/a&gt;, coupled with our config above:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;package example
package jdbc

import cats.effect.Sync
import cats.implicits._
import com.typesafe.scalalogging.LazyLogging
import org.flywaydb.core.api.configuration.FluentConfiguration
import org.flywaydb.core.api.Location
import org.flywaydb.core.Flyway
import scala.jdk.CollectionConverters._

object DBMigrations extends LazyLogging {

  def migrate[F[_]: Sync](config: JdbcDatabaseConfig): F[Int] =
    Sync[F].delay {
      logger.info(
        &quot;Running migrations from locations: &quot; +
        config.migrationsLocations.mkString(&quot;, &quot;)
      )
      val count = unsafeMigrate(config)
      logger.info(s&quot;Executed $count migrations&quot;)
      count
    }

  private def unsafeMigrate(config: JdbcDatabaseConfig): Int = {
    val m: FluentConfiguration = Flyway.configure
      .dataSource(
        config.url,
        config.user.orNull,
        config.password.orNull
      )
      .group(true)
      .outOfOrder(false)
      .table(config.migrationsTable)
      .locations(
        config.migrationsLocations
          .map(new Location(_))
          .toList: _*
      )
      .baselineOnMigrate(true)

    logValidationErrorsIfAny(m)
    m.load().migrate().migrationsExecuted
  }

  private def logValidationErrorsIfAny(m: FluentConfiguration): Unit = {
    val validated = m.ignorePendingMigrations(true)
      .load()
      .validateWithResult()

    if (!validated.validationSuccessful)
      for (error &lt;- validated.invalidMigrations.asScala)
        logger.warn(s&quot;&quot;&quot;
          |Failed validation:
          |  - version: ${error.version}
          |  - path: ${error.filepath}
          |  - description: ${error.description}
          |  - errorCode: ${error.errorDetails.errorCode}
          |  - errorMessage: ${error.errorDetails.errorMessage}
        &quot;&quot;&quot;.stripMargin.strip)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;5-create-your-first-db-migration&quot;&gt;5. Create your first DB migration&lt;/h2&gt;

&lt;p&gt;Add this in &lt;code&gt;src/main/resources/example/jdbc/V0010__CreateMyFirstTable.sql&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE MyFirstTable(
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  uKey VARCHAR(200) NOT NULL,
  uValue TEXT NOT NULL,
  createdAt TIMESTAMP NOT NULL,
  updatedAt TIMESTAMP NOT NULL
);

CREATE UNIQUE INDEX MyFirstTable__Key
ON MyFirstTable(uKey);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;6-add-sbt-command&quot;&gt;6. Add sbt command&lt;/h2&gt;

&lt;p&gt;Define a command, such that we can apply all migrations like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// TBD, does not work yet
sbt run-db-migrations
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First, define an “app” that can run all migrations:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;package example
package jdbc

import cats.implicits._
import cats.effect.IOApp
import cats.effect.{ExitCode, IO}
import com.typesafe.scalalogging.LazyLogging

object DBMigrationsCommand extends IOApp with LazyLogging {
  /**
    * Lists all JDBC data-sources, defined in `application.conf`
    */
  val dbConfigNamespaces = List(
    &quot;example.jdbc&quot;
  )

  def run(args: List[String]): IO[ExitCode] = {
    val migrate =
      dbConfigNamespaces.traverse_ { namespace =&gt;
        for {
          _   &lt;- IO(logger.info(s&quot;Migrating database configuration: $namespace&quot;))
          cfg &lt;- JdbcDatabaseConfig.loadFromGlobal[IO](namespace)
          _   &lt;- DBMigrations.migrate[IO](cfg)
        } yield ()
      }
    migrate.as(ExitCode.Success)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;NOTE: you can unify multiple migrations locations from multiple projects, in case you have a multi-project build. This is the reason for why &lt;code&gt;dbConfigNamespaces&lt;/code&gt; is a &lt;code&gt;List&lt;/code&gt; 😉&lt;/p&gt;

&lt;p&gt;Then add this in &lt;code&gt;build.sbt&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;lazy val runMigrate = taskKey[Unit](&quot;Migrates the database schema.&quot;)
addCommandAlias(&quot;run-db-migrations&quot;, &quot;runMigrate&quot;)

lazy val root = (project in file(&quot;.&quot;))
  .settings(
    //...
    fullRunTask(runMigrate, Compile, &quot;example.jdbc.DBMigrationsCommand&quot;),
    fork in runMigrate := true,
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now test that it works:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;sbt run-db-migrations
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then see what tables were created. Execute this in your shell:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;docker exec -it mariadb mysql -uroot -ppass MyAwesomeApp \
  -e &quot;SHOW TABLES&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should get this output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+------------------------+
| Tables_in_MyAwesomeApp |
+------------------------+
| FlywaySchemaHistory    |
| MyFirstTable           |
+------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;7-pro-tip-unit-test-migrations-with-hsqldb&quot;&gt;7. Pro-tip: Unit-test migrations with HSQLDB&lt;/h2&gt;

&lt;p&gt;You can run these migrations in your tests too. And you can use an in-memory database, such as HSQLDB, if your SQL does not use any specific MySQL features.&lt;/p&gt;

&lt;p&gt;Add this to your &lt;code&gt;build.sbt&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;lazy val root = (project in file(&quot;.&quot;))
  .settings(
    //...
    libraryDependencies ++= Seq(
      //...
      // Needed for testing
      &quot;org.hsqldb&quot; % &quot;hsqldb&quot; % &quot;2.5.1&quot; % Test,
      scalaTest % Test,
    ),
    // Recommended
    fork in Test := true,
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Add &lt;code&gt;src/test/resources/application.test.conf&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;include &quot;application.conf&quot;

// Overrides MySQL connection with in-memory HSQLDB
example.jdbc {
  url = &quot;jdbc:hsqldb:mem:MyAwesomeApp;sql.syntax_mys=true&quot;
  driver = &quot;org.hsqldb.jdbc.JDBCDriver&quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then add your test (in &lt;code&gt;src/test/scala/example/jdbc/DBTestSuite.scala&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;package example
package jdbc

import cats.effect._
import org.scalatest.funsuite.AnyFunSuite
import com.typesafe.config.ConfigFactory

class DBTestSuite extends AnyFunSuite {
  test(&quot;database migrations&quot;) {
    val conf = ConfigFactory
      .load(getClass.getClassLoader, &quot;application.test.conf&quot;)
      .resolve()

    val jdbcConf = JdbcDatabaseConfig
      .load[SyncIO](conf.getConfig(&quot;example.jdbc&quot;))
      .unsafeRunSync()

    val m = DBMigrations.migrate[SyncIO](jdbcConf).unsafeRunSync()
    assert(m == 1)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Run with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sbt test
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enjoy~&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/11/15/managing-database-migrations-scala/?pk_campaign=rss&quot;&gt;Managing Database Migrations in Scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 15 Nov 2020 16:17:25 +0000</pubDate>
  <link>https://alexn.org/blog/2020/11/15/managing-database-migrations-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/11/15/managing-database-migrations-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  <category>SQL</category>
  <category>Typelevel</category>
  </item>


<item>
  <title>List static blog tags in folder (Jekyll, etc)</title>
  <description>Script for listing the used tags of a Jekyll directory of articles.</description>
  <content:encoded>&lt;p&gt;I maintain a Jekyll blog, with tagged articles (tags specified in the Markdown front-matter), but maintaining tags isn’t easy, because I often forget what tags I used. E.g. is it &lt;code&gt;Functional&lt;/code&gt;, or &lt;code&gt;FP&lt;/code&gt;? I can never remember.&lt;/p&gt;

&lt;p&gt;Here’s a simple script that traverses all the files in a directory, parsing their YAML front-matter, gathers all the tags, then displays them sorted by popularity:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;#!/usr/bin/env ruby

require &apos;optparse&apos;
require &quot;json&quot;
require &quot;yaml&quot;

options = {}
OptionParser.new do |opt|
  opt.on(&apos;--folder PATH&apos;) { |o| options[:path] = File.expand_path(o) }
end.parse!

if !options[:path] &amp;&amp; ARGV[0] &amp;&amp; File.directory?(ARGV[0])
  options[:path] = File.expand_path(ARGV[0])
end
raise OptionParser::MissingArgument.new(&quot;--folder&quot;) if options[:path].nil?

filters = [
  File.join(options[:path], &quot;*.md&quot;),
  File.join(options[:path], &quot;*.markdown&quot;),
  File.join(options[:path], &quot;*.html&quot;),
  File.join(options[:path], &quot;*.htm&quot;),
]

all_tags = {}
filters.each do |filter|
  Dir[filter].each do |path|
    contents = File.read(path)
    if contents =~ /\A---\s*\r?\n(.*?)^---/m
      yaml_str = ($1).strip
      yaml = YAML.load(yaml_str)
      tags = yaml[&apos;tags&apos;] || []
      tags.each do |tag|
        all_tags[tag] ||= 0
        all_tags[tag] += 1
      end
    end
  end
end

all_tags.to_a.sort_by{|x| -x[1]}.each do |tag|
  printf(&quot;%20s %3d\n&quot;, tag[0], tag[1])
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;E.g. invoking it on my current &lt;code&gt;_snippets&lt;/code&gt; folder reveals:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;$ list-tags _snippets
               Scala  15
         Cats Effect   7
                Akka   4
    Reactive Streams   4
               Async   3
              Python   2
                 sbt   2
          TypeScript   2
                 CLI   2
                  FP   2
                Bash   1
                Ruby   1
              Jekyll   1
             Testing   1
               Monix   1
                 Fun   1
             Haskell   1
                 JVM   1
          JavaScript   1
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/11/13/list-blog-tags-in-folder/?pk_campaign=rss&quot;&gt;List static blog tags in folder (Jekyll, etc)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 13 Nov 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 13:24:12 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 13:24:12 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/11/13/list-blog-tags-in-folder/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/11/13/list-blog-tags-in-folder/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Blogging</category>
  <category>Jekyll</category>
  <category>Ruby</category>
  <category>Snippet</category>
  </item>


<item>
  <title>I like Option.get</title>
  <description>We should strive to make illegal states unrepresentable. Option.get is a partial function that, according to many, shouldn’t be in the standard library. Yet it doesn’t bother me; the inability of Scala to make it safe is the problem.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2020/11/12/i-like-option-get/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/option.get.png?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;800&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  In strong, static, expressive FP languages, such as Scala, or Haskell, there’s the ongoing drive to “&lt;em&gt;capture invariants in the type system&lt;/em&gt;” and “&lt;em&gt;to make illegal states unrepresentable&lt;/em&gt;”. For a nice introduction, see &lt;a href=&quot;https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/&quot;&gt;Parse, don’t validate&lt;/a&gt; by Alexis King.
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Option.get&lt;/code&gt; or &lt;code&gt;List.head&lt;/code&gt; get such bad reps because these functions aren’t total. To wit:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val value: Option[String] = None

value.get
//=&gt; java.util.NoSuchElementException: None.get
//     at scala.None$.get(Option.scala:627)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is indeed bad, because it fails at runtime. And if it fails at runtime, this means it can fail in production, in spite of all our unit tests and fancy CI setup.&lt;/p&gt;

&lt;p&gt;In fairness, even with the current status quo, &lt;code&gt;option.get&lt;/code&gt; is still better than usage of &lt;code&gt;null&lt;/code&gt;, because developers are still aware that the value might be missing (by seeing the type, then having to call &lt;code&gt;.get&lt;/code&gt;, at the very least), and even in absence of such mindfulness, at least the exception is clearer, as &lt;code&gt;NullPointerException&lt;/code&gt; is often thrown due to faulty internals, and JVM initialization timing issues. At least you know it’s your own fault 🙂&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;get&lt;/code&gt; wasn’t available on &lt;code&gt;Option&lt;/code&gt;, then you’d be forced to do this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;value match {
  case Some(v) =&gt; v
  case None =&gt; &quot;unknown&quot;
}
// Or this ...
value.getOrElse(&quot;unknown&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And if you’d miss a case, you’d get a warning (or an error, if you work with &lt;a href=&quot;https://alexn.org/blog/2020/05/26/scala-fatal-warnings/&quot;&gt;fatal warnings&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;value match { case Some(v) =&gt; v }
//=&gt; warning: match may not be exhaustive.
//   It would fail on the following input: None
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The compiler can thus force you to deal with &lt;code&gt;None&lt;/code&gt; explicitly.&lt;/p&gt;

&lt;p&gt;All of that aside however, in the following piece of code, what’s wrong isn’t the presence of &lt;code&gt;Option.get&lt;/code&gt;, but rather the compiler’s inability of seeing the &lt;code&gt;if&lt;/code&gt; expression:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// This is correct and will never trigger runtime exceptions
if (option.nonEmpty)
  option.get // Like a boss 😎
else
  &quot;unknown&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In other words, I’ll blame Scala and Haskell, and not the availability of &lt;code&gt;Option.get&lt;/code&gt;. I learned to expect more from my tools. It’s not me, it’s you, Scala.&lt;/p&gt;

&lt;p&gt;We could say that in absence of compiler features to cope with this, then &lt;code&gt;.get&lt;/code&gt; shouldn’t exist. However, programming languages are general purpose, and often get used in contexts in which strong static guarantees are not only useless, but get in the way. I still &lt;a href=&quot;https://alexn.org/blog/2020/11/11/organize-index-screenshots-ocr-macos/&quot;&gt;build my scripts in Ruby&lt;/a&gt;, because the static languages that I love are really bad for scripting. I’d like to disable some static guarantees, whenever brevity is important, and not correctness. E.g. for my own throwaway scripts I couldn’t care less that &lt;code&gt;Option.get&lt;/code&gt; throws exceptions.&lt;/p&gt;

&lt;p&gt;TypeScript has untagged unions, and under &lt;code&gt;--strict&lt;/code&gt; this throws an error:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;const sample: number | null = null

sample + 10
//=&gt; error TS2531: Object is possibly &apos;null&apos;.

// This works
if (sample !== null) {
  sample + 10
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;Option&lt;/code&gt; being boxed (tagged) provides us with benefits, like the ability to express &lt;code&gt;Option&lt;Option&lt;A&gt;&gt;&lt;/code&gt; (without auto-flattening), or the ability to define monadic operations for it. Here’s one way to express &lt;code&gt;Option&lt;/code&gt; in TypeScript:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;type None = {
  nonEmpty: false
}

type Some&lt;A&gt; = {
  nonEmpty: true
  value: A
}

type Option&lt;A&gt; = Some&lt;A&gt; | None

// ----------------------------------

const sample: Option&lt;String&gt; =
  { nonEmpty: false } // None

sample.value
//=&gt; error TS2339: Property &apos;value&apos; does not exist on type &apos;Option&lt;String&gt;&apos;.
//   Property &apos;value&apos; does not exist on type &apos;None&apos;.

// Compiles just fine
if (sample.nonEmpty) {
  console.log( sample.value )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is called &lt;a href=&quot;https://en.wikipedia.org/wiki/Flow-sensitive_typing&quot;&gt;Flow-sensitive typing&lt;/a&gt;. And minus some limitations and gotchas, it works just fine.&lt;/p&gt;

&lt;p&gt;I hope Scala will evolve to do it too, because TypeScript, and Kotlin can already do this 🙂 and it would be a shame for Scala to not evolve such abilities, to go along with its brand new &lt;a href=&quot;https://dotty.epfl.ch/docs/reference/new-types/union-types.html&quot;&gt;untagged union types&lt;/a&gt;.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/11/12/i-like-option-get/?pk_campaign=rss&quot;&gt;I like Option.get&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 12 Nov 2020 18:02:46 +0000</pubDate>
  <link>https://alexn.org/blog/2020/11/12/i-like-option-get/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/11/12/i-like-option-get/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  <category>TypeScript</category>
  </item>


<item>
  <title>Organize and Index Your Screenshots (OCR) on macOS</title>
  <description>Screenshots contain text, text that should be searchable, as finding a screenshot later is the whole point of creating it.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2020/11/11/organize-index-screenshots-ocr-macos/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/spotlight-search.png?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;800&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I maintain a growing &lt;code&gt;Screenshots&lt;/code&gt; folder. Screenshots contain text, text that should be searchable, as finding a screenshot later is the whole point of creating it.
&lt;/p&gt;

&lt;p&gt;My folder is stored in Dropbox, and unfortunately they are not indexing images on the “Plus” plan, at the moment of writing. And OneDrive currently has this functionality suspended for personal accounts, due to some technical issues they are having. Having to depend on a cloud service for searching your screenshots sucks, and I don’t want the lock-in of online services.&lt;/p&gt;

&lt;p&gt;Here’s how to organize and index your screenshots locally, using open source stuff, and save some money …&lt;/p&gt;

&lt;h2 id=&quot;1-install-tesseract-ocr-engine&quot;&gt;1. Install: Tesseract OCR Engine&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/tesseract-ocr/tesseract&quot;&gt;Tesseract OCR&lt;/a&gt; is a neat OSS project, available in Homebrew:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;brew install tesseract
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Given a PNG image file, you can convert it into a properly annotated PDF with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;tesseract /input/path/to/file.png /output/path/to/file -l eng pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will process &lt;code&gt;/input/path/to/file.png&lt;/code&gt; and create a properly annotated &lt;code&gt;/output/path/to/file.pdf&lt;/code&gt; from it, that can then be indexed by macOS’s Spotlight, or Dropbox.&lt;/p&gt;

&lt;h2 id=&quot;2-create-folder-structure&quot;&gt;2. Create folder structure&lt;/h2&gt;

&lt;p&gt;In Dropbox I have the following folders:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Screenshots
    &lt;ul&gt;
      &lt;li&gt;Processing&lt;/li&gt;
      &lt;li&gt;Raw&lt;/li&gt;
      &lt;li&gt;OCR&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;New screenshots go in &lt;code&gt;Processing&lt;/code&gt;. Indexable PDF files generated by Tesseract go in &lt;code&gt;OCR&lt;/code&gt;. And after processing, the raw files are moved in &lt;code&gt;Raw&lt;/code&gt;, possibly with some renaming, which helps in sorting the files by their timestamp.&lt;/p&gt;

&lt;h2 id=&quot;3-change-the-default-screenshots-folder&quot;&gt;3. Change the default screenshots folder&lt;/h2&gt;

&lt;p&gt;Instruct your macOS to save screenshots directly in your &lt;code&gt;Processing&lt;/code&gt; folder:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;defaults write com.apple.screencapture location ~/Dropbox/Screenshots/Processing
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;4-add-the-synchronization-script&quot;&gt;4. Add the synchronization script&lt;/h2&gt;

&lt;p&gt;I’ve built my script with Ruby. In case you don’t have Ruby installed:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;brew install ruby
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Create the following script somewhere on your &lt;code&gt;PATH&lt;/code&gt; and make it executable. I prefer &lt;code&gt;~/bin/screenshots-sync&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;#!/usr/bin/env ruby

require &apos;optparse&apos;
require &apos;pp&apos;

USAGE = &lt;&lt;ENDUSAGE
Usage:
  screenshots-sync [-h] -i &lt;path&gt; -o &lt;path&gt; -r &lt;path&gt; [-d]
ENDUSAGE

options = {}
OptionParser.new do |opts|
  opts.banner = USAGE

  opts.on(&quot;-i&quot;, &quot;--input-dir INPUT_DIR&quot;, &quot;Path to the input directory.&quot;) {|v|
    raise OptionParser::InvalidArgument unless File.directory?(v)
    options[:processingDir] = File.expand_path(v)
  }
  opts.on(&quot;-o&quot;, &quot;--output-ocr-dir OUTPUT_OCR_DIR&quot;, &quot;Path to the output directory for OCR-ed PDF files.&quot;) {|v|
    raise OptionParser::InvalidArgument unless File.directory?(v)
    options[:ocrDir] = File.expand_path(v)
  }
  opts.on(&quot;-r&quot;, &quot;--output-raw-dir OUTPUT_RAW_DIR&quot;, &quot;Path to the output directory for the raw image files.&quot;) {|v|
    raise OptionParser::InvalidArgument unless File.directory?(v)
    options[:rawDir] = File.expand_path(v)
  }
  opts.on(&quot;-f&quot;, &quot;--filter FILTER&quot;, &quot;File name filter (LIST), defaults to *.jpg, *.jpeg, *.png&quot;) {|v|
    options[:filter] ||= []
    options[:filter].push(v)
  }
  opts.on(&quot;-v&quot;, &quot;--[no-]verbose&quot;, &quot;Run verbosely&quot;) {|v|
    options[:verbose] = v
  }
end.parse!

options[:tesseract] = `which tesseract`
options[:tesseract] = &quot;/usr/local/bin/tesseract&quot; unless File.exists? options[:tesseract]
raise &quot;Missing tesseract executable from PATH&quot; unless File.executable?(options[:tesseract])

options[:filter] ||= [&quot;*.png&quot;, &quot;*.jpeg&quot;, &quot;*.jpg&quot;] unless options[:filter]

raise OptionParser::MissingArgument.new(&quot;--input-dir&quot;) if options[:processingDir].nil?
raise OptionParser::MissingArgument.new(&quot;--output-ocr-dir&quot;) if options[:ocrDir].nil?
raise OptionParser::MissingArgument.new(&quot;--output-raw-dir&quot;) if options[:rawDir].nil?

if options[:verbose]
  puts &quot;\nRunning with options:\n\n&quot;
  pp options
  puts
end

def execute(cmd, options)
  puts cmd if options[:verbose]
  out = if options[:verbose] then &quot;&quot; else &quot;1&gt;/dev/null 2&gt;&amp;1&quot; end
  r = system(&quot;#{cmd} #{out}&quot;)
  unless r
    $stderr.puts &quot;ERROR — command exited with error code (#{r}):\n  #{cmd}&quot;
    exit 1
  end
end

options[:filter].each do |filter|
  Dir[&quot;#{options[:processingDir]}/#{filter}&quot;].each do |f|
    # Filename format generated by macOS
    if f =~ /Screenshot\s+(\d{4}-\d{2}-\d{2})\s+at\s+(\d{2}\.\d{2}\.\d{2})/
      fname = &quot;Screenshot #{$1} #{$2}#{File.extname(f)}&quot;
    # Filename format generated by my Galaxy Tab (Android)
    elsif f =~ /Screenshot[_\s-]+(\d{4})(\d{2})(\d{2})[_\s-]+(\d{2})(\d{2})(\d{2})(?:[_\s-]+([^.]*))?/
      details = if $7 then &quot; #{$7}&quot; else &quot;&quot; end
      fname = &quot;Screenshot #{$1}-#{$2}-#{$3} #{$4}.#{$5}.#{$6}#{details}#{File.extname(f)}&quot;
    else
      fname = File.basename(f)
    end

    raw_output = File.join(options[:rawDir], fname)
    ocr_output = File.join(options[:ocrDir], fname)
    source = File.expand_path(f)

    if source != raw_output
      execute(&quot;mv \&quot;#{source}\&quot; \&quot;#{raw_output}\&quot;&quot;, options)
    end

    execute(&quot;#{options[:tesseract]} \&quot;#{raw_output}\&quot; \&quot;#{ocr_output}\&quot; -l eng pdf&quot;, options)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don’t forget to make it executable:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;chmod +x ~/bin/screenshots-sync
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that this script can be used standalone, for importing existing screenshots archives:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;$ screenshots-sync -h

Usage:
  screenshots-sync [-h] -i &lt;path&gt; -o &lt;path&gt; -r &lt;path&gt; [-d]
    -i, --input-dir INPUT_DIR        Path to the input directory.
    -o OUTPUT_OCR_DIR,               Path to the output directory for OCR-ed PDF files.
        --output-ocr-dir
    -r OUTPUT_RAW_DIR,               Path to the output directory for the raw image files.
        --output-raw-dir
    -f, --filter FILTER              File name filter (LIST), defaults to *.jpg, *.jpeg, *.png
    -v, --[no-]verbose               Run verbosely
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;5-load-a-launch-agent&quot;&gt;5. Load a Launch Agent&lt;/h2&gt;

&lt;p&gt;Installing a &lt;a href=&quot;https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html&quot;&gt;launch agent&lt;/a&gt; for running our synchronization script, whenever new files appear in &lt;code&gt;Processing&lt;/code&gt;, is easy.&lt;/p&gt;

&lt;p&gt;Create the &lt;code&gt;~/Library/LaunchAgents/my.sync.ocr.plist&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
&lt;plist version=&quot;1.0&quot;&gt;
&lt;dict&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;my.screenshot.ocr&lt;/string&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;!-- TODO: change alex with your username --&gt;
        &lt;string&gt;/Users/alex/bin/screenshots-sync&lt;/string&gt;
        &lt;string&gt;--input-dir&lt;/string&gt;
        &lt;!-- TODO: change alex with your username --&gt;
        &lt;string&gt;/Users/alex/Dropbox/Screenshots/Processing&lt;/string&gt;
        &lt;string&gt;--output-ocr-dir&lt;/string&gt;
        &lt;!-- TODO: change alex with your username --&gt;
        &lt;string&gt;/Users/alex/Dropbox/Screenshots/OCR&lt;/string&gt;
        &lt;string&gt;--output-raw-dir&lt;/string&gt;
        &lt;!-- TODO: change alex with your username --&gt;
        &lt;string&gt;/Users/alex/Dropbox/Screenshots/Raw&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;WatchPaths&lt;/key&gt;
    &lt;array&gt;
        &lt;!-- TODO: change alex with your username --&gt;
        &lt;string&gt;/Users/alex/Dropbox/Screenshots/Processing&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;ThrottleInterval&lt;/key&gt;
    &lt;integer&gt;5&lt;/integer&gt;
    &lt;key&gt;StandardOutPath&lt;/key&gt;
    &lt;!-- TODO: change alex with your username --&gt;
    &lt;string&gt;/Users/alex/Library/Logs/screenshots-sync.log&lt;/string&gt;
    &lt;key&gt;StandardErrorPath&lt;/key&gt;
    &lt;!-- TODO: change alex with your username --&gt;
    &lt;string&gt;/Users/alex/Library/Logs/screenshots-sync.log&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then install it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;launchctl load -w ~/Library/LaunchAgents/my.sync.ocr.plist
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;enjoy&quot;&gt;Enjoy&lt;/h2&gt;

&lt;p&gt;Your screenshots will now be indexed by macOS’s Finder, searchable via Spotlight.&lt;/p&gt;

&lt;p&gt;They’ll also get indexed by Dropbox, because the Plus plan supports searching in PDF files.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/11/11/organize-index-screenshots-ocr-macos/?pk_campaign=rss&quot;&gt;Organize and Index Your Screenshots (OCR) on macOS&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 11 Nov 2020 12:43:46 +0000</pubDate>
  <link>https://alexn.org/blog/2020/11/11/organize-index-screenshots-ocr-macos/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/11/11/organize-index-screenshots-ocr-macos/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Cloud</category>
  <category>macOS</category>
  <category>Ruby</category>
  </item>


<item>
  <title>Block comments on the web</title>
  <description>Comments on the web can be toxic, and a waste of time. Here’s how to block them…</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  Comments on the web can be toxic, and a waste of time. Here&apos;s how to block them ...
&lt;/p&gt;

&lt;h2 id=&quot;in-firefoxchrome-and-android&quot;&gt;In Firefox/Chrome, and Android&lt;/h2&gt;

&lt;p&gt;I assume you already use &lt;a href=&quot;https://github.com/gorhill/uBlock&quot;&gt;uBlock Origin&lt;/a&gt;, and if not, then throw away whatever alternative you have, and switch to it.&lt;/p&gt;

&lt;p&gt;On Android, uBlock Origin is supported by &lt;a href=&quot;https://www.mozilla.org/en-US/firefox/mobile/&quot;&gt;Firefox&lt;/a&gt;. If Firefox isn’t an option, there are others. At the moment of writing &lt;a href=&quot;https://vivaldi.com/&quot;&gt;Vivaldi&lt;/a&gt; has backed-in content blocking, and supports custom filtering rules, but you might have to publish these rules, in a text file, somewhere online. &lt;a href=&quot;https://adguard.com&quot;&gt;Adguard&lt;/a&gt; might also support custom content filtering rules, although I have issues with trusting them MITM my traffic.&lt;/p&gt;

&lt;p&gt;In uBlock Origin, add these to “&lt;em&gt;My Filters&lt;/em&gt;” in its dashboard:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;news.ycombinator.com##table.comment-tree
reddit.com##div.commentarea

youtube.com###comments

||disqus.com/embed/comments/
||disqus.com/embed.js
###disqus_thread
##.dsq-brlink
##.disqus-container
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s how it should look like:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/block-comments.png?202603060940&quot; alt=&quot;Screenshot of uBlock Origin&apos;s My Filters section&quot; width=&quot;1526&quot; height=&quot;763&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;These rules block comments from:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Hacker News&lt;/li&gt;
  &lt;li&gt;Reddit&lt;/li&gt;
  &lt;li&gt;YouTube&lt;/li&gt;
  &lt;li&gt;Disqus (on all websites)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optionally, for extra sanity and street cred, also add these rules 😎&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;||twitter.com
||facebook.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A short primer on the syntax …&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Prefix CSS selectors with &lt;code&gt;##&lt;/code&gt;; so &lt;code&gt;##.dsq-brlink&lt;/code&gt; will block HTML elements with a &lt;code&gt;.dsq-brlink&lt;/code&gt; class, and &lt;code&gt;###disqus_thread&lt;/code&gt; will block HTML elements with a &lt;code&gt;#disqus_thread&lt;/code&gt; ID
    &lt;ul&gt;
      &lt;li&gt;These CSS selectors can be “generic”, meaning they apply to all websites (in the case of Disqus), or they can apply to a specific domain: e.g. &lt;code&gt;###disqus_thread&lt;/code&gt; is a cosmetic filter that applies to all websites, whereas &lt;code&gt;youtube.com###comments&lt;/code&gt; filters HTML elements with a &lt;code&gt;#comments&lt;/code&gt; ID that are shown on &lt;code&gt;youtube.com&lt;/code&gt;
&lt;/li&gt;
      &lt;li&gt;See relevant &lt;a href=&quot;https://adblockplus.org/filter-cheatsheet#elementhiding&quot; target=&quot;_blank&quot;&gt;cheat sheet section&lt;/a&gt;
&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You can block specific resources from loading; a &lt;code&gt;||&lt;/code&gt; prefix means that a domain name follows, until a separator such as &lt;code&gt;/&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;A rule such as &lt;code&gt;||disqus.com/embed.js&lt;/code&gt; will block &lt;code&gt;/embed.js&lt;/code&gt; on all subdomains of &lt;code&gt;disqus.com&lt;/code&gt;
&lt;/li&gt;
      &lt;li&gt;See relevant &lt;a href=&quot;https://adblockplus.org/filter-cheatsheet#blocking2&quot; target=&quot;_blank&quot;&gt;cheat sheet section&lt;/a&gt;
&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more details on these rules, see this cheat sheet: &lt;br&gt;
&lt;a href=&quot;https://adblockplus.org/filter-cheatsheet&quot;&gt;Adblock filters explained&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;publish-it&quot;&gt;Publish it&lt;/h3&gt;

&lt;p&gt;You can publish this list, as a text file, somewhere, anywhere, and reuse it wherever you have uBlock Origin installed. For example, I published mine at:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://alexn.org/assets/misc/block-lists/no-comments.txt&quot; target=&quot;_blank&quot;&gt;alexn.org/assets/misc/block-lists/no-comments.txt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then import it in uBlock Origin easily:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/block-comments2.png?202603060940&quot; alt=&quot;Screenshot of uBlock Origin&apos;s Filter List&quot; width=&quot;1375&quot; height=&quot;728&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;safari--ios-iphone-ipad&quot;&gt;Safari / iOS (iPhone, iPad)&lt;/h2&gt;

&lt;p&gt;Safari, on macOS and iOS, has content blockers too. Not as capable, but they do the job. An excellent one is &lt;a href=&quot;https://giorgiocalderolla.com/wipr.html&quot;&gt;Wipr&lt;/a&gt;, but it doesn’t allow setting custom rules.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A prepackaged solution that can block comments is &lt;a href=&quot;https://petercammeraat.net/projects/quiet/&quot;&gt;Quiet&lt;/a&gt;, but that’s less fun&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://1blocker.com/&quot;&gt;1Blocker&lt;/a&gt; appears to allow for &lt;a href=&quot;https://support.1blocker.com/hc/en-us/articles/360002309738-Creating-Custom-Rules&quot;&gt;creating custom rules&lt;/a&gt;, but I haven’t tried it yet&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://developer.apple.com/documentation/safariservices/creating_a_content_blocker&quot;&gt;Building your own content blocker&lt;/a&gt; could be a fun project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you know of a better solution, write about it in the comments section 😅😂&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/10/20/block-comments-on-the-web/?pk_campaign=rss&quot;&gt;Block comments on the web&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 20 Oct 2020 19:51:45 +0000</pubDate>
  <link>https://alexn.org/blog/2020/10/20/block-comments-on-the-web/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/10/20/block-comments-on-the-web/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Browser</category>
  <category>Web</category>
  </item>


<item>
  <title>Generic IOApp alternative</title>
  <description>IOApp alternative, for Cats Effect v2, that can work with any effect type.</description>
  <content:encoded>&lt;p&gt;This is a simple and generic &lt;a href=&quot;https://typelevel.org/cats-effect/datatypes/ioapp.html&quot;&gt;IOApp&lt;/a&gt; and &lt;a href=&quot;https://monix.io/api/current/monix/eval/TaskApp.html&quot;&gt;TaskApp&lt;/a&gt; replacement. For those instances in which you want to work with &lt;code&gt;F[_]&lt;/code&gt; and not &lt;code&gt;IO&lt;/code&gt; or &lt;code&gt;Task&lt;/code&gt;, even in &lt;code&gt;main&lt;/code&gt; apps.&lt;/p&gt;

&lt;p&gt;Requirements:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://alexn.org/blog/2020/10/12/effect-runtime/&quot;&gt;EffectRuntime&lt;/a&gt; (snippet); or if not in the mood for that, replace it with the basic &lt;a href=&quot;https://typelevel.org/cats-effect/datatypes/contextshift.html&quot;&gt;cats.effect.ContextShift&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://monix.io/docs/3x/#monix-catnap&quot;&gt;Monix Catnap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect._
import monix.catnap.SchedulerEffect

abstract class PureApp[F[_]](implicit protected val F: Async[F]) { self =&gt;
  protected def runtime: Resource[SyncIO, EffectRuntime[F]]
  protected def effect(implicit r: EffectRuntime[F]): ConcurrentEffect[F]
  protected implicit def timer(implicit F: Concurrent[F], r: EffectRuntime[F]): Timer[F] = r.timer

  def run(args: List[String])(implicit
    F: ConcurrentEffect[F],
    r: EffectRuntime[F]
  ): F[ExitCode]

  final def main(args: Array[String]): Unit = {
    val (res, cancel) = runtime.allocated.unsafeRunSync()
    implicit val r = res
    try {
      new CustomIOApp()(effect(r), r).main(args)
    } finally {
      cancel.unsafeRunSync()
    }
  }

  private final class CustomIOApp(implicit F: ConcurrentEffect[F], runtime: EffectRuntime[F])
    extends IOApp {

    override protected implicit def contextShift: ContextShift[IO] =
      SchedulerEffect.contextShift[IO](runtime.unsafe.scheduler)(IO.ioEffect)
    override protected implicit def timer: Timer[IO] =
      SchedulerEffect.timerLiftIO[IO](runtime.unsafe.scheduler)(IO.ioEffect)
    override def run(args: List[String]): IO[ExitCode] =
      F.toIO(self.run(args))
  }
}

object PureApp {
  abstract class ForIO extends PureApp[IO] {
    override final def effect(implicit r: EffectRuntime[IO]): ConcurrentEffect[IO] =
      IO.ioConcurrentEffect(r)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sample:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;abstract class MyGenericApp[F[_]: Async] extends PureApp[F] {
  
  def run(args: List[String])(implicit
    F: ConcurrentEffect[F],
    r: EffectRuntime[F]
  ): F[ExitCode] = {
    for {
      name &lt;- Sync[F].delay(scala.io.StdIn.readLine())
      _    &lt;- Timer[F].sleep(1.second)
      _    &lt;- Sync[F].delay(println(s&quot;Hello, $name&quot;))
    } yield {
      ExitCode.Success
    }
  }
}

/**
 * Actual main implementation that the JVM can recognize.
 */
object MyApp extends MyGenericApp[IO] {
  override def runtime: Resource[SyncIO, EffectRuntime[F]] = 
    ???
  override def effect(implicit r: EffectRuntime[F]) = 
    IO.ioConcurrentEffect(r)
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/10/15/generic-ioapp-alternative/?pk_campaign=rss&quot;&gt;Generic IOApp alternative&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 15 Oct 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 13:31:09 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 13:31:09 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/10/15/generic-ioapp-alternative/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/10/15/generic-ioapp-alternative/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Cats Effect</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Effect Runtime</title>
  <description>Defining a “runtime” for Cats-Effect v2 that provides the underlying environment necessary (i.e. ContextShift, Timer, Clock).</description>
  <content:encoded>&lt;p&gt;Defining an &lt;code&gt;EffectRuntime&lt;/code&gt; that is used to build IO effects. This would be a replacement for &lt;a href=&quot;https://typelevel.org/cats-effect/datatypes/contextshift.html&quot;&gt;ContextShift&lt;/a&gt; (Cats Effect 2.x), with an integrated &lt;code&gt;Logger&lt;/code&gt;, &lt;a href=&quot;https://monix.io/docs/current/execution/scheduler.html&quot;&gt;Scheduler&lt;/a&gt; (thus having access to &lt;a href=&quot;https://typelevel.org/cats-effect/datatypes/timer.html&quot;&gt;Timer&lt;/a&gt; too), and utilities for monitoring.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;UnsafeLogger&lt;/code&gt; / &lt;code&gt;SafeLogger&lt;/code&gt; and &lt;code&gt;UnsafeMonitoring&lt;/code&gt; interfaces are left as an exercise for the reader.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect._
import cats.implicits._
import monix.execution._
// ...

/**
  * Slice of [[EffectRuntime]], to be used only when a dependency on
  * [[UnsafeLogger]] is needed.
  */
trait UnsafeRuntimeLogger {
  def unsafe: UnsafeLoggerRef

  trait UnsafeLoggerRef {
    def logger: UnsafeLogger
  }
}

/**
  * Slice of [[EffectRuntime]], to be used only when a dependency 
  * on `ExecutionContext` / `monix.execution.Scheduler` is needed.
  */
trait UnsafeRuntimeScheduler {
  def unsafe: UnsafeSchedulerRef

  trait UnsafeSchedulerRef {
    def scheduler: Scheduler
  }
}

/**
  * Slice of [[EffectRuntime]], to be used only when a reference
  * to [[UnsafeMonitoring]] is needed.
  */
trait UnsafeRuntimeMonitoring {
  def unsafe: UnsafeMonitoringRef

  trait UnsafeMonitoringRef {
    def monitoring: UnsafeMonitoring
  }
}

/**
  * Slice of [[EffectRuntime]], to be used only in an &quot;unsafe&quot;context
  * (where side effects are not suspended in `F[_]`).
  */
trait UnsafeRuntime
  extends UnsafeRuntimeLogger
  with UnsafeRuntimeScheduler
  with UnsafeRuntimeMonitoring {

  def unsafe: Unsafe

  trait Unsafe extends UnsafeLoggerRef 
    with UnsafeSchedulerRef 
    with UnsafeMonitoringRef
}

/**
  * Slice of [[EffectRuntime]], to be used only when a reference
  * to [[SafeLogger]] is needed.
  */
trait EffectRuntimeLogger[F[_]] extends UnsafeRuntimeLogger {
  protected implicit def F: Sync[F]
  def logger: SafeLogger[F]
}

/**
  * Our evolved `cats.effect.ContextShift` that has everything 
  * we need in it to build IO effects.
  */
abstract class EffectRuntime[F[_]]
  extends ContextShift[F]
  with EffectRuntimeLogger[F]
  with UnsafeRuntime { self =&gt;

  protected implicit def F: Async[F]

  def logger: SafeLogger[F]
  def scheduler: F[Scheduler]
  def blocker: Blocker
  def timer(implicit F: Concurrent[F]): Timer[F]

  def deferAction[A](f: Scheduler =&gt; F[A]): F[A] =
    self.scheduler.flatMap(f)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sample for wrapping a Future-based API:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent._
import scala.concurrent.duration._

def unsafeGetRequest(req: Request)(
  implicit ec: ExecutionContext
): Future[Response] = {
  ???
}

def getRequest[F[_]: Concurrent](req: Request)(
  implicit r: EffectRuntime[F]
): F[Response] =
  r.deferAction { implicit ec =&gt;
    for {
      _ &lt;- r.logger.debug(s&quot;Triggering request: $req&quot;)
      resp &lt;- Async
        .fromFuture(Sync[F].delay(unsafeGetRequest(req)))
        .handleErrorWith { err =&gt;
          r.logger.error(&quot;Unexpected error, retrying&quot;, err) &gt;&gt;
          r.timer[F].sleep(1.second) &gt;&gt;
          getRequest(req)
        }
    } yield {
      resp
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;WARN: the retry logic isn’t a good one. For a better implementation,
see &lt;a href=&quot;https://alexn.org/blog/2020/08/03/on-error-retry-loop/&quot;&gt;Retry Failing Tasks with Cats and Scala&lt;/a&gt;.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/10/12/effect-runtime/?pk_campaign=rss&quot;&gt;Effect Runtime&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 12 Oct 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 13:30:23 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 13:30:23 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/10/12/effect-runtime/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/10/12/effect-runtime/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Cats Effect</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>When My World Vanishes</title>
  <description>It’s me, facing a hard to solve problem. It’s a difficult one, and I’m having problems focusing. I make some coffee, I move to another room, and I’m already thinking of running to some coffee shop, forgetting that we’re still in a pandemic.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  It’s me, facing a hard to solve problem. It’s a difficult one, and I’m having problems focusing. I make some coffee, I move to another room, and I’m already thinking of running to some coffee shop, forgetting that we’re still in a pandemic. I sometimes find it hard to focus, it can be hard to start, I procrastinate a lot, or I’m just too damn lazy.
&lt;/p&gt;

&lt;p&gt;The problems I’m dealing with can require an extreme attention to details, as you have to load all of those fine-grained interactions between components, all of those side effects, all the system’s responsibilities and limitations; you go over the problem repeatedly, maybe you can understand it, maybe you can simplify it, maybe you don’t need to solve it at all. When things don’t work, you try a change in perspective.&lt;/p&gt;

&lt;p&gt;My 10-year-old son is often imitating my computer posture. He wants to grow up to be just like me, but the jury is still out on whether that’s a good thing 🤷‍♂️&lt;/p&gt;

&lt;p&gt;People can’t solve multiple problems in parallel. When we do, we only do it for superficial problems. Yes, we can drive a car while talking on the phone, or thinking about some argument with a colleague. But that’s only because of the autonomic nervous system, which can be trained to make us do things out of reflex, putting us in auto-pilot. It’s like when breathing, we don’t think about breathing in or out.&lt;/p&gt;

&lt;p&gt;When I drive alone, I’m so deep in my own thoughts, that I’m in full auto-pilot, changing gears, making turns, stopping at the red light, avoiding obstacles. I sometimes awaken while driving towards the office, even if we are still during the pandemic, it’s weekend, and my trip was to the supermarket, in the opposite direction. Funny enough I get the same effect when ridding my bike, or my kick scooter, in spite of the increased effort, the constant motion of my legs, and the increased awareness needed to avoid traffic accidents.&lt;/p&gt;

&lt;p&gt;Hard problems demand focus. A single word from a colleague, or from my wife or kid, a single runaway thought could destroy my focus. Working from home can be hard, especially when you have a son that wants to play, and you can’t say no to his puppy eyes.&lt;/p&gt;

&lt;p&gt;To help focus I often play some tune on repeat, over and over again. Or maybe there’s some inertia, the problem is exciting, and that magic moment finally comes …&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/earth.jpg&quot; alt=&quot;Picture of Earth&quot; width=&quot;1200&quot; height=&quot;600&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;And the world around me vanishes …&lt;/p&gt;

&lt;p&gt;All other problems, my hopes, my dreams, my worries about tomorrow, the world’s hum, everything becomes irrelevant and silent, feeling as if I’ve migrated to another reality, being just me and the algorithm I’m working on. A reality in which the problems are solvable, and the solutions are born out of thin air. It’s like a vice; if I ever had one that I can’t quit, this is it.&lt;/p&gt;

&lt;p&gt;It’s the reason for why I never liked alcohol, as it prevents me from going there. I remember being junior year in high-school, and getting drunk with my gang. It’s a memory that got imprinted on me, because the national “Olympiad in Informatics” was in a couple of days, and drunk as I was, I kept repeating the recipe for “&lt;em&gt;killed backtracking&lt;/em&gt;”, out of fear I’d forget it. Fun times, got third prize.&lt;/p&gt;

&lt;p&gt;I remembered this intense feeling of focus while browsing my music library, and finding a gem. I give you the sound-track of &lt;a href=&quot;https://monix.io&quot;&gt;Monix&lt;/a&gt;, a tune I played over and over again during some of the most focused days I’ve ever had:&lt;/p&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=mlXtwZY4ko4&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/mlXtwZY4ko4/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=mlXtwZY4ko4&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Best Mamgu Ever — Underworld
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Tonight I worked on a hard problem, playing this tune on auto-repeat.&lt;/p&gt;

&lt;p&gt;I’ll probably fail to go to sleep too soon, as this dumb tune is going to keep ringing in my ears. But it’s not really the music that’s keeping me awake, but the problem I’ve been working on, with the tune being just its echo. Oh well, my brain will have to calm down eventually.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/10/10/when-my-world-vanishes/?pk_campaign=rss&quot;&gt;When My World Vanishes&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sat, 10 Oct 2020 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2020/10/10/when-my-world-vanishes/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/10/10/when-my-world-vanishes/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Personal</category>
  </item>


<item>
  <title>Scala Snippet: Unlawful Effects</title>
  <description>Unlawful/independent version of cats.effect.Effect.</description>
  <content:encoded>&lt;p&gt;Unlawful/independent version of &lt;code&gt;cats.effect.Effect&lt;/code&gt; from Cats Effect v2. Allows for converting (and executing) &lt;code&gt;IO&lt;/code&gt;-like values to &lt;code&gt;scala.concurrent.Future&lt;/code&gt;, being also good for a graceful migration to Cats Effect v3:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.ApplicativeError
import cats.effect.{ Effect, IO }
import cats.implicits._
import simulacrum.typeclass
import scala.concurrent.{ Future, Promise }

/**
  * Type class defining an &quot;unlawful&quot; variant of `cats.effect.Effect`.
  *
  * This allows it to work with plain `Future`, which cannot implement `Effect`.
  * It also allows for a graceful migration to Cats Effect v3.
  *
  * NOTE: if the requirement is `F[_] : Sync : UnlawfulEffect` then this
  * is de facto equivalent with `Effect`, therefore `UnlawfulEffect` shouldn&apos;t
  * be used.
  */
@typeclass trait UnlawfulEffect[F[_]] {
  def unsafeToFuture[A](fa: F[A]): Future[A]
}

object UnlawfulEffect extends UnlawfulEffectLowLevelImplicits {
  /**
    * Standard `Future` instance, which couldn&apos;t be a lawful `Effect`.
    */
  implicit val forFuture: UnlawfulEffect[Future] =
    new UnlawfulEffect[Future] {
      override def unsafeToFuture[A](fa: Future[A]): Future[A] =
        fa
    }

  /**
    * Optimization for `cats.effect.IO`, even if this should be handled by
    * [[forAnyEffect]].
    */
  implicit val forIO: UnlawfulEffect[IO] =
    new UnlawfulEffect[IO] {
      override def unsafeToFuture[A](fa: IO[A]): Future[A] =
        fa.unsafeToFuture()
    }
}

trait UnlawfulEffectLowLevelImplicits { self: UnlawfulEffect.type =&gt;
  /**
    * Converts from:
    * [[https://typelevel.org/cats-effect/typeclasses/effect.html]]
    */
  implicit def forAnyEffect[F[_]](implicit F: Effect[F]): UnlawfulEffect[F] =
    new UnlawfulEffect[F] {
      override def unsafeToFuture[A](fa: F[A]): Future[A] = {
        val p = Promise[A]()
        F.runAsync(fa) { result =&gt;
          // Not really cool to not suspend side-effects here, but
          // we know the context in which we are in, and it&apos;s fine, this time;
          // Don&apos;t try this at home!
          p.complete(result.toTry)
          IO.unit
        }.unsafeRunSync()
        p.future
      }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can then interact with more impure APIs, that aren’t IO-driven:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import akka.stream.scaladsl.Flow

implicit class FlowOps[In, Out, Mat](flow: Flow[In, Out, Mat]) 
  extends AnyVal {

  def mapEffect[F[_]: UnlawfulEffect, Out2](
    parallelism: Int
  )(fa: Out =&gt; F[Out2]): Flow[In, Out2, Mat] = {
    flow.mapAsync(parallelism)(out =&gt; UnlawfulEffect.unsafeToFuture(fa(out)))
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sample:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.IO

Flow[Int].mapEffect { num =&gt;
  IO {
    println(s&quot;Received: $num&quot;)
    num.toString
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is similar to usage of &lt;a href=&quot;https://monix.io/api/current/monix/eval/TaskLike.html&quot;&gt;TaskLike&lt;/a&gt; in &lt;a href=&quot;https://monix.io&quot;&gt;Monix&lt;/a&gt;.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/10/08/unlawful-effect.scala/?pk_campaign=rss&quot;&gt;Scala Snippet: Unlawful Effects&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 08 Oct 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 13:36:39 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 13:36:39 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/10/08/unlawful-effect.scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/10/08/unlawful-effect.scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Cats Effect</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Running integration tests, with Scala + sbt</title>
  <description>Scala sbt setup for separating unit tests from integrationt tests.</description>
  <content:encoded>&lt;p&gt;For separating integration tests, from unit tests, in &lt;code&gt;build.sbt&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// sbt command-line shortcut
addCommandAlias(&quot;ci-integration&quot;, &quot;Integration/testOnly -- -n integrationTest&quot;)

lazy val IntegrationTest = config(&quot;integration&quot;).extend(Test)

//...
lazy val root = Project(base = file(&quot;.&quot;))
  .configs(IntegrationTest)
  .settings(
    // Exclude integration tests by default (in ScalaTest)
    Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, &quot;-l&quot;, &quot;integrationTest&quot;),
    // Include integration tests, by nullifying the above option
    IntegrationTest / testOptions := Seq.empty,
  )
  .settings(
    // Enable integration tests
    inConfig(IntegrationTest)(Defaults.testTasks)
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then in your tests:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import org.scalatest.Tag
import org.scalatest.funsuite.AsyncFunSuite

object IntegrationTest extends Tag(&quot;integrationTest&quot;)

class MyTestSuite extends AsyncFunSuite {
  // Tagging this test as an integration test
  test(&quot;integration works&quot;, IntegrationTest) {
    ???
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then run:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;sbt ci-integration
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/10/05/running-integration-tests.scala/?pk_campaign=rss&quot;&gt;Running integration tests, with Scala + sbt&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 05 Oct 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 13:38:35 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 13:38:35 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/10/05/running-integration-tests.scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/10/05/running-integration-tests.scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>sbt</category>
  <category>Scala</category>
  <category>Testing</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Scala Snippet: Flow/Processor to Effect</title>
  <description>Converts an Akka Streams Flow into an In =&amp;gt; IO[Out] method, thus wrapping Flow into Cats-Effect’s IO.</description>
  <content:encoded>&lt;p&gt;Converts an Akka Streams &lt;code&gt;Flow&lt;/code&gt; into an &lt;code&gt;In =&gt; IO[Out]&lt;/code&gt; method,
thus wrapping &lt;code&gt;Flow&lt;/code&gt; into Cats-Effect’s &lt;code&gt;IO&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import akka.actor.ActorSystem
import akka.stream.Materializer
import akka.stream.scaladsl.Flow
import cats.effect.{ ContextShift, IO, Resource }
import cats.implicits._
import monix.execution.AsyncSemaphore
import monix.execution.atomic.Atomic
import org.reactivestreams.{ Processor, Publisher, Subscriber, Subscription }

import scala.annotation.{ nowarn, tailrec }
import scala.concurrent.duration.Duration
import scala.concurrent.{ Await, ExecutionContext, Future, Promise }

final class FlowToEffect[In, Out] private (
  processor: Processor[In, Out]
)(implicit
  cs: ContextShift[IO],
  ec: ExecutionContext
) {
  private[this] val (producer: Publisher[Out], subscriber: Subscriber[In]) =
    (processor, processor)

  private[this] val awaitCallLatch = AsyncSemaphore(1)
  private[this] var publisherResponsePromise: Promise[Out] = _
  private[this] val requested =
    Atomic(Left(Promise()): Either[Promise[Unit], Long])

  private[this] val connectionClosed = Promise[Unit]()

  subscriber.onSubscribe(new Subscription {
    // Called by Akka Streams
    @tailrec
    override def request(n: Long): Unit = {
      assert(n &gt;= 0)
      if (n == 0) return
      val update =
        if (n - 1 &gt; 0) Right(n - 1)
        else Left(Promise[Unit]())

      requested.get() match {
        case current @ Left(promise) =&gt;
          if (!requested.compareAndSet(current, update))
            request(n)
          else
            promise.success(())

        case current @ Right(n0) =&gt;
          if (!requested.compareAndSet(current, Right(n + n0)))
            request(n)
      }
    }

    // Called by Akka Streams
    override def cancel(): Unit =
      throw new IllegalStateException()
  })

  producer.subscribe(new Subscriber[Out] {
    private[this] var sub: Subscription = _

    override def onSubscribe(s: Subscription): Unit = {
      sub = s
      connectionClosed.future.onComplete { _ =&gt;
        println(&quot;Cancelling connection&quot;)
        sub.cancel()
      }
      sub.request(1)
    }

    override def onNext(t: Out): Unit = {
      publisherResponsePromise.success(t)
      sub.request(1)
      awaitCallLatch.release()
    }

    override def onError(t: Throwable): Unit = {
      publisherResponsePromise.failure(t)
      // TODO: signal future requests that stream ended in error
      awaitCallLatch.release()
    }

    override def onComplete(): Unit = ()
  })

  private val cancelIO: IO[Unit] =
    IO {
      connectionClosed.success(())
      ()
    }

  @nowarn(&quot;cat=deprecation&quot;)
  def pushEvent(in: In): IO[Out] =
    IO.fromFuture(IO {
      awaitCallLatch.acquire().flatMap {
        _ =&gt;
          val promise = Promise[Out]()
          publisherResponsePromise = promise

          val backpressurePermission =
            requested.transformAndExtract {
              case Right(n) =&gt;
                if (n &gt; 1)
                  (Future.successful(()), Right(n - 1))
                else
                  (Future.successful(()), Left(Promise()))

              case current @ Left(promise) =&gt;
                (promise.future, current)
            }

          backpressurePermission.flatMap { _ =&gt;
            subscriber.onNext(in)
            promise.future
          }
      }
    })
}

object FlowToEffect {
  def apply[I, O](
    f: IO[Processor[I, O]]
  )(implicit
    cs: ContextShift[IO],
    ec: ExecutionContext
  ): Resource[IO, FlowToEffect[I, O]] = {
    Resource(f.map { processor =&gt;
      val ref = new FlowToEffect(processor)
      (ref, ref.cancelIO)
    })
  }

  def apply[I, O, Mat](
    flow: Flow[I, O, Mat]
  )(implicit
    cs: ContextShift[IO],
    m: Materializer,
    ec: ExecutionContext
  ): Resource[IO, FlowToEffect[I, O]] = {
    val res = Resource.liftF(IO {
      flow.toProcessor.run()
    })
    res.flatMap(proc =&gt; apply(IO.pure(proc)))
  }

  def main(args: Array[String]): Unit = {
    import ExecutionContext.Implicits.global
    implicit val as = ActorSystem(&quot;test&quot;)
    implicit val cs = IO.contextShift(global)

    val flow = Flow.fromFunction[Int, String] { int =&gt;
      show&quot;Received number: $int&quot;
    }

    val (res, cancelRes) = FlowToEffect(flow).allocated.unsafeRunSync()
    try {
      val f1 = res.pushEvent(1).unsafeToFuture()
      val f2 = res.pushEvent(2).unsafeToFuture()
      val f3 = res.pushEvent(3).unsafeToFuture()

      val r1 = Await.result(f1, Duration.Inf)
      println(show&quot;Received: $r1&quot;)
      val r2 = Await.result(f2, Duration.Inf)
      println(show&quot;Received: $r2&quot;)
      val r3 = Await.result(f3, Duration.Inf)
      println(show&quot;Received: $r3&quot;)
    } finally {
      cancelRes.unsafeRunSync()
      Await.result(as.terminate(), Duration.Inf)
      ()
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/09/25/flow-processor-to-effect/?pk_campaign=rss&quot;&gt;Scala Snippet: Flow/Processor to Effect&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 25 Sep 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 15:56:30 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 15:56:30 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/09/25/flow-processor-to-effect/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/09/25/flow-processor-to-effect/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Akka</category>
  <category>Cats Effect</category>
  <category>Reactive Streams</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Privilege</title>
  <description>Today it’s my 38ᵗʰ birthday. I was born into privilege. Other people aren’t as lucky.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2020/09/10/privilege/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/fi-miu.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;800&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;My son ❤️&lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Today it&apos;s my 38ᵗʰ birthday. I was born into privilege. Other people aren&apos;t as lucky.
&lt;/p&gt;

&lt;p&gt;I’m privileged to have a wonderful wife and son, to have a family.&lt;/p&gt;

&lt;p&gt;I’m privileged that I’m middle-class, that I have a comfortable and stable job, that I have more job security during a crisis; I’m privileged that my worries for tomorrow are superficial; I’m lucky not to have debt.&lt;/p&gt;

&lt;p&gt;I’m privileged to have found my vocation; to have a profession that I would practice even if I’d win the lottery tomorrow.&lt;/p&gt;

&lt;p&gt;I’m privileged to have enough to eat and enjoy anything I’d like, such as cooking with extra-virgin olive oil and Irish grass-fed butter. Privileged to eat turkey, pork, bream, or salmon on every meal; to have whatever dessert I want, and fresh fruits, even when out of season and expensive. I’m privileged to eat delicious home-cooked meals every day.&lt;/p&gt;

&lt;p&gt;I’m privileged to afford to go on vacation, and that in this Covid-19 pandemic, my biggest problem was that I got bored while working from home and that I’ve got unspent vacation days left.&lt;/p&gt;

&lt;p&gt;I’m privileged to have gone to school, attending the Romanian public school system, which for all its problems, it’s extraordinary. We can only see how an incredible privilege this is when looking at the issues faced by poor children in Romanian villages or the US. And I have no life long debt from that education.&lt;/p&gt;

&lt;p&gt;I’m privileged to be a European heterosexual white male, born into an official religion. Everywhere I go, all doors are open for me. I’m not judged for where I was born. I don’t have have to keep the receipt when going to the store to prove that I haven’t stolen anything. If I am rejected, I’m not dismissed because of my skin color, sexual orientation, being a Jew, or a woman.&lt;/p&gt;

&lt;p&gt;I’m privileged to wear a size M or L for my tee-shirt. Even though I tend to get fat, I gravitate between overweight and XL, but no more than that. I’m privileged not to be “morbidly obese” and couldn’t get blamed for having a flaw of character because of my body constitution. I’m not condemned for gluttony, which is what society does against fat people.&lt;/p&gt;

&lt;p&gt;I’m privileged to be healthy. But even if I had a problem, I have access to a public healthcare system, which has its issues, but it’s available. I wouldn’t have to sell my apartment to pay for my medical bills. As a middle-class white male (with money for tips and an attitude), I am prioritized. And if I’m not in the mood for public institutions, for staying in lines, I can always go to that private clinic that I’m subscribed to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I was born in privilege. Other people aren’t as lucky.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m not writing this to feel good, or grateful for what I have, due to other people being less fortunate, even though that’s a thing. It’s essential to be mindful that many of us have a social privilege that placed us at the front of the pack, which gave us an advantage. That as much as we’d like to believe that we’ve made it due to hard work, that opportunities at birth are equal, that’s not true. And this is unfair, it’s unjust.&lt;/p&gt;

&lt;p&gt;We work hard for what we have, for sure. But in our society, hard work isn’t everything. And the privilege we’re born into matters more.&lt;/p&gt;

&lt;p&gt;Systemic racism, misogyny, antisemitism, fatphobia, xenophobia—these are issues even in 2020. And when people end up hating other human beings, based on class or category, most often than not, it is privilege they are protecting, not their hard work.&lt;/p&gt;

&lt;p&gt;My son is and will be privileged. I’m glad that he is because he won’t be discriminated against. It’s not shameful to be born into privilege, but it is dumb luck.&lt;/p&gt;

&lt;p&gt;Therefore I’m raising my son not to hate or discriminate against other people based on social position, race, ethnicity, religion, body size, sex, or sexual orientation. It’s the least I could do. And you should too.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/09/10/privilege/?pk_campaign=rss&quot;&gt;Privilege&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 10 Sep 2020 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2020/09/10/privilege/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/09/10/privilege/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Personal</category>
  </item>


<item>
  <title>Scala Snippet: Safe Passwords</title>
  <description>For security, it’s not a good practice to keep sensitive data in RAM indefinitely.</description>
  <content:encoded>&lt;p&gt;See: &lt;a href=&quot;https://books.nowsecure.com/secure-mobile-development/en/coding-practices/securely-store-sensitive-data-in-ram.html&quot;&gt;Securely Store Sensitive Data in RAM&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.{ Resource, Sync }
import java.util.ConcurrentModificationException
import java.util.concurrent.atomic.AtomicBoolean

final case class PasswordValue(value: String) {
  override def toString = &quot;PasswordValue(****)&quot;
}

final class SafePassword private (chars: Array[Char]) {
  private[this] val lock = new AtomicBoolean(false)
  private[this] var isAvailable = true

  def read[F[_]](implicit F: Sync[F]): Resource[F, PasswordValue] =
    Resource[F, PasswordValue](F.suspend {
      unsafeAcquire() match {
        case Right(()) =&gt;
          val cancel = F.delay(lock.set(false))
          F.pure((PasswordValue(new String(chars)), cancel))
        case Left(error) =&gt;
          F.raiseError(error)
      }
    })

  def onceThenNullify[F[_]](implicit F: Sync[F]): Resource[F, PasswordValue] =
    read.flatMap { value =&gt;
      Resource(F.pure((value, F.delay(unsafeNullify()))))
    }

  private[this] def unsafeNullify(): Unit = {
    if (isAvailable) {
      isAvailable = false
      for (i &lt;- chars.indices) {
        chars(i) = 0
      }
    }
  }

  private[this] def unsafeAcquire(): Either[Throwable, Unit] =
    if (!lock.compareAndSet(false, true)) {
      Left(
        new ConcurrentModificationException(
          &quot;Cannot use this password from concurrent tasks&quot;
        )
      )
    } else if (!isAvailable) {
      lock.set(false)
      Left(
        new IllegalStateException(
          &quot;Password was nullified already&quot;
        )
      )
    } else {
      Right(())
    }
}

object SafePassword {
  def apply[F[_]](value: String)(implicit F: Sync[F]): F[SafePassword] =
    F.delay(unsafe(value))

  def unsafe(value: String): SafePassword =
    new SafePassword(value.toCharArray)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;SafePassword[IO](&quot;74kDc2J%dd2&amp;&quot;).flatMap { pass =&gt;
  pass.onceThenNullify[IO].use { p =&gt;
    IO {
      println(p.value)
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/08/27/safe-password.scala/?pk_campaign=rss&quot;&gt;Scala Snippet: Safe Passwords&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 27 Aug 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 13:45:46 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 13:45:46 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/08/27/safe-password.scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/08/27/safe-password.scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>JVM</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Sample Error Hierarchy in Scala</title>
  <description>Mimicking the HTTP error codes.</description>
  <content:encoded>&lt;figure&gt;
  &lt;a href=&quot;https://alexn.org/assets/media/snippets/error-hierarchy.svg&quot; target=&quot;_blank&quot;&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/snippets/error-hierarchy.svg&quot; alt=&quot;Error hierarchy graph&quot; title=&quot;Error hierarchy graph&quot; style=&quot;max-width:100%;height:auto;&quot; width=&quot;1095&quot; height=&quot;188&quot;&gt;
  &lt;/a&gt;
&lt;/figure&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed abstract class KnownException(message: String, cause: Throwable)
  extends RuntimeException(message, cause)

sealed abstract class InputException(message: String, cause: Throwable)
  extends KnownException(message, cause)

object InputException {
  final case class Validation(message: String, cause: Throwable)
    extends InputException(message, cause)
    with ExceptionCaseClassEquality

  final case class BadInput(message: String, cause: Throwable)
    extends InputException(message, cause)
    with ExceptionCaseClassEquality

  final case class Forbidden(message: String, cause: Throwable)
    extends InputException(message, cause)
    with ExceptionCaseClassEquality

  final case class NotFound(message: String, cause: Throwable)
    extends InputException(message, cause)
    with ExceptionCaseClassEquality

  final case class Conflict(message: String, cause: Throwable)
    extends InputException(message, cause)
    with ExceptionCaseClassEquality
}

sealed abstract class OutputException(message: String, cause: Throwable)
  extends KnownException(message, cause)

object OutputException {
  final case class Timeout(message: String, cause: Throwable)
    extends OutputException(message, cause)
    with ExceptionCaseClassEquality

  final case class TooManyRequests(message: String, cause: Throwable)
    extends OutputException(message, cause)
    with ExceptionCaseClassEquality

  final case class ResourceUnavailable(message: String, cause: Throwable)
    extends OutputException(message, cause)
    with ExceptionCaseClassEquality

  final case class Unknown(message: String, cause: Throwable)
    extends OutputException(message, cause)
    with ExceptionCaseClassEquality
}

trait ExceptionCaseClassEquality { self: Throwable with Product =&gt;
  override def equals(other: Any): Boolean = {
    other match {
      case refTh: Throwable =&gt;
        refTh match {
          case refProd: Product =&gt;
            productIterator.toSeq.equals(refProd.productIterator.toSeq) &amp;&amp;
              getStackTrace.toSeq.equals(refTh.getStackTrace.toSeq)
          case _ =&gt;
            false
        }
      case _ =&gt;
        false
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/08/14/error-hierarchy.scala/?pk_campaign=rss&quot;&gt;Sample Error Hierarchy in Scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 14 Aug 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 13:51:57 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 13:51:57 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/08/14/error-hierarchy.scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/08/14/error-hierarchy.scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Snippet: turn on JVM debugging in sbt</title>
  <description>Remote debugging can be used to debug externally executed programs, useful to activate in sbt in order to keep using it while debugging with your favorite IDE.</description>
  <content:encoded>&lt;p&gt;Remote debugging can be used to debug externally executed programs, useful to activate in &lt;code&gt;sbt&lt;/code&gt; in order to keep using it while debugging with your favorite IDE. See for example &lt;a href=&quot;https://www.jetbrains.com/help/idea/tutorial-remote-debug.html&quot;&gt;IntelliJ IDEA’s documentation&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; there is now a &lt;code&gt;--jvm-debug &lt;port&gt;&lt;/code&gt; parameter to the &lt;code&gt;sbt&lt;/code&gt; executable …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sbt --jvm-debug 5005
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;OLD WAY:&lt;/strong&gt; — if the above is not suitable, you can do a manual config like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;fork := true

javaOptions ++= {
  val Digits = &quot;^(\\d+)$&quot;.r
  sys.env.get(&quot;JVM_DEBUG&quot;) match {
    case Some(&quot;true&quot;) =&gt;
      Seq(&quot;-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005&quot;)
    case Some(Digits(port)) =&gt;
      Seq(s&quot;-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=$port&quot;)
    case _ =&gt;
      Seq.empty
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then set a &lt;code&gt;JVM_DEBUG&lt;/code&gt; environment variable, before executing &lt;code&gt;sbt&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;JVM_DEBUG=5005 sbt
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/08/13/sbt-fork-debug.sbt/?pk_campaign=rss&quot;&gt;Snippet: turn on JVM debugging in sbt&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 13 Aug 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 14:00:47 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 14:00:47 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/08/13/sbt-fork-debug.sbt/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/08/13/sbt-fork-debug.sbt/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>sbt</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>TypeScript Sample: Flow Sensitive Typing</title>
  <description>Demonstrating Typescript’s untagged union types.</description>
  <content:encoded>&lt;p&gt;Demonstrating Typescript’s untagged union types:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;type Left&lt;L&gt; = {
  either: &quot;left&quot;
  value: L
}

type Right&lt;R&gt; = {
  either: &quot;right&quot;,
  value: R
}

type Either&lt;L, R&gt; = Left&lt;L&gt; | Right&lt;R&gt;

function left&lt;L, R=never&gt;(value: L): Either&lt;L, R&gt; {
  return { either: &quot;left&quot;, value }
}

function right&lt;R, L=never&gt;(value: R): Either&lt;L, R&gt; {
  return { either: &quot;right&quot;, value }
}

// ----
const value = left&lt;string, number&gt;(&quot;Hello!&quot;)

// Flow-sensitive typing in action
if (value.either == &quot;left&quot;) {
  const l: string = value.value
  console.log(&quot;string: &quot;, l)
} else {
  const r: number = value.value
  console.log(&quot;number&quot;, r)
}
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/08/11/flow-sensitive-typing.ts/?pk_campaign=rss&quot;&gt;TypeScript Sample: Flow Sensitive Typing&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 11 Aug 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 14:02:35 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 14:02:35 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/08/11/flow-sensitive-typing.ts/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/08/11/flow-sensitive-typing.ts/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>TypeScript</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Retry Failing Tasks with Cats and Scala</title>
  <description>Retry actions ending in failure via simple functions and Typelevel Cats type-classes.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2020/08/03/on-error-retry-loop/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/snippets/on-error-retry-loop.png?202603060940&quot; alt=&quot;&quot; width=&quot;1400&quot; height=&quot;700&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  In the face of errors, we could interrupt what we are doing and log the incident for debugging purposes. Some errors are temporary, for example, network connection errors, the web service becoming unavailable for whatever reason, etc. It might be appropriate to do one or multiple retries, as it might not be acceptable to drop a valuable transaction on the floor.
&lt;/p&gt;

&lt;p&gt;Libraries with DSLs for specifying complex retry logic exist, see &lt;strong&gt;&lt;a href=&quot;https://github.com/cb372/cats-retry&quot;&gt;cats-retry&lt;/a&gt;&lt;/strong&gt;. In this article, I am not talking about such libraries because implementing your functions is fun, educational, and because you might not need a library where a simple function could do just fine.&lt;/p&gt;

&lt;p&gt;Here’s how …&lt;/p&gt;

&lt;h2 id=&quot;task-example&quot;&gt;Task Example&lt;/h2&gt;

&lt;p&gt;We are going to use &lt;a href=&quot;https://typelevel.org/cats-effect/datatypes/io.html&quot;&gt;cats.effect.IO&lt;/a&gt; for exemplification, but this can work just as well with the &lt;a href=&quot;https://monix.io/docs/3x/eval/task.html&quot;&gt;Monix Task&lt;/a&gt;, &lt;a href=&quot;https://monix.io/docs/3x/eval/coeval.html&quot;&gt;Monix Coeval&lt;/a&gt; or any data type that implements the necessary &lt;a href=&quot;https://typelevel.org/cats/&quot;&gt;Typelevel Cats&lt;/a&gt; and &lt;a href=&quot;https://typelevel.org/cats-effect/&quot;&gt;Cats Effect&lt;/a&gt; type classes.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.IO
import java.io._

// Not very motivating example, but let&apos;s go with it
def readTextFromFile(file: File, charset: String): IO[String] =
  IO {
    val in = new BufferedReader(
      new InputStreamReader(
        new FileInputStream(file), charset
      ))

    val builder = new StringBuilder()
    var line: String = null
    do {
      line = in.readLine()
      if (line != null)
        builder.append(line).append(&quot;\n&quot;)
    } while (line != null)

    builder.toString
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This operation is doing I/O, the file we are looking for could be missing, but only temporarily, or we might have an IOPS capacity problem. In some cases, we might want to keep retrying the task.&lt;/p&gt;

&lt;h2 id=&quot;naive-implementation&quot;&gt;Naive Implementation&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/typelevel/cats/blob/v2.1.1/core/src/main/scala/cats/ApplicativeError.scala&quot;&gt;ApplicativeError&lt;/a&gt; type class from Cats defines these functions:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait ApplicativeError[F[_], E] extends Applicative[F] {
  // ...
  def handleErrorWith[A](fa: F[A])(f: E =&gt; F[A]): F[A]

  def raiseError[A](e: E): F[A]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;handleErrorWith&lt;/code&gt; function works like a &lt;code&gt;flatMap&lt;/code&gt; operation, but for errors (the equivalent of Java/Scala’s &lt;code&gt;catch&lt;/code&gt; statement). And the &lt;code&gt;raiseError&lt;/code&gt; function lifts an &lt;code&gt;E&lt;/code&gt; error into the &lt;code&gt;F[A]&lt;/code&gt; context (the equivalent of Java’s and Scala’s &lt;code&gt;throw&lt;/code&gt; for exceptions).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.implicits._
import cats.{ApplicativeError, Defer}

object OnErrorRetry {
  // WARN: not OK, because we don&apos;t have an end condition!
  def adInfinitum[F[_], A](fa: F[A])
    (implicit F: ApplicativeError[F, Throwable], D: Defer[F]): F[A] = {

    fa.handleErrorWith { _ =&gt;
      // Recursive call describing infinite loop
      D.defer(loop(fa))
    }
  }
}

//...
OnErrorRetry.adInfinitum(readTextFromFile(file))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the usage of &lt;code&gt;ApplicativeError&lt;/code&gt; and &lt;code&gt;Defer&lt;/code&gt; type classes, added as restrictions for our &lt;code&gt;F[_]&lt;/code&gt;.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;b&gt;&lt;em&gt;NOTE 1:&lt;/em&gt;&lt;/b&gt; There’s a caveat with the way we’re using &lt;code&gt;handleErrorWith&lt;/code&gt; in such recursive loops. The type we use might not have a &lt;em&gt;memory-safe&lt;/em&gt; implementation, which is always a concern in Scala, due to the JVM lacking TCO. The data types that can throw errors, errors based on runtime conditions that can be retried, usually implement a memory-safe &lt;code&gt;handleErrorWith&lt;/code&gt;. Still, it’s better if we can ensure this via type restrictions.
  &lt;br&gt;&lt;br&gt;
  We use the &lt;a href=&quot;https://typelevel.org/cats/api/cats/Defer.html&quot;&gt;Defer&lt;/a&gt; type class to force usage of memory-safe (trampolined) implementations, although its laws are probably not strong enough. Still, this restriction will do just fine in practice. The alternative would have been to not put a restriction for memory safety, or to use &lt;a href=&quot;https://typelevel.org/cats-effect/typeclasses/sync.html&quot;&gt;Cats Effect’s Sync&lt;/a&gt;, but this type class is too restricted, to the point that the signature becomes opaque, as it might as well launch missiles.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;b&gt;&lt;em&gt;NOTE 2:&lt;/em&gt;&lt;/b&gt; We have specialized our &lt;code&gt;E&lt;/code&gt; error type, as seen in &lt;code&gt;ApplicativeError[F, E]&lt;/code&gt;, to &lt;code&gt;Throwable&lt;/code&gt;.
  &lt;br&gt;&lt;br&gt;
  There’s no reason to specialize &lt;code&gt;E&lt;/code&gt;, except that the Scala compiler ends up having issues inferring the type involved. There are ways to describe a nice API with a generic &lt;code&gt;E&lt;/code&gt; and keep the Scala compiler happy, but that’s not the tutorial’s purpose.
&lt;/p&gt;

&lt;p&gt;This sample has several problems that we’ll have to address:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;no end condition&lt;/li&gt;
  &lt;li&gt;no filtering of errors, since not all errors are recoverable&lt;/li&gt;
  &lt;li&gt;no protections, like “&lt;em&gt;exponential backoff&lt;/em&gt;”&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;filtering-and-end-condition&quot;&gt;Filtering and End Condition&lt;/h2&gt;

&lt;p&gt;We must only retry the task in situations in which it can be retried. For example if the task throws a &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/nio/charset/CharacterCodingException.html&quot; target=&quot;_blank&quot;&gt;CharacterCodingException&lt;/a&gt;, that’s not a task that can be retried, that’s a bug. It’s not always clear when the task can be retried or not, but we can try our best.&lt;/p&gt;

&lt;p&gt;And we want to retry, but not forever. So there has to be an end condition in that loop.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;/**
  * Signaling desired outcomes via Boolean is very confusing,
  * having our own ADT for this is better.
  */
sealed trait RetryOutcome

object RetryOutcome {
  case object Next extends RetryOutcome
  case object Raise extends RetryOutcome
}

/** Module grouping our retry helpers. */
object OnErrorRetry {

  def withAtMost[F[_], A](fa: F[A], maxRetries: Int)
    (p: E =&gt; RetryOutcome)
    (implicit F: ApplicativeError[F, Throwable], D: Defer[F]): F[A] = {

    fa.handleErrorWith { error =&gt;
      if (maxRetries &gt; 0)
        p(error) match {
          case RetryOutcome.Next =&gt;
            // Recursive call
            D.defer(withAtMost(fa, maxRetries - 1)(p))
          case RetryOutcome.Raise =&gt;
            // Cannot recover from error
            F.raiseError(error)
        }
      else
        // Maximum retries reached, triggering error
        F.raiseError(error)
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;OnErrorRetry.withAtMost(readTextFromFile(file), maxRetries = 10) {
  case _: CharacterCodingException =&gt;
    RetryOutcome.Raise
  case _ =&gt;
    RetryOutcome.Next
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;building-a-generic-retry-loop&quot;&gt;Building a Generic Retry Loop&lt;/h2&gt;

&lt;p&gt;Inspired by Monix’s &lt;a href=&quot;https://github.com/monix/monix/pull/507&quot;&gt;onErrorRestartLoop&lt;/a&gt;, we can describe this function in a generic fashion:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object OnErrorRetry {
  /**
    * Saves us from describing recursive functions that accumulate state.
    */
  def loop[F[_], A, S](
    fa: F[A],
    initial: S
  )(
    f: (Throwable, S, S =&gt; F[A]) =&gt; F[A]
  )(implicit F: ApplicativeError[F, Throwable], D: Defer[F]): F[A] = {
    fa.handleErrorWith { err =&gt;
      f(err, initial, state =&gt; D.defer(loop(fa, state)(f)))
    }
  }

  def withAtMost[F[_], A](fa: F[A], maxRetries: Int)(
    p: Throwable =&gt; RetryOutcome
  )(implicit
    F: ApplicativeError[F, Throwable],
    D: Defer[F]
  ): F[A] = {
    loop(fa, maxRetries) { (error, retriesLeft, retry) =&gt;
      if (retriesLeft &gt; 0)
        p(error) match {
          case RetryOutcome.Next =&gt;
            retry(retriesLeft - 1)
          case RetryOutcome.Raise =&gt;
            // Cannot recover from error
            F.raiseError(error)
        }
      else
        // Maximum retries reached, triggering error
        F.raiseError(error)
    }
  }
}

// Retrying 10 times at most
OnErrorRetry.withAtMost(readTextFromFile(file), maxRetries = 10) {
  case _: CharacterCodingException =&gt;
    RetryOutcome.Raise
  case _ =&gt;
    RetryOutcome.Next
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;exponential-backoff&quot;&gt;Exponential Backoff&lt;/h2&gt;

&lt;p&gt;We might also want to introduce &lt;a href=&quot;https://en.wikipedia.org/wiki/Exponential_backoff&quot;&gt;exponential backoff&lt;/a&gt; because if the resource is busy, the last thing we want to do is to overwhelm it with retry requests. And we are are going to use &lt;a href=&quot;https://typelevel.org/cats-effect/datatypes/timer.html&quot;&gt;Timer&lt;/a&gt; for introducing delays.&lt;/p&gt;

&lt;p&gt;At this point, the state and the configuration are more complicated, so let’s introduce a reusable data structure too, that should be self-explanatory:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent.duration._

/**
  * Configuration for retry logic, could be read from a config file, via
  * something like [[https://github.com/pureconfig/pureconfig PureConfig]].
  */
final case class RetryConfig(
  maxRetries: Int,
  initialDelay: FiniteDuration,
  maxDelay: FiniteDuration,
  backoffFactor: Double,
  private val evolvedDelay: Option[FiniteDuration] = None,
) {
  def canRetry: Boolean = maxRetries &gt; 0

  def delay: FiniteDuration =
    evolvedDelay.getOrElse(initialDelay)

  def evolve: RetryConfig =
    copy(
      maxRetries = math.max(maxRetries - 1, 0),
      evolvedDelay = Some {
        val nextDelay = evolvedDelay.getOrElse(initialDelay) * backoffFactor
        maxDelay.min(nextDelay) match {
          case ref: FiniteDuration =&gt; ref
          case _: Duration.Infinite =&gt; maxDelay
        }
      }
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, we can do this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object OnErrorRetry {
  // ...
  def withBackoff[F[_], A](fa: F[A], config: RetryConfig)(
    p: Throwable =&gt; F[RetryOutcome]
  )(implicit
    F: MonadError[F, Throwable],
    D: Defer[F],
    timer: Timer[F]
  ): F[A] = {
    OnErrorRetry.loop(fa, config) { (error, state, retry) =&gt;
      if (state.canRetry)
        p(error).flatMap {
          case RetryOutcome.Next =&gt;
            timer.sleep(state.delay) *&gt; retry(state.evolve)
          case RetryOutcome.Raise =&gt;
            // Cannot recover from error
            F.raiseError(error)
        }
      else
        // No retries left
        F.raiseError(error)
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In our predicate we take an &lt;code&gt;F[RetryOutcome]&lt;/code&gt; instead of a &lt;code&gt;RetryOutcome&lt;/code&gt;. That’s because we might want to trigger additional side effects, like logging.&lt;/p&gt;

&lt;p&gt;So to build our final sample, let’s introduce a dependency on &lt;a href=&quot;https://github.com/lightbend/config&quot;&gt;typesafe-config&lt;/a&gt; in &lt;code&gt;build.sbt&lt;/code&gt;, which you probably have anyway:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;libraryDependencies += &quot;com.typesafe&quot; % &quot;config&quot; % &quot;1.4.0&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object Playground extends LazyLogging with IOApp {
  // Motivating example
  def readTextFromFile(file: File, charset: String): IO[String] = ???

  override def run(args: List[String]): IO[ExitCode] = {
    val config = RetryConfig(
      maxRetries = 10,
      initialDelay = 10.millis,
      maxDelay = 2.seconds,
      backoffFactor = 1.5
    )
    val task = IO.suspend {
      val path = args.headOption.getOrElse(
        throw new IllegalArgumentException(&quot;File path expected in main&apos;s args&quot;)
      )
      readTextFromFile(new File(path), &quot;UTF-8&quot;)
    }
    val taskWithRetries = OnErrorRetry.withBackoff(task, config) {
      case _: CharacterCodingException | _: IllegalArgumentException =&gt;
        IO.pure(RetryOutcome.Raise)
      case e =&gt;
        IO(logger.warn(&quot;Unexpected error, retrying&quot;, e))
          .as(RetryOutcome.Next)
    }
    for {
      t &lt;- taskWithRetries
      _ &lt;- IO(println(t))
    } yield ExitCode.Success
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enjoy~&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/08/03/on-error-retry-loop/?pk_campaign=rss&quot;&gt;Retry Failing Tasks with Cats and Scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 03 Aug 2020 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2020/08/03/on-error-retry-loop/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/08/03/on-error-retry-loop/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  </item>


<item>
  <title>Scala Snippet: Cats-Effect Resource to Reactive Streams</title>
  <description>Cats-Effect’s Resource can’t be converted directly into a Reactive Streams Publisher. Beware!</description>
  <content:encoded>&lt;p&gt;Cats-Effect’s Resource can’t be converted directly into a Reactive Streams Publisher. Beware!&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.Resource
import org.reactivestreams.Publisher
import scala.concurrent.Future

type Ack[F] = () =&gt; F[Unit]

// This leaks
def fromResource[F[_], A](res: Resource[F, A]): F[Publisher[A]]

// Explicit acknowledgement logic is required
def fromResource[F[_], A](res: Resource[F, A]): F[Publisher[(A, Ack[F])]]

//-------------

// Similarly for concrete resources, this leaks!
def fromFile(file: File): Publisher[InputStream]

// Explicit acknowledgement logic is required
def fromFile(file: File): Publisher[(InputStream, Ack[Future])]
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/07/30/from-resource-to-reactivestreams.scala/?pk_campaign=rss&quot;&gt;Scala Snippet: Cats-Effect Resource to Reactive Streams&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 30 Jul 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 14:13:37 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 14:13:37 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/07/30/from-resource-to-reactivestreams.scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/07/30/from-resource-to-reactivestreams.scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Akka</category>
  <category>Cats Effect</category>
  <category>Reactive Streams</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>ExecutionContext Must Be Stack-safe</title>
  <description>Sample demonstrating that directly executing runnables in your ExecutionContext (with no stack-safety) is a really bad idea.</description>
  <content:encoded>&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Demonstrating that directly executing runnables in your 
// ExecutionContext is a really bad idea

def trigger(cycles: Int): Future[Int] = {
  implicit val directEC =
    new ExecutionContext {
      def execute(r: Runnable) = r.run()
      def reportFailure(e: Throwable) = throw e
    }

  val p = Promise[Int]()
  val f = (0 until cycles).foldLeft(p.future)((f, _) =&gt; f.map(_ + 1))
  p.success(0)
  f
}

// Throws StackOverflowError
trigger(5000)
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/05/27/future-stack-overflow.scala/?pk_campaign=rss&quot;&gt;ExecutionContext Must Be Stack-safe&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 27 May 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 12:47:40 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 12:47:40 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/05/27/future-stack-overflow.scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/05/27/future-stack-overflow.scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Async</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Fatal Warnings and Linting in Scala</title>
  <description>Strengthen your code via -Xfatal-warnings, linting and piss off your colleagues with useful compiler errors.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2020/05/26/scala-fatal-warnings/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala-xfatal-warnings.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;600&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  The best practices are those enforced by the build tools, as part of the build process. Don’t annoy your colleagues in code reviews; let the build tools do that for you.
&lt;/p&gt;

&lt;p&gt;The Scala compiler has multiple linting options available and emits some warnings out of the box that would be more useful as errors. Let’s see how we can rely on the Scala compiler to strengthen our code and piss off your colleagues with clean code requirements.&lt;/p&gt;

&lt;h2 id=&quot;best-practice-stop-ignoring-warnings&quot;&gt;Best Practice: Stop Ignoring Warnings!&lt;/h2&gt;

&lt;p&gt;Some of it might be noise; however, in that noise, some real gems might be missed, warnings that signal bugs. For example, the compiler can do exhaustiveness checks when pattern matching:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def size(list: List[_]): Int =
  list match {
    case _ :: rest =&gt; 1 + size(rest)
  }
// On line 2: warning: match may not be exhaustive.
//        It would fail on the following input: Nil
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s what happens next:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;size(List(1,2,3))
// scala.MatchError: List() (of class scala.collection.immutable.Nil$)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It shouldn’t be just a warning. Even if you’re diligent, this warning can get lost in a sea of other warnings, like it often does. And here we were lucky, because the runtime exception was triggered on the happy path, but our luck would eventually run out and end up with such exceptions in production.&lt;/p&gt;

&lt;h2 id=&quot;1-activate--xfatal-warnings&quot;&gt;1. Activate -Xfatal-warnings&lt;/h2&gt;

&lt;p&gt;To turn all compiler warnings into errors, you can activate &lt;code&gt;-Xfatal-warnings&lt;/code&gt;. In &lt;a href=&quot;https://www.scala-sbt.org/1.x/docs/Basic-Def.html&quot;&gt;build.sbt&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scalacOptions ++= Seq(
  &quot;-Xfatal-warnings&quot;,
  //...
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;NOTE:&lt;/strong&gt; it’s probably a good idea to exclude this from the &lt;code&gt;console&lt;/code&gt; configuration, see &lt;a href=&quot;#23-relax-the-console-configuration&quot;&gt;section 2.3&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;Now if we try out the code above, we get an error like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[error] .../Example.scala:10:5: match may not be exhaustive.
[error] It would fail on the following input: Nil
[error]     list match {
[error]     ^
[error] one error found
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Thus we can no longer ignore it.&lt;/p&gt;

&lt;h3 id=&quot;11-make-only-some-warnings-fatal-scala-213&quot;&gt;1.1. Make only some warnings fatal (Scala 2.13)&lt;/h3&gt;

&lt;p&gt;There’s a new &lt;code&gt;-Wconf&lt;/code&gt; option in Scala 2.13.2 (&lt;a href=&quot;https://github.com/scala/scala/pull/8373&quot;&gt;see PR&lt;/a&gt;). With it, we can still keep some warnings as warnings.&lt;/p&gt;

&lt;p&gt;Use-case: say you’re upgrading an Akka project. It’s going to have a ton of &lt;code&gt;@deprecated&lt;/code&gt; warnings that you may not want to fix right now, but you still want to keep the exhaustiveness checks as errors.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scalacOptions ++= Seq(
  // &quot;-Xfatal-warnings&quot;,
  &quot;-Wconf:cat=deprecation:ws,any:e&quot;,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What this does is to turn all warnings into errors, &lt;em&gt;except for deprecation&lt;/em&gt; messages, which are still left as warnings. To break it down:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code&gt;cat=deprecation&lt;/code&gt; refers to deprecation messages (classes/methods marked with &lt;code&gt;@deprecated&lt;/code&gt; being called) and &lt;code&gt;:ws&lt;/code&gt; says that for these warnings a “warning summary” should be shown&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;any:e&lt;/code&gt; says that for any other kind of warning, signal it via an error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run this in a terminal for more help:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;scalac -Wconf:help
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;2-activate-all-linting-options&quot;&gt;2. Activate All Linting Options&lt;/h2&gt;

&lt;p&gt;There are many useful compiler options that you could activate. You can find a (possibly non-complete) list on &lt;a href=&quot;https://docs.scala-lang.org/overviews/compiler-options/index.html&quot;&gt;docs.scala-lang.org&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;WARNING:&lt;/strong&gt; the compiler evolves and it&apos;s good to keep this list up to date (see next tip)!
&lt;/p&gt;

&lt;p&gt;For Scala 2.13 at the time of writing, here’s my list of &lt;code&gt;scalac&lt;/code&gt; options:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scalacOptions := Seq(
  // Feature options
  &quot;-encoding&quot;, &quot;utf-8&quot;,
  &quot;-explaintypes&quot;,
  &quot;-feature&quot;,
  &quot;-language:existentials&quot;,
  &quot;-language:experimental.macros&quot;,
  &quot;-language:higherKinds&quot;,
  &quot;-language:implicitConversions&quot;,
  &quot;-Ymacro-annotations&quot;,

  // Warnings as errors!
  &quot;-Xfatal-warnings&quot;,

  // Linting options
  &quot;-unchecked&quot;,
  &quot;-Xcheckinit&quot;,
  &quot;-Xlint:adapted-args&quot;,
  &quot;-Xlint:constant&quot;,
  &quot;-Xlint:delayedinit-select&quot;,
  &quot;-Xlint:deprecation&quot;,
  &quot;-Xlint:doc-detached&quot;,
  &quot;-Xlint:inaccessible&quot;,
  &quot;-Xlint:infer-any&quot;,
  &quot;-Xlint:missing-interpolator&quot;,
  &quot;-Xlint:nullary-override&quot;,
  &quot;-Xlint:nullary-unit&quot;,
  &quot;-Xlint:option-implicit&quot;,
  &quot;-Xlint:package-object-classes&quot;,
  &quot;-Xlint:poly-implicit-overload&quot;,
  &quot;-Xlint:private-shadow&quot;,
  &quot;-Xlint:stars-align&quot;,
  &quot;-Xlint:type-parameter-shadow&quot;,
  &quot;-Wdead-code&quot;,
  &quot;-Wextra-implicit&quot;,
  &quot;-Wnumeric-widen&quot;,
  &quot;-Wunused:implicits&quot;,
  &quot;-Wunused:imports&quot;,
  &quot;-Wunused:locals&quot;,
  &quot;-Wunused:params&quot;,
  &quot;-Wunused:patvars&quot;,
  &quot;-Wunused:privates&quot;,
  &quot;-Wvalue-discard&quot;,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are many useful options in there, from disallowing “adapted args”, detecting inaccessible code, inferred &lt;code&gt;Any&lt;/code&gt;, shadowing of values, to unused imports and params and others.&lt;/p&gt;

&lt;h3 id=&quot;21-use-the-sbt-tpolecat-plugin&quot;&gt;2.1. Use the sbt-tpolecat plugin&lt;/h3&gt;

&lt;p&gt;Keeping that list of compiler options up to date is exhausting, new useful options get added all the time, others are deprecated, and especially for libraries, you have to deal with multiple Scala versions in the same project.&lt;/p&gt;

&lt;p&gt;A better option is to include &lt;a href=&quot;https://github.com/DavidGregory084/sbt-tpolecat&quot;&gt;sbt-tpolecat&lt;/a&gt; in your project.&lt;/p&gt;

&lt;h3 id=&quot;22-exclude-annoying-linting-options&quot;&gt;2.2. Exclude annoying linting options&lt;/h3&gt;

&lt;p&gt;Some linting options can trigger false positives that are too annoying. It’s fine to remove them from your project or specific configurations (e.g. &lt;code&gt;Test&lt;/code&gt;, &lt;code&gt;Console&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For example, I do not like the &lt;code&gt;-Wunused:privates&lt;/code&gt; option because it triggers an annoying false positive when defining (unused) default values in &lt;code&gt;case class&lt;/code&gt; definitions.&lt;/p&gt;

&lt;p&gt;If using &lt;code&gt;sbt-tpolecat&lt;/code&gt;, as mentioned above, you can include something like this in your build definition:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scalacOptions in Compile ~= { options: Seq[String] =&gt;
  options.filterNot(
    Set(
      &quot;-Wunused:privates&quot;
    )
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;23-relax-the-console-configuration&quot;&gt;2.3. Relax the console configuration&lt;/h3&gt;

&lt;p&gt;When playing around in the console, it’s a good idea to deactivate &lt;code&gt;Xfatal-warnings&lt;/code&gt;, along with some of the more annoying warnings.&lt;/p&gt;

&lt;p&gt;You could &lt;a href=&quot;#21-use-the-sbt-tpolecat-plugin&quot;&gt;use sbt-tpolecat&lt;/a&gt;, which already does this automatically, or you could add this to &lt;code&gt;build.sbt&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val filterConsoleScalacOptions = { options: Seq[String] =&gt;
  options.filterNot(Set(
    &quot;-Xfatal-warnings&quot;,
    &quot;-Werror&quot;,
    &quot;-Wdead-code&quot;,
    &quot;-Wunused:imports&quot;,
    &quot;-Ywarn-unused:imports&quot;,
    &quot;-Ywarn-unused-import&quot;,
    &quot;-Ywarn-dead-code&quot;,
  ))
}

// ...
scalacOptions.in(Compile, console) ~= filterConsoleScalacOptions,
scalacOptions.in(Test, console) ~= filterConsoleScalacOptions
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Credit for this snippet: &lt;a href=&quot;https://github.com/DavidGregory084/sbt-tpolecat/blob/v0.1.11/src/main/scala/io/github/davidgregory084/TpolecatPlugin.scala#L109&quot;&gt;DavidGregory084/sbt-tpolecat&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;3-silence-some-warnings&quot;&gt;3. Silence some warnings&lt;/h2&gt;

&lt;p&gt;Sometimes you want to ignore a certain warning:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;maybe it’s a false positive&lt;/li&gt;
  &lt;li&gt;maybe you want something “unused”, as a placeholder&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;31-silencer-plugin-scala--213&quot;&gt;3.1. Silencer plugin (Scala &lt; 2.13)&lt;/h3&gt;

&lt;p&gt;You can use the &lt;a href=&quot;https://github.com/ghik/silencer&quot;&gt;ghik/silencer&lt;/a&gt; compiler plugin.&lt;/p&gt;

&lt;p&gt;For our sample above, if we want to silence that exhaustiveness check:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import com.github.ghik.silencer.silent

@silent(&quot;not.*?exhaustive&quot;)
def size(list: List[_]): Int =
  list match {
    case _ :: rest =&gt; 1 + size(rest)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The annotation accepts a regular expression that matches the warning being silenced.&lt;/p&gt;

&lt;p&gt;You can also use silence warnings for an entire folder, useful if you have auto-generated source files:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Alternative, if using the silencer plugin
scalacOptions ++= Seq(
  &quot;-P:silencer:pathFilters=.*[/]src_managed[/].*&quot;,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;32-using-nowarn-and--wconf-in-scala-2132&quot;&gt;3.2. Using @nowarn and -Wconf in Scala 2.13.2&lt;/h3&gt;

&lt;p&gt;Scala 2.13 has added the &lt;a href=&quot;https://github.com/scala/scala/pull/8373&quot;&gt;-Wconf flag for configurable warnings, @nowarn annotation for local suppression&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@nowarn&lt;/code&gt; can be more fine grained. We could do just like the above and silence with a pattern matcher:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.annotation.nowarn

@nowarn(&quot;msg=not.*?exhaustive&quot;)
def size(list: List[_]): Int =
  list match {
    case _ :: rest =&gt; 1 + size(rest)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But we can do better, because the actual error messages are brittle. We can silence based on the “category” of the warning. To find the category of a warning, we can (temporarily) enable extra verbosity in these messages via this compiler option in &lt;code&gt;build.sbt&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scalacOptions += &quot;-Wconf:any:warning-verbose&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That error will then look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[error] ... [other-match-analysis @ size] match may not be exhaustive.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The category is “&lt;code&gt;other-match-analysis&lt;/code&gt;”, so we can silence it like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;@nowarn(&quot;cat=other-match-analysis&quot;)
def size(list: List[_]): Int =
  list match {
    case _ :: rest =&gt; 1 + size(rest)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can also silence warnings for entire folders, via &lt;code&gt;-Wconf&lt;/code&gt;, useful if you have auto-generated files (e.g. from templates):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Turns off warnings for generated files and for templates
scalacOptions ++= Seq(
  &quot;-Wconf:src=src_managed/.*:silent&quot;,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;NOTE:&lt;/strong&gt; for &lt;strong&gt;forward compatibility&lt;/strong&gt; in older Scala versions, with the &lt;a href=&quot;#31-silencer-plugin-scala--213&quot;&gt;Silencer plugin&lt;/a&gt;, coupled with &lt;a href=&quot;https://github.com/scala/scala-library-compat&quot;&gt;scala-library-compat&lt;/a&gt;, you can use the new &lt;code&gt;@nowarn&lt;/code&gt; annotation with older Scala versions, however only the &lt;code&gt;@nowarn(&quot;msg=&lt;pattern&gt;&quot;)&lt;/code&gt; filtering is supported.
&lt;/p&gt;

&lt;h2 id=&quot;4-other-linters&quot;&gt;4. Other linters&lt;/h2&gt;

&lt;p&gt;You shouldn’t stop at Scala’s linting options. There are other sbt plugins available that can enforce certain best practices. Off the top of my head:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/scalacenter/scalafix&quot;&gt;Scalafix&lt;/a&gt; (this one can even rewrite the code for you 😉)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wartremover/wartremover&quot;&gt;Wartremover&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/sksamuel/scapegoat&quot;&gt;Scapegoat&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/scalastyle/scalastyle&quot;&gt;Scalastyle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these, you could ban &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;Any&lt;/code&gt; from your project, among other beneficial options.&lt;/p&gt;

&lt;p&gt;Any useful plugins that I’m missing?&lt;/p&gt;

&lt;h3 id=&quot;41-example-disable-tostring-conversions&quot;&gt;4.1. Example: disable .toString conversions&lt;/h3&gt;

&lt;p&gt;I recently disabled unsafe &lt;code&gt;.toString&lt;/code&gt; and &lt;code&gt;string + any&lt;/code&gt; conversions in our work project, with the purpose to not leak sensitive customer data in logs. To do this I enabled “&lt;em&gt;Wartremover&lt;/em&gt;” with this configuration in &lt;code&gt;build.sbt&lt;/code&gt;, and it is doing wonders:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;wartremoverErrors in (Compile, compile) := Seq(Wart.ToString, Wart.StringPlusAny),
wartremoverErrors in (Test, test) := Seq.empty,
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Coupled with a custom logger interface making use of its own type class, we can ensure that data structures containing protected data cannot leak by mistake via logging (either Logback or &lt;code&gt;println&lt;/code&gt; statements).&lt;/p&gt;

&lt;h2 id=&quot;final-words&quot;&gt;Final words&lt;/h2&gt;

&lt;p&gt;Scala is a static language, but sometimes it isn’t static or opinionated enough. The more you can prove about your code at compile-time, the less defects you can have at runtime.&lt;/p&gt;

&lt;p&gt;Now go forth and annoy your colleagues with actually useful compiler errors!&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/05/26/scala-fatal-warnings/?pk_campaign=rss&quot;&gt;Fatal Warnings and Linting in Scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 26 May 2020 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2020/05/26/scala-fatal-warnings/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/05/26/scala-fatal-warnings/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  </item>


<item>
  <title>Parallelizing Work via a JavaScript Semaphore</title>
  <description>Simple and very effective implementation of a Semaphore, used for easily parallelizing work in JavaScript/TypeScript.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2020/04/21/javascript-semaphore/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/async-semaphore-typescript.png?202603060940&quot; alt=&quot;&quot; width=&quot;1600&quot; height=&quot;800&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  This is a simple, but very effective implementation of a &lt;code&gt;Semaphore&lt;/code&gt;, used for easily parallelizing work in JavaScript/TypeScript. And while libraries for doing this might be available, quality varies and implementing your own stuff is fun.
&lt;/p&gt;

&lt;p&gt;Use-case: many times we iterate over a list of items and then do expensive network requests, like reading and writing to a database.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  Scala already has good implementations for doing this, no need to reinvent the wheel. See:
  &lt;a href=&quot;https://typelevel.org/cats-effect/concurrency/semaphore.html&quot;&gt;cats.effect.concurrent.Semaphore&lt;/a&gt; and &lt;a href=&quot;https://monix.io/api/3.1/monix/catnap/Semaphore.html&quot;&gt;monix.catnap.Semaphore&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;Simple example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// Dummy function
function saveToDatabase(item: number): Promise&lt;void&gt; {
 return new Promise(f =&gt; {
   if (item % 1000 === 0) { console.log(&quot;Progress: &quot;, item) }
   setTimeout(f, 100 /* millis */)
 })
}

// ...
for (let i = 0; i &lt; 100000; i++) {
  await saveToDatabase(i)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But this will be very slow, taking ~2.8 hours to finish.&lt;/p&gt;

&lt;p&gt;On the other hand, if we try a naive solution via &lt;code&gt;Promise.race&lt;/code&gt;, this can easily overwhelm your database and your script can crash with “&lt;em&gt;out of memory&lt;/em&gt;” or “&lt;em&gt;out of available file handles&lt;/em&gt;” errors. This is also not adequate in case producing those items in the first place is an expensive process (e.g. going over an async iterator). We can certainly hold 100,000 items in memory, but talk about 100 million or more and things start to fall apart.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;const promises: Promise&lt;void&gt;[] = []

for (let i = 0; i &lt; 100000; i++) {
  promises.push(saveToDatabase(i))
}

await Promise.race(promises)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let’s implement a simple data structure that can help us parallelize the workload, but only execute at most 100 tasks in parallel:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;const semaphore = new AsyncSemaphore(100)

for (let i = 0; i &lt; 100000; i++) {
  await semaphore.withLockRunAndForget(() =&gt; saveToDatabase(i))
}

await semaphore.awaitTerminate()
console.log(&quot;Done!&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Execution time will be ~1.7 minutes (compared with 2.8 hours for the first sample).&lt;/p&gt;

&lt;p&gt;The method &lt;code&gt;withLockRunAndForget&lt;/code&gt; only waits in case the semaphore doesn’t have handles available. And when the loop is finished, we need &lt;code&gt;awaitTerminate&lt;/code&gt; to wait for all active tasks to finish.&lt;/p&gt;

&lt;p&gt;Implementation, which can be copy/pasted in your project:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;export class AsyncSemaphore {
  private _available: number
  private _upcoming: Function[]
  private _heads: Function[]

  private _completeFn!: () =&gt; void
  private _completePr!: Promise&lt;void&gt;

  constructor(public readonly workersCount: number) {
    if (workersCount &lt;= 0) throw new Error(&quot;workersCount must be positive&quot;)
    this._available = workersCount
    this._upcoming = []
    this._heads = []
    this._refreshComplete()
  }

  async withLock&lt;A&gt;(f: () =&gt; Promise&lt;A&gt;): Promise&lt;A&gt; {
    await this._acquire()
    return this._execWithRelease(f)
  }

  async withLockRunAndForget&lt;A&gt;(f: () =&gt; Promise&lt;A&gt;): Promise&lt;void&gt; {
    await this._acquire()
    // Ignoring returned promise on purpose!
    this._execWithRelease(f)
  }

  async awaitTerminate(): Promise&lt;void&gt; {
    if (this._available &lt; this.workersCount) {
      return this._completePr
    }
  }

  private async _execWithRelease&lt;A&gt;(f: () =&gt; Promise&lt;A&gt;): Promise&lt;A&gt; {
    try {
      return await f()
    } finally {
      this._release()
    }
  }

  private _queue(): Function[] {
    if (!this._heads.length) {
      this._heads = this._upcoming.reverse()
      this._upcoming = []
    }
    return this._heads
  }

  private _acquire(): void | Promise&lt;void&gt; {
    if (this._available &gt; 0) {
      this._available -= 1
      return undefined
    } else {
      let fn: Function = () =&gt; {/***/}
      const p = new Promise&lt;void&gt;(ref =&gt; { fn = ref })
      this._upcoming.push(fn)
      return p
    }
  }

  private _release(): void {
    const queue = this._queue()
    if (queue.length) {
      const fn = queue.pop()
      if (fn) fn()
    } else {
      this._available += 1

      if (this._available &gt;= this.workersCount) {
        const fn = this._completeFn
        this._refreshComplete()
        fn()
      }
    }
  }

  private _refreshComplete(): void {
    let fn: () =&gt; void = () =&gt; {/***/}
    this._completePr = new Promise&lt;void&gt;(r =&gt; { fn = r })
    this._completeFn = fn
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enjoy~&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/04/21/javascript-semaphore/?pk_campaign=rss&quot;&gt;Parallelizing Work via a JavaScript Semaphore&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 21 Apr 2020 16:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2020/04/21/javascript-semaphore/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/04/21/javascript-semaphore/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Asynchrony</category>
  <category>Concurrency</category>
  <category>JavaScript</category>
  <category>TypeScript</category>
  </item>


<item>
  <title>Blog Updates</title>
  <description>Dusted off my website, with big plans ahead.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      
&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=RYmGT905Skc&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/RYmGT905Skc/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=RYmGT905Skc&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I love writing. I write long emails, long chat texts, long code comments. Some of my rants are epic. Sometimes I&apos;m amazed that my colleagues have the patience to read it all 🙂
&lt;/p&gt;

&lt;p&gt;Yet I’ve neglected my personal blog. This happens because &lt;a href=&quot;https://x.com/alexelcu&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; fulfilled my needs for shitposting and for code I ended up creating snippets as &lt;a href=&quot;https://gist.github.com/alexandru&quot; target=&quot;_blank&quot;&gt;Gists&lt;/a&gt;, many of which are private, meant for colleagues.&lt;/p&gt;

&lt;p&gt;No more. I dusted off my blog and will commence a regular posting schedule.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  This blog is about programming, but take note that I don’t do just functional programming, or just Scala. Today’s article is about &lt;a href=&quot;https://alexn.org/blog/2020/04/21/javascript-semaphore/&quot;&gt;imperative, Promise-driven JavaScript&lt;/a&gt;.
&lt;/p&gt;

&lt;h2 id=&quot;website-yak-shaving&quot;&gt;Website Yak Shaving&lt;/h2&gt;

&lt;p&gt;Like all professional software developers that want to write more, I started with yak shaving by updating my blog:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Migrated from &lt;a href=&quot;https://middlemanapp.com/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Middleman&lt;/a&gt; to &lt;a href=&quot;https://jekyllrb.com/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Jekyll&lt;/a&gt; for generating my static website&lt;/li&gt;
  &lt;li&gt;Changed the design from something homemade to a modified &lt;a href=&quot;https://github.com/brianmaierjr/long-haul&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;brianmaierjr/long-haul&lt;/a&gt;; design should be responsive on mobile phones&lt;/li&gt;
  &lt;li&gt;Disabled comments, replaced widget with an email address — if you want to talk with me about my articles, we can do so in private&lt;/li&gt;
  &lt;li&gt;Automatic thumbnails for Vimeo/YouTube videos, enabled for Twitter/Facebook cards; expect more videos soon&lt;/li&gt;
  &lt;li&gt;Integration of &lt;a href=&quot;https://www.mathjax.org/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;MathJax&lt;/a&gt; for math formulas&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=RYmGT905Skc&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/RYmGT905Skc/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=RYmGT905Skc&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;If you find anything broken, please let me know.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/04/21/blog-updates/?pk_campaign=rss&quot;&gt;Blog Updates&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 21 Apr 2020 10:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2020/04/21/blog-updates/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2020/04/21/blog-updates/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Blogging</category>
  <category>Personal</category>
  </item>


<item>
  <title>Python Snippet: Send Email via SMTP</title>
  <description>Python snippet for sending an email via SMTP.</description>
  <content:encoded>&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;#!/usr/bin/env python

import smtplib
import argparse

from datetime import datetime, timedelta
from email.message import EmailMessage

parser = argparse.ArgumentParser(description=&apos;Send email&apos;)
parser.add_argument(
  &apos;--smtp-host&apos;, dest=&apos;smtp_host&apos;,
  type=str, help=&quot;SMTP host and port&quot;, required=True)
parser.add_argument(
  &apos;--smtp-user&apos;, dest=&apos;smtp_user&apos;,
  type=str, help=&quot;SMTP user for login&quot;, required=True)
parser.add_argument(
  &apos;--smtp-pass&apos;, dest=&apos;smtp_pass&apos;,
  type=str, help=&quot;SMTP password for login&quot;, required=True)
parser.add_argument(
  &apos;--to&apos;, dest=&apos;to_address&apos;,
  type=str, help=&quot;TO address&quot;, required=True)
parser.add_argument(
  &apos;--from&apos;, dest=&apos;from_address&apos;,
  type=str, help=&quot;FROM address&quot;, required=True)
parser.add_argument(
  &apos;--title&apos;, dest=&apos;title&apos;,
  type=str, help=&quot;Mail title&quot;, required=True)
parser.add_argument(
  &apos;--body&apos;, dest=&apos;body&apos;,
  type=str, help=&quot;Mail body&quot;, required=True)

args = parser.parse_args()

msg = EmailMessage()
msg.set_content(args.body)

msg[&apos;Subject&apos;] = args.title
msg[&apos;From&apos;] = args.from_address
msg[&apos;To&apos;] = args.to_address

service = smtplib.SMTP_SSL(args.smtp_host)
# service.starttls()
service.login(args.smtp_user, args.smtp_pass)
service.send_message(msg)
service.close()
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/03/18/send-mail.py/?pk_campaign=rss&quot;&gt;Python Snippet: Send Email via SMTP&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 18 Mar 2020 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 12:33:25 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 12:33:25 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/03/18/send-mail.py/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/03/18/send-mail.py/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>CLI</category>
  <category>Python</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Shell Snippet: Encrypt Files with AES256</title>
  <description>Quickly encrypt a message or a file for sending to your colleagues over unsecure messengers (Slack, etc).</description>
  <content:encoded>&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;#!/usr/bin/env bash
#
# Quickly encrypt a message or a file for sending to
# your colleagues over unsecure messengers (Slack, etc)...
#
#     echo &quot;secret message&quot; | encrypt
#
# Or to encrypt a file:
#
#     encrypt ./path/to/file
#
# -----------------------------------------------------------------------------

FILEPATH=&quot;$1&quot;

if [ -z &quot;$FILEPATH&quot; ]; then
    BASE64=$(openssl enc -A -aes256 -base64 -md md5)

    echo
    echo \# Decrypt this message by running:
    echo \# ================================
    echo 
    echo echo \&quot;&quot;$BASE64&quot;\&quot; \| openssl enc -d -aes256 -base64 -md md5 -A
    echo 
    echo \# ================================    
    echo
elif [ -f &quot;$FILEPATH&quot; ]; then
    RPATH=$(realpath --relative-base=&quot;$HOME&quot; &quot;$FILEPATH&quot;)
    BASE64=$(openssl enc -A -aes256 -base64 -md md5 &lt; &quot;$FILEPATH&quot;)

    echo
    echo \# Decrypt this file by running:
    echo \# ================================
    echo 
    echo echo \&quot;&quot;$BASE64&quot;\&quot; \| openssl enc -d -aes256 -base64 -md md5 -A \&gt; \&quot;&quot;~/$RPATH&quot;\&quot;
    echo 
    echo \# ================================
    echo
else
    echo &gt;&amp;2
    echo &quot;ERROR - file not found: $FILEPATH&quot; &gt;&amp;2
    echo &gt;&amp;2
    exit 1
fi
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2020/02/18/encrypt.sh/?pk_campaign=rss&quot;&gt;Shell Snippet: Encrypt Files with AES256&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 18 Feb 2020 00:00:00 +0000</pubDate>
  <dc:modified>Tue, 17 Jan 2023 11:17:38 +0000</dc:modified>
  <atom:modified>Tue, 17 Jan 2023 11:17:38 +0000</atom:modified>
  <link>https://alexn.org/blog/2020/02/18/encrypt.sh/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2020/02/18/encrypt.sh/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>CLI</category>
  <category>Shell</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Haskell Snippet: Sierpinski Triangle</title>
  <description>A fun Haskell sample that draws a Sierpinski triangle via ASCII characters.</description>
  <content:encoded>&lt;pre&gt;&lt;code class=&quot;language-haskell&quot;&gt;#!/usr/bin/env stack
-- stack --resolver lts-14.14 script
import Data.Bits

main :: IO ()
main = mapM_ putStrLn lines
  where
    n = 32 :: Int
    line i =
      [ if i .&amp;. j /= 0 then &apos; &apos; else &apos;*&apos;
      | j &lt;- [0 .. n - 1] ]
    lines = [line i | i &lt;- [0 .. n - 1]]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;NOTE: the code isn’t mine, but I don’t remember from where I got it from.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2019/11/29/sierpinski.hs/?pk_campaign=rss&quot;&gt;Haskell Snippet: Sierpinski Triangle&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 29 Nov 2019 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 16:13:24 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 16:13:24 +0000</atom:modified>
  <link>https://alexn.org/blog/2019/11/29/sierpinski.hs/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2019/11/29/sierpinski.hs/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Haskell</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Regexp Replacement via Function in Java/Scala</title>
  <description>Replace in strings via regexp, with the replacement being calculated via a function.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2019/11/22/howto-regexp-replacement-via-function-java-scala/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala-replace-all-function.png?202603060940&quot; alt=&quot;&quot; width=&quot;1238&quot; height=&quot;530&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Article explains how to have fine grained control over replacements when using &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#replaceAll(java.lang.String,java.lang.String)&quot;&gt;String.replaceAll&lt;/a&gt; or similar in Java or Scala. The samples given are in Scala, but if you’re a Java user, the snippets can be easily translated without any issues.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  The following task should be obvious to accomplish in Scala / Java,
  yet I’ve lost 2 hours on it, because Java’s standard library is aged
  and arcane.
  &lt;br&gt;&lt;br&gt;
  Writing this article mostly for myself, to dump this somewhere 🙂
&lt;/p&gt;

&lt;p&gt;In Ruby if  you want to replace all occurrences of a string, via a regular expression, you can use &lt;a href=&quot;https://ruby-doc.org/core-2.6.5/String.html#method-i-gsub&quot;&gt;gsub&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;&quot;HelloWorld!&quot;.gsub(/(?&lt;=[a-z0-9_])[A-Z]/, &apos; \0&apos;)
#=&gt; Hello World!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This API is available in Scala/Java as well:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&quot;HelloWorld!&quot;.replaceAll(&quot;(?&lt;=[a-z0-9_])[A-Z]&quot;, &quot; $0&quot;)
// res: String = Hello World!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However Ruby goes one step further and accepts as the replacement a function block:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;&quot;HelloWorld!&quot;.gsub(/(?&lt;=[a-z0-9_])[A-Z]/) {|ch| ch.downcase }
#=&gt; Hello world!

&quot;Apollo 12&quot;.gsub(/\d+/) {|num| num.to_i + 1}
#=&gt; &quot;Apollo 13&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Java API exposed by &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html&quot;&gt;Pattern&lt;/a&gt; is a little awkward, so lets see how to do this in Scala / Java:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Index = Int
type MatchGroup = String

def replaceAll(regex: Pattern, input: String)
  (f: (Index, MatchGroup, List[MatchGroup]) =&gt; String): String = {

  val m = regex.matcher(input)
  val sb = new StringBuffer

  while (m.find()) {
    val groups = {
      val buffer = ListBuffer.empty[String]
      var i = 0
      while (i &lt; m.groupCount()) {
        buffer += m.group(i + 1)
        i += 1
      }
      buffer.toList
    }
    val replacement = f(m.start(), m.group(), groups)
    m.appendReplacement(sb, Matcher.quoteReplacement(replacement))
  }

  m.appendTail(sb)
  sb.toString
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What happens here is that &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Matcher.html&quot;&gt;Matcher&lt;/a&gt; allows you to replace all occurrences of a string with an iterator-like protocol by using:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Matcher.html#find()&quot;&gt;.find&lt;/a&gt;: for finding the next occurrence in a &lt;code&gt;while&lt;/code&gt; loop&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Matcher.html#appendReplacement(java.lang.StringBuilder,java.lang.String)&quot;&gt;.appendReplacement&lt;/a&gt;: which appends the remaining text after the discovery of the last match and the current one, plus the replacement that you’ve calculated for the current match
    &lt;ul&gt;
      &lt;li&gt;Note this requires the usage of &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Matcher.html#quoteReplacement(java.lang.String)&quot;&gt;quoteReplacement&lt;/a&gt;, because otherwise the logic in &lt;code&gt;appendReplacement&lt;/code&gt; will treat certain special chars like &lt;code&gt;\&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt;, so this specifies that you want the replacement to be verbatim&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Matcher.html#appendTail(java.lang.StringBuilder)&quot;&gt;.appendTail&lt;/a&gt;: to append to the final string whatever is left&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can now describe something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def camelCaseToSnakeCase(input: String): String =
  replaceAll(&quot;[A-Z](?=[a-z0-9_])&quot;.r.pattern, input) { (i, ch, _) =&gt;
    (if (i &gt; 0) &quot;_&quot; else &quot;&quot;) + ch.toLowerCase
  }

// And usage:
camelCaseToSnakeCase(&quot;RebuildSubscribersCounts&quot;)
//=&gt; res: String = rebuild_subscribers_counts
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def incrementNumbersIn(input: String): String =
  replaceAll(&quot;\\d+&quot;.r.pattern, input) { (_, num, _) =&gt;
    (num.toInt + 1).toString
  }

// And usage:
incrementNumbersIn(&quot;Apollo 12&quot;)
//=&gt; res: String = Apollo 13
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enjoy ~&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2019/11/22/howto-regexp-replacement-via-function-java-scala/?pk_campaign=rss&quot;&gt;Regexp Replacement via Function in Java/Scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 22 Nov 2019 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2019/11/22/howto-regexp-replacement-via-function-java-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2019/11/22/howto-regexp-replacement-via-function-java-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  <category>Ruby</category>
  </item>


<item>
  <title>Async Queue in TypeScript</title>
  <description>Production-ready, Promise-enabled async queue.</description>
  <content:encoded>&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;type Callback&lt;A&gt; = (a: A) =&gt; void;

/**
 * Delays stuff for ensuring fairness.
 */
export function yieldRunLoop(): Promise&lt;void&gt; {
  const fn: (cb: (() =&gt; void)) =&gt; void = typeof setImmediate !== &apos;undefined&apos;
    ? setImmediate
    : cb =&gt; setTimeout(cb, 0)
  return new Promise(fn)
}

/**
 * Async queue implementation
 */
export class Queue&lt;A&gt; {
  private readonly elements: A[] = []
  private readonly callbacks: ([Callback&lt;A&gt;, Callback&lt;Error&gt;])[] = []

  enqueue = async (a: A) =&gt; {
    const cbs = this.callbacks.shift()
    if (cbs) {
      // fairness + guards against stack overflows
      await yieldRunLoop()
      const [resolve, _] = cbs
      resolve(a)
    } else {
      this.elements.push(a)
    }
  }

  dequeue = async () =&gt; {
    if (this.elements.length &gt; 0) {
      return this.elements.shift() as A
    } else {
      let cb: [Callback&lt;A&gt;, Callback&lt;any&gt;] | undefined
      const p = new Promise&lt;A&gt;((resolve, reject) =&gt; { cb = [resolve, reject] })
      if (!cb) throw new Error(&quot;Promise constructor&quot;)
      this.callbacks.push(cb)
      return await p
    }
  }

  rejectAllActive = (e: Error) =&gt; {
    while (this.callbacks.length &gt; 0) {
      const cbs = this.callbacks.pop()
      if (!cbs) continue
      const [_, reject] = cbs
      reject(e)
    }
  }
}

/**
 * Consumer implementation.
 *
 * @param workers specifies the number of workers to start in parallel
 * @param blockProcessFromExiting if `true` then blocks the Nodejs process from exiting
 *
 * @returns a `[promise, cancel]` tuple, where `cancel` is a function that can be used
 *          to stop all processing and `promise` can be awaited for the completion of
 *          all workers, workers that complete on cancellation
 */
export function consumeQueue&lt;A&gt;(queue: Queue&lt;A&gt;, workers: number, blockProcessFromExiting: boolean = false) {
  const Cancel = new Error(&quot;queue-cancel-all&quot;)
  const startWorker =
    async (isActive: boolean[], process: (a: A) =&gt; Promise&lt;void&gt;) =&gt; {
      await yieldRunLoop()
      try {
        while (isActive.length &gt; 0 &amp;&amp; isActive[0]) {
          const a = await queue.dequeue()
          try {
            await process(a)
          } catch (e) {
            console.error(&quot;Error while processing queue message:&quot;, a, e)
          }
          // Fairness + protection against stack-overflow
          await yieldRunLoop()
        }
      } catch (e) {
        if (e != Cancel) throw e
      }
    }

  // For keeping the process alive, for as long as there is a run-loop active
  function startTick() {
    let tickID: Object
    function tick() { tickID = setTimeout(tick, 1000) }
    tick()
    return () =&gt; clearTimeout(tickID as any)
  }

  return (process: (a: A) =&gt; Promise&lt;void&gt;) =&gt; {
    const isActive = [true]
    const cancelTick = blockProcessFromExiting ? startTick() : () =&gt; {}
    const cancel = () =&gt; {
      isActive[0] = false
      queue.rejectAllActive(Cancel)
      cancelTick()
    }

    const tasks: Promise&lt;void&gt;[] = []
    for (let i=0; i&lt;workers; i++) {
      tasks.push(startWorker(isActive, process))
    }

    const all = Promise.all(tasks).then(_ =&gt; undefined as void)
    return [all, cancel] as [Promise&lt;void&gt;, () =&gt; void]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;async function main() {
  console.log(&quot;Starting...&quot;)
  const queue = new Queue&lt;string&gt;()

  const [promise, cancel] = consumeQueue(queue, 3, true)(
    async msg =&gt; {
      await new Promise(r =&gt; setTimeout(r, 1000))
      console.log(msg)
    })

  process.on(&apos;SIGINT&apos;, async () =&gt; {
    console.log(&quot;\nCancelling...\n&quot;)
    cancel()
  })

  await queue.enqueue(&quot;Hello&quot;)
  await queue.enqueue(&quot;World!&quot;)

  // Requires `blockProcessFromExiting` to be `true`
  await promise
  console.log(&quot;Done!&quot;)
}

main().catch(console.error)
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2019/10/07/async-queue.ts/?pk_campaign=rss&quot;&gt;Async Queue in TypeScript&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 07 Oct 2019 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 15:50:37 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 15:50:37 +0000</atom:modified>
  <link>https://alexn.org/blog/2019/10/07/async-queue.ts/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2019/10/07/async-queue.ts/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Async</category>
  <category>JavaScript</category>
  <category>Snippet</category>
  <category>TypeScript</category>
  </item>


<item>
  <title>Scala Snippet: Blocking Task</title>
  <description>Monix Task implementation for wrapping (suspending) blocking I/O such
that it can be canceled.
s
Imported from gist.github.com.</description>
  <content:encoded>&lt;p&gt;Monix Task implementation for wrapping (suspending) blocking I/O such
that it can be canceled.
s
Imported from &lt;a href=&quot;https://gist.github.com/alexandru/d04c23e3ebd918c6144b5ad33c69f48f&quot;&gt;gist.github.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;WARN: not sure if this code is correct.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import monix.eval._
import monix.execution.atomic.Atomic
import scala.util.control.NonFatal

def blocking[A](f: =&gt; A): Task[A] =
  Task.cancelable0 { (scheduler, cb) =&gt;
    // For capturing the executing thread
    val thread = Atomic(None : Option[Thread])
    // For synchronizing cancellation, ensuring the
    // interrupted flag is reset, in case it is our fault
    val wasInterrupted = Atomic(false)

    // Executing on top of thread-pool
    scheduler.execute(new Runnable {
      def run() = {
        val th = Thread.currentThread()
        val update = Some(th)
        var started = false

        try {
          if (thread.compareAndSet(None, update)) {
            started = true
            scala.concurrent.blocking {
              cb.onSuccess(f)
            }
          }
        } catch {
          case e: InterruptedException =&gt;
            ()
          case NonFatal(e) =&gt;
            cb.onError(e)
        } finally {
          // If true, then cancellation logic is guaranteed to
          // interrupt or to have interrupted current thread
          if (started &amp;&amp; !thread.compareAndSet(update, null)) {
            // Waits for cancellation logic to finish
            while (!wasInterrupted.get) {
              // Thread.onSpinWait() on Java 9
              Thread.`yield`()
            }
            // Clear interruption flag
            Thread.interrupted()
          }
        }
      }
    })

    // Cancellation logic
    Task {
      thread.getAndSet(null) match {
        case None | null =&gt; ()
        case Some(th) =&gt;
          th.interrupt()
          wasInterrupted.set(true)
      }
    }
  }
&lt;/code&gt;&lt;/pre&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2019/09/02/blocking-task.scala/?pk_campaign=rss&quot;&gt;Scala Snippet: Blocking Task&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 02 Sep 2019 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 12:15:08 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 12:15:08 +0000</atom:modified>
  <link>https://alexn.org/blog/2019/09/02/blocking-task.scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/snippets/2019/09/02/blocking-task.scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Async</category>
  <category>Monix</category>
  <category>Scala</category>
  <category>Snippet</category>
  </item>


<item>
  <title>Scala&#39;s isInstanceOf is an Anti-Pattern</title>
  <description>Scala has a much better way of discriminating between types. Scala has implicit parameters, with which you can describe type classes.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2019/08/11/isinstanceof-anti-pattern/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala-instanceof-antipattern.png?202603060940&quot; alt=&quot;&quot; width=&quot;768&quot; height=&quot;574&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  When you use &lt;code&gt;isInstanceOf[Class]&lt;/code&gt; checks, that’s an anti-pattern, as Scala has a much better way of discriminating between types. Scala has implicit parameters, with which you can describe &lt;a href=&quot;https://en.wikipedia.org/wiki/Type_class&quot;&gt;type classes&lt;/a&gt;.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  When C# developers try Java, one primary complaint is about the lack of reification for Java’s generics and by that they mean the ability to discriminate between different type parameters, so to differentiate between &lt;code&gt;List[Int]&lt;/code&gt; and &lt;code&gt;List[String]&lt;/code&gt; via &lt;code&gt;isInstanceOf&lt;/code&gt; checks. Java and Scala do type erasure so a &lt;code&gt;List[String]&lt;/code&gt; at runtime becomes a &lt;code&gt;List[Any]&lt;/code&gt;.
  &lt;br&gt;&lt;br&gt;
  Interestingly this complaint is not valid for Scala. Because of Scala’s expressiveness, you shouldn’t need to do &lt;code&gt;isInstanceOf&lt;/code&gt; checks, unless it’s for interoperability or for awkward micro optimizations that have no place in high level code. Reification is a runtime construct and Scala solves the associated use cases by moving all of that at compile time, via implicit parameters.
&lt;/p&gt;

&lt;p&gt;Let’s do an exercise …&lt;/p&gt;

&lt;h2 id=&quot;the-anti-pattern&quot;&gt;The Anti-Pattern&lt;/h2&gt;

&lt;p&gt;Given some piece of heavy logic, let’s say you want to describe a function that can execute a block of code, along with some finalizer, something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def guarantee[R](f: =&gt; R)(finalizer: =&gt; Unit): R =
  try f finally finalizer
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;guarantee {
  println(&quot;Executing!&quot;)
  1 + 1
} {
  println(&quot;Done!&quot;)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then one of your colleagues comes along and tries it with &lt;code&gt;Future&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

guarantee {
  Future {
    println(&quot;Executing!&quot;)
    1 + 1
  }
} {
  println(&quot;Done!&quot;)
}

//=&gt; Done!
//=&gt; Executing!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oops! This doesn’t work, so one of you might get the bright idea to do this instead:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.util.control.NonFatal

def guarantee[R](f: =&gt; R)(finalizer: =&gt; Unit): R =
  try {
    f match {
      // Anti-pattern
      case ref: Future[_] =&gt;
        ref.transform { r =&gt; finalizer; r }
          .asInstanceOf[R]
      case result =&gt;
        finalizer
        result
    }
  } catch {
    case NonFatal(e) =&gt;
      finalizer
      throw e
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This logic isn’t extensible — What happens when you’ll want to introduce logic for Java’s &lt;code&gt;CompletableFuture&lt;/code&gt;, Monix’s &lt;code&gt;Task&lt;/code&gt;, Cats-Effect’s &lt;code&gt;IO&lt;/code&gt; and so on? Each type gets its own branch?&lt;/p&gt;

&lt;p&gt;We’ve run into the &lt;a href=&quot;https://en.wikipedia.org/wiki/Expression_problem&quot;&gt;expression problem&lt;/a&gt; and yet our &lt;code&gt;R&lt;/code&gt; data type is not a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tagged_union&quot;&gt;tagged union&lt;/a&gt;, meaning that the set of possible values in that pattern match is endless.&lt;/p&gt;

&lt;p&gt;The second problem is the default branch. We are assuming that, in case &lt;code&gt;R&lt;/code&gt; is not a &lt;code&gt;Future&lt;/code&gt;, then we are dealing with a side effectful function that executes synchronously. So one of your colleagues comes along and does this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import monix.eval.Task

guarantee {
  // Oh noes!
  Task {
    println(&quot;Executing!&quot;)
    1 + 1
  }
} {
  println(&quot;Done!&quot;)
}

//=&gt; Done!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oops again! Now we’ve got a bug.&lt;/p&gt;

&lt;h2 id=&quot;type-classes-to-the-rescue&quot;&gt;Type Classes to the rescue&lt;/h2&gt;

&lt;p&gt;Let us define a type class for discriminating between types at &lt;em&gt;compile-time&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait CanGuarantee[R] {
  def guarantee(f: =&gt; R)(finalizer: =&gt; Unit): R
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now our function can look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def guarantee[R: CanGuarantee](f: =&gt; R)(finalizer: =&gt; Unit): R =
  implicitly[CanGuarantee[R]].guarantee(f)(finalizer)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To get the behavior of the original sample, we can define the default instances in the companion object like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object CanGuarantee  {
  // Future instance
  implicit def futureInstance[A]: CanGuarantee[Future[A]] =
    new CanGuarantee[Future[A]] {
      def guarantee(f: =&gt; Future[A])(finalizer: =&gt; Unit): Future[A] =
        Future(f).flatten.transform { r =&gt;
          finalizer
          r
        }
    }

  // Default instance
  implicit def syncInstance[R]: CanGuarantee[R] =
    new CanGuarantee[R] {
      def guarantee(f: =&gt; R)(finalizer: =&gt; Unit): R =
        try f finally finalizer
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The upside is that now the mechanism is extensible, without modifying the original function:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;final class Thunk[A](val run: () =&gt; A)

object Thunk {
  // Extending our logic with a new data type
  implicit def canGuarantee[A]: CanGuarantee[Thunk[A]] =
    new CanGuarantee[Thunk[A]] {
      def guarantee(f: =&gt; Thunk[A])(finalizer: =&gt; Unit): Thunk[A] =
        new Thunk(() =&gt; {
          try f.run() finally finalizer
        })
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;the-problem-with-defaults&quot;&gt;The problem with defaults&lt;/h2&gt;

&lt;p&gt;What happens in case you don’t define &lt;code&gt;CanGuarantee[Thunk[A]]&lt;/code&gt;?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;guarantee {
  new Thunk { () =&gt;
    println(&quot;Calculating!&quot;)
    1 + 1
  }
} {
  println(&quot;Done!&quot;)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;syncInstance&lt;/code&gt; that we defined above is incorrect for &lt;code&gt;Thunk&lt;/code&gt;. This means that we can introduce silent bugs. What should happen here?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import java.util.concurrent.CompletableFuture

guarantee {
  CompletableFuture.runAsync { () =&gt;
    println(&quot;Running!&quot;)
  }
} {
  println(&quot;Done!&quot;)
}
//=&gt; Done!
//=&gt; Running!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a bug waiting to happen.&lt;/p&gt;

&lt;p&gt;Therefore one can make the case that the default instance, if it doesn’t have the intended behavior for all data types, should not exist. But you can still provide a helper for creating one:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.annotation.implicitNotFound

@implicitNotFound(&quot;&quot;&quot;Cannot find implicit value for CanGuarantee[${R}].
If this value is synchronously calculated via an effectful function,
then use CanGuarantee.synchronous to create one.&quot;&quot;&quot;)
trait CanGuarantee[R] {
  def guarantee(f: =&gt; R)(finalizer: =&gt; Unit): R
}

object CanGuarantee {
  // No longer implicit
  def synchronous[R]: CanGuarantee[R] =
    new CanGuarantee[R] {
      def guarantee(f: =&gt; R)(finalizer: =&gt; Unit): R =
        try f finally finalizer
    }

  // Future instance
  implicit def futureInstance[A]: CanGuarantee[Future[A]] =
    new CanGuarantee[Future[A]] {
      def guarantee(f: =&gt; Future[A])(finalizer: =&gt; Unit): Future[A] =
        Future(f).flatten.transform { r =&gt;
          finalizer
          r
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice the usage of Scala’s &lt;a href=&quot;https://www.scala-lang.org/api/current/scala/annotation/implicitNotFound.html&quot;&gt;@implicitNotFound&lt;/a&gt; annotation for providing a nice error message.&lt;/p&gt;

&lt;p&gt;Let’s see what happens now when we try running the &lt;code&gt;CompletableFuture&lt;/code&gt; code again:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;error: Cannot find implicit value for CanGuarantee[CompletableFuture[Void]].
If this value is synchronously calculated via an effectful function,
then use CanGuarantee.synchronous to create one.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s better. This now goes for &lt;code&gt;Unit&lt;/code&gt; as well:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;scala&gt; guarantee { println(&quot;Executing!&quot;) } { println(&quot;Done!&quot;) }

error: Cannot find implicit value for CanGuarantee[Unit].
If this value is synchronously calculated via an effectful function,
then use CanGuarantee.synchronous[Unit] to create one.
       guarantee { println(&quot;Executing!&quot;) } { println(&quot;Done!&quot;) }
                                           ^
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want to work with &lt;code&gt;Unit&lt;/code&gt;, you have to create an instance for it, but notice how the error message tells you exactly what to do:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;implicit val ev = CanGuarantee.synchronous[Unit]

guarantee { println(&quot;Executing!&quot;) } { println(&quot;Done!&quot;) }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h2&gt;

&lt;p&gt;Friends don’t let friends use &lt;code&gt;isInstanceOf&lt;/code&gt; checks, because Scala has better ways of handling the related use cases.&lt;/p&gt;

&lt;p&gt;Enjoy~&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2019/08/11/isinstanceof-anti-pattern/?pk_campaign=rss&quot;&gt;Scala&apos;s isInstanceOf is an Anti-Pattern&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 11 Aug 2019 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2019/08/11/isinstanceof-anti-pattern/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2019/08/11/isinstanceof-anti-pattern/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Best Of</category>
  <category>Scala</category>
  </item>


<item>
  <title>On Bifunctor IO and Java&#39;s Checked Exceptions</title>
  <description>Bifunctor IO is a hot topic in the Scala community. Herein I’m expressing my dislike for it, as it shares the problems of Java’s Checked Exceptions.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2018/05/06/bifunctor-io/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/bio.png?202603060940&quot; alt=&quot;&quot; width=&quot;1368&quot; height=&quot;684&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  The Bifunctor &lt;code&gt;IO&lt;/code&gt; data type is a hot topic in the Scala community. In this article however I’m expressing my dislike for it because it shares the same problems as Java’s Checked Exceptions.
&lt;/p&gt;

&lt;h2 id=&quot;what-is-io&quot;&gt;What is IO?&lt;/h2&gt;

&lt;p&gt;Normally the &lt;code&gt;IO&lt;/code&gt; data type is expressed as:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed trait IO[+A] {
  ???
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What this means is that &lt;code&gt;IO&lt;/code&gt; is like a thunk, like a function with
zero parameters, that upon execution will finally produce an &lt;code&gt;A&lt;/code&gt;
value, if successful. The type also signals possible side effects that
might happen upon execution, but since it behaves like a function
(that hasn’t been executed yet), when you are given an &lt;code&gt;IO&lt;/code&gt; value you
can consider it as being pure (and the function producing it has
&lt;em&gt;referential transparency&lt;/em&gt;). This means that &lt;code&gt;IO&lt;/code&gt; can be used to
describe pure computations.&lt;/p&gt;

&lt;p&gt;Modern &lt;code&gt;IO&lt;/code&gt; implementations for JVM are also capable of describing
asynchronous processes, therefore you can also think of &lt;code&gt;IO&lt;/code&gt; as being:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;opaque type IO[+A] = () =&gt; Future[A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If we had &lt;a href=&quot;https://docs.scala-lang.org/sips/opaque-types.html&quot;&gt;opaque types&lt;/a&gt;
this would work well ;-)&lt;/p&gt;

&lt;p&gt;Available implementations are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://typelevel.org/cats-effect/datatypes/io.html&quot;&gt;cats.effect.IO&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://monix.io/docs/3x/eval/task.html&quot;&gt;monix.eval.Task&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/scalaz/scalaz/blob/series/7.3.x/concurrent/src/main/scala/scalaz/concurrent/Task.scala&quot;&gt;scalaz.concurrent.Task&lt;/a&gt;
(in the 7.2.x and 7.3.x series)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some cool presentations on this subject:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.youtube.com/watch?v=g_jP47HFpWA&quot;&gt;The Making of an IO&lt;/a&gt; (ScalaIO FR, 2017)&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.youtube.com/watch?v=X-cEGEJMx_4&quot;&gt;What Referential Transparency can do for you&lt;/a&gt; (ScalaIO FR, 2017)&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://monix.io/presentations/2016-task-flatmap-oslo.html&quot;&gt;Monix Task: Lazy, Async and Awesome&lt;/a&gt; (flatMap(Oslo), 2016)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;IO[+A]&lt;/code&gt; implements &lt;code&gt;MonadError[IO, Throwable]&lt;/code&gt;. And if we’re talking
of Cats-Effect or Monix, it also implements
&lt;a href=&quot;https://typelevel.org/cats-effect/typeclasses/sync.html&quot;&gt;Sync&lt;/a&gt; among
others.&lt;/p&gt;

&lt;p&gt;This means that &lt;code&gt;IO[+A]&lt;/code&gt; can terminate with error, it can terminate in
a &lt;code&gt;Throwable&lt;/code&gt;, actually reflecting the capabilities of the Java
Runtime. This means that this code is legit:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.IO
import scala.util.Random

def genRandomPosInt(max: Int): IO[Int] =
  IO(Math.floorMod(Random.nextInt(), max))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The astute reader might notice that this isn’t a total function, as it
could throw an &lt;code&gt;ArithmeticException&lt;/code&gt;. An easy mistake to make.&lt;/p&gt;

&lt;h2 id=&quot;whats-the-bifunctor-io&quot;&gt;What’s the Bifunctor IO?&lt;/h2&gt;

&lt;p&gt;I’m going to call this data type &lt;code&gt;BIO&lt;/code&gt;, to differentiate it from &lt;code&gt;IO&lt;/code&gt; above:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed trait BIO[E, A] {
  ???
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Such a type parameterizes the error type in &lt;code&gt;E&lt;/code&gt;. This is more or less like usage of
&lt;code&gt;Either&lt;/code&gt; to express the error, but as you shall see below, they aren’t exactly
equivalent:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;opaque type BIO[E, A] = IO[Either[E, A]]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or in case you’re throwing &lt;code&gt;EitherT&lt;/code&gt; in the mix to make that less awkward:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.data.EitherT

type BIO[E, A] = EitherT[IO, E, A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Exposing the error type would allow one to be very explicit at compile time
about the error:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def openFile(file: File): BIO[FileNotFoundException, BufferedReader] =
  // Made up API
  BIO.delayE {
    try Right(new BufferedReader(new FileReader(file)))
    catch { case e: FileNotFoundException =&gt; Left(e) }
  }

def genRandomInt: BIO[Nothing, Int] =
  BIO.delayE(Right(Random.nextInt()))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see in the first function that we are very explicit about
&lt;code&gt;FileNotFoundException&lt;/code&gt; being an error that could happen, instructing readers
that they should probably do error recovery.&lt;/p&gt;

&lt;p&gt;And in the second function we could use &lt;code&gt;Nothing&lt;/code&gt; as the error type to
signal that this operation can in fact produce no error (not really, but
let’s go with it 😉).&lt;/p&gt;

&lt;p&gt;Available implementations:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/scalaz/ioeffect&quot;&gt;scalaz/ioeffect&lt;/a&gt;, the Scalaz 8 &lt;code&gt;IO&lt;/code&gt;,
available as a backport for Scalaz 7, by John A. De Goes and other Scalaz contributors&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/LukaJCB/cats-bio&quot;&gt;cats-bio&lt;/a&gt; by Luka Jacobowitz, inspired
by Scalaz 8’s &lt;code&gt;IO&lt;/code&gt;, he took Cats-Effect’s &lt;code&gt;IO&lt;/code&gt; and changed &lt;code&gt;Throwable&lt;/code&gt; to &lt;code&gt;E&lt;/code&gt;
as a proof of concept&lt;/li&gt;
  &lt;li&gt;Worthy to mention is also &lt;a href=&quot;https://github.com/LukaJCB/cats-uio&quot;&gt;Unexceptional IO&lt;/a&gt;,
Luka’s precursor to his BIO implementation, inspired by Haskell’s
&lt;a href=&quot;https://hackage.haskell.org/package/unexceptionalio&quot;&gt;UIO&lt;/a&gt; I think&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some articles on this subject:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;http://degoes.net/articles/effects-without-transformers&quot;&gt;No More Transformers: High-Performance Effects in Scalaz 8&lt;/a&gt;,
by John A. De Goes&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://typelevel.org/blog/2018/04/13/rethinking-monaderror.html&quot;&gt;Rethinking MonadError&lt;/a&gt;,
by Luka Jacobowitz&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The premise of these articles is that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;our type system should stop us from being able to write nonsensical error handling
code and give us a way to show anyone reading the code that we’ve already handled errors&lt;/li&gt;
  &lt;li&gt;the performance of &lt;code&gt;EitherT&lt;/code&gt; is bad and usage more awkward&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Naturally, I disagree with the first assertion and I don’t think the second assertion is a problem 😀&lt;/p&gt;

&lt;h2 id=&quot;the-problems-of-javas-checked-exceptions&quot;&gt;The Problems of Java’s Checked Exceptions&lt;/h2&gt;

&lt;p&gt;While I think that the Bifunctor IO is a cool implementation, that’s pretty useful
for certain people, or certain use cases, I believe that ultimately it’s not a good
default implementation, as it shares the same problems as Java’s Checked Exceptions.
Or in other words, it’s ignoring decades of experience with exceptions, since
their introduction in LISP and then in C++, Java, C# and other mainstream languages.&lt;/p&gt;

&lt;p&gt;The web is littered with articles on why checked exceptions were a bad idea and many
of those reasons are also very relevant for an &lt;code&gt;IO[E, A]&lt;/code&gt;. Here’s just two such
interesting articles:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://testing.googleblog.com/2009/09/checked-exceptions-i-love-you-but-you.html&quot;&gt;Checked exceptions I love you, but you have to go&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.artima.com/intv/handcuffs.html&quot;&gt;The Trouble with Checked Exceptions&lt;/a&gt;, an interview with Anders Hejlsberg&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But let me explain in more detail …&lt;/p&gt;

&lt;h3 id=&quot;1-composition-destroys-specific-error-types&quot;&gt;1. Composition Destroys Specific Error Types&lt;/h3&gt;

&lt;p&gt;Let’s go with a more serious example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import java.io._

def openFile(file: File): BIO[FileNotFoundException, BufferedReader] =
  // Made up API
  BIO.delayE {
    try Right(new BufferedReader(new FileReader(file)))
    catch { case e: FileNotFoundException =&gt; Left(e) }
  }

def readLine(in: BufferedReader): BIO[IOException, String] =
  BIO.delayE {
    try Right(in.readLine())
    catch { case e: IOException =&gt; Left(e) }
    finally in.close()
  }

def convertToNumber(nr: String): BIO[NumberFormatException, Long] =
  BIO.delayE {
    try Right(nr.toLong)
    catch { case e: NumberFormatException =&gt; Left(e) }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What would be the type of a composition of multiple &lt;code&gt;IO&lt;/code&gt; values like this?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;for {
  buffer &lt;- openFile(file)
  line &lt;- readLine(buffer)
  num &lt;- convertToNumber(line)
} yield num
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s right, you’ll have a &lt;code&gt;Throwable&lt;/code&gt; on your hands. And this is
assuming that we’ve got a &lt;code&gt;flatMap&lt;/code&gt; that widens the result to the most
specific super-type, otherwise you’ll have to take care of conversions
manually, at each step. Also note that our usage of &lt;code&gt;Throwable&lt;/code&gt; is
irrelevant for the problem at hand. You could come up with your own
error type, but &lt;code&gt;Throwable&lt;/code&gt; is actually more practical, because we can
simply cast it.&lt;/p&gt;

&lt;p&gt;So assuming a &lt;code&gt;flatMap&lt;/code&gt; that doesn’t automatically widen the error
type of the result, what you’ll have to deal with is actually worse:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;for {
  buffer &lt;- openFile(file).leftWiden[Throwable]
  line &lt;- readLine(buffer).leftWiden[Throwable]
  num &lt;- convertToNumber(line).leftWiden[Throwable]
} yield num
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not sure how people feel about this, but to me this isn’t an
improvement over the status quo, far from it, this is just noise
polluting the code. And before you say anything in its defence, make
sure the argument doesn’t also apply to Java and everything you
dislike about it 😉&lt;/p&gt;

&lt;h3 id=&quot;2-you-dont-recover-from-errors-often&quot;&gt;2. You Don’t Recover From Errors Often&lt;/h3&gt;

&lt;p&gt;Imagine a piece of code like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;for {
  r1 &lt;- op1
  r2 &lt;- op2
  r3 &lt;- op3
} yield r1 + r2 + r3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we are executing 3 operations in sequence and each of them can fail,
we don’t know which or how.&lt;/p&gt;

&lt;p&gt;Does it matter? Most of the time, you don’t care. Most of the time it is
irrelevant. Most of the time you can’t even recover until later.&lt;/p&gt;

&lt;p&gt;Due to this uncertainty about which operations trigger errors and
which don’t, the premise of a Bifunctor &lt;code&gt;IO&lt;/code&gt; is that we’re forced to
do &lt;code&gt;attempt&lt;/code&gt; (error recovery) everywhere, but that is not a correct
premise. The way exceptions work and why they were introduced in LISP
and later in C++, is that you only catch exceptions at the point were
you can actually do something about it, otherwise it’s fine to live in
blissful ignorance.&lt;/p&gt;

&lt;p&gt;Empirical evidence suggests that most checked exceptions in Java are
either ignored or re-thrown, forcing people to write catch blocks that
are meaningless and even error prone.&lt;/p&gt;

&lt;p&gt;You can even find some studies on handling of checked exceptions in
Java projects, although I’m unsure about how good they are. For
example there’s
&lt;a href=&quot;https://ieeexplore.ieee.org/document/7832935/&quot;&gt;Analysis of Exception Handling Patterns in Java Projects&lt;/a&gt;,
which states that:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“Results of this study indicate that most programmers ignore checked exceptions and
leave them unnoticed. Additionally, it is observed that classes higher in the exception
class hierarchy are more frequently used as compared to specific exception subclasses.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Consider that in case of a web server the recovery might be something
as simple as showing the user an HTTP 500 status. HTTP 500 statuses are
a problem, but only if they happen and when they start to show up,
you can then go back and fix what needs to be fixed.&lt;/p&gt;

&lt;p&gt;Also remember the &lt;code&gt;FileNotFoundException&lt;/code&gt; we mentioned above?
Well, in most cases there’s not much you can do about it. It’s not like
you’ve got much choice in the knowledge that the file is missing,
most of the time the important bit being that an error, any error,
happened.&lt;/p&gt;

&lt;p&gt;To quote Anders Hejlsberg, the original designer of C#:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“It is funny how people think that the important thing about
exceptions is handling them. That is not the important thing about
exceptions. In a well-written application there’s a ratio of ten to
one, in my opinion, of try/finally to try/catch. Or in C#, &lt;code&gt;using&lt;/code&gt;
statements, which are like try/finally.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words the most important part of exceptions are the finalizers,
recovery being less frequent.&lt;/p&gt;

&lt;h3 id=&quot;3-the-error-type-is-an-encapsulation-leak&quot;&gt;3. The Error Type is an Encapsulation Leak&lt;/h3&gt;

&lt;p&gt;Lets say that we have this function:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def foo(param: A): BIO[FileNotFoundException, B]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By saying that it can end with a &lt;code&gt;FileNotFoundException&lt;/code&gt;, we are instructing
all callers, at all call sites, to handle this error as part of the exposed API.&lt;/p&gt;

&lt;p&gt;It’s pretty obvious that &lt;code&gt;FileNotFoundException&lt;/code&gt; can happen due to trying to
open a file on disk that is missing. It’s a very specific error, isn’t it,
the kind of error we’re supposed to like if we’re fans of &lt;code&gt;EitherT&lt;/code&gt; or of the
Bifunctor &lt;code&gt;IO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Well, what happens if we change &lt;code&gt;foo&lt;/code&gt; to make an HTTP request instead, or
maybe we turn it into something that reads a memory location. Now all of a sudden
&lt;code&gt;FileNotFoundException&lt;/code&gt; is no longer a possibility.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def foo(param: A): BIO[Unit, B]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This then bubbles down to all call sites, effectively breaking backwards compatibility,
so all that depend on your &lt;code&gt;foo&lt;/code&gt; will have to upgrade and recompile. And as the author
of &lt;code&gt;foo&lt;/code&gt; you’ll be faced with two choices:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;break compatibility&lt;/li&gt;
  &lt;li&gt;keep lying to your users that &lt;code&gt;foo&lt;/code&gt; can end with a &lt;code&gt;FileNotFoundException&lt;/code&gt; and
thus leave them with &lt;em&gt;unreachable code&lt;/em&gt; - which is something that some Java
libraries are known to have done&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;NOTE: there are cases in which &lt;em&gt;you want&lt;/em&gt; to break binary compatibility in
case the error type changes.  That is precisely the use case for which the
Bifunctor IO or &lt;code&gt;EitherT&lt;/code&gt; are recommended.&lt;/p&gt;

&lt;h3 id=&quot;4-it-pushes-complexity-to-the-user&quot;&gt;4. It Pushes Complexity to the User&lt;/h3&gt;

&lt;p&gt;On utility I deeply understand the need to parameterize all things. But the question is,
what else could we parameterize and why aren’t we doing it?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;we could have a type parameter that says whether the operation is blocking-IO bound,
or CPU bound and  in this way we could avoid running an &lt;code&gt;IO&lt;/code&gt; that’s CPU-bound on a
thread-pool meant for blocking I/O or vice-versa&lt;/li&gt;
  &lt;li&gt;we could add a type parameter for the execution model — is it synchronous or asynchronous?&lt;/li&gt;
  &lt;li&gt;we could describe the side effect with a type parameter — i.e. is it doing PostgreSQL queries,
or ElasticSearch inserts and in this way the type becomes more transparent and you could
come up with rules for what’s safe to execute in parallel or what not&lt;/li&gt;
  &lt;li&gt;add your own pet peeve …&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m fairly sure that people have attempted these. I’m fairly sure that
there might even be libraries around that are useful in certain
specific instances. But they are not mainstream.&lt;/p&gt;

&lt;p&gt;We aren’t doing it because adding type parameters to the types we are
using leads to the death of the compiler, not to mention our own
understanding of the types involved, plus usage becomes that much
harder, because by introducing type parameters, values with different
type arguments no longer compose without explicit conversion /
widening, pushing a lot of complexity to the user.&lt;/p&gt;

&lt;p&gt;This is why &lt;code&gt;EitherT&lt;/code&gt; is cool, even with all of its problems. It’s cool
because it can be bolted on, when you need it, adding that complexity
only when necessary.&lt;/p&gt;

&lt;p&gt;The Bifunctor &lt;code&gt;IO[E, A]&lt;/code&gt; looks cool, but what happens downstream to
the types using it? Monix’s &lt;code&gt;Iterant&lt;/code&gt; for example is
&lt;code&gt;Iterant[F[_], A]&lt;/code&gt;. Should it be &lt;code&gt;Iterant[F[_], E, A]&lt;/code&gt;? Or maybe
&lt;code&gt;Iterant[F[Throwable, _], A]&lt;/code&gt;? Or &lt;code&gt;Iterant[F[_, _], E, A]&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;If I parameterize the error in &lt;code&gt;Iterant&lt;/code&gt;, how could it keep on working with
the current &lt;code&gt;IO&lt;/code&gt; that doesn’t have a &lt;code&gt;E&lt;/code&gt; parameter? And if &lt;code&gt;Iterant&lt;/code&gt; works with
&lt;code&gt;IO[Throwable, _]&lt;/code&gt;, then what’s the point of &lt;code&gt;IO[E, A]&lt;/code&gt; anyway?&lt;/p&gt;

&lt;p&gt;Note that having multiple type parameters is a problem in Haskell too.
Martin Odersky already expressed his dislike for type classes of multiple type
parameters, such as &lt;code&gt;MonadError&lt;/code&gt; and it’s pretty telling that type classes with
multiple type parameters are not part of standard Haskell.&lt;/p&gt;

&lt;h3 id=&quot;5-the-bifunctor-io-doesnt-reflect-the-runtime&quot;&gt;5. The Bifunctor IO Doesn’t Reflect the Runtime&lt;/h3&gt;

&lt;p&gt;I gave this piece of code above and I’m fairly sure that you missed the
bug in it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def readLine(in: BufferedReader): BIO[IOException, String] =
  BIO.delayE {
    try Right(in.readLine())
    catch { case e: IOException =&gt; Left(e) }
    finally in.close()
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The bug is that &lt;code&gt;in.close()&lt;/code&gt; can throw exceptions as well. Actually on top of the JVM
even pure, total functions can throw &lt;code&gt;InterruptedException&lt;/code&gt; for example.&lt;/p&gt;

&lt;p&gt;So what happens next?&lt;/p&gt;

&lt;p&gt;Well the Bifunctor &lt;code&gt;IO&lt;/code&gt; cannot represent just any &lt;code&gt;Throwable&lt;/code&gt;. By making &lt;code&gt;E&lt;/code&gt; generic,
it means that handling of &lt;code&gt;Throwable&lt;/code&gt; is out. So at this point there are about 3 possibilities:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;crash the process, which would be the default, naive implementation&lt;/li&gt;
  &lt;li&gt;your thread crashes without making a sound, logging to a stderr that gets redirected to &lt;code&gt;/dev/null&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;use something like a custom Java
&lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.UncaughtExceptionHandler.html&quot;&gt;Thread.UncaughtExceptionHandler&lt;/a&gt;,
or Scalaz’s specific “fiber” error reporter to report such errors somewhere&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also the astute reader should notice that by replacing the &lt;code&gt;MonadError&lt;/code&gt; handling and recovery
by a simple reporter there’s no way to do &lt;em&gt;back-pressured retries&lt;/em&gt;. The nature of bugs is that
many bugs are non-deterministic. Maybe you’re doing an HTTP request and you’re expecting a
number in return, but it gives you an unexpected response - maybe it has a maximum limit
of concurrent connections or something.&lt;/p&gt;

&lt;p&gt;When making requests to web services, wouldn’t it be better to give them some slack?
Wouldn’t it be better to do retries with &lt;a href=&quot;https://en.wikipedia.org/wiki/Exponential_backoff&quot;&gt;exponential backoff&lt;/a&gt;
a couple of times before crashing? Or maybe use utilities such as
&lt;a href=&quot;https://monix.io/docs/3x/eval/circuit-breaker.html&quot;&gt;TaskCircuitBreaker&lt;/a&gt;? Of course it is. And in
the environments I worked on, such instances are very frequent and the processes have to be really
resilient to failure and resiliency is built-in only when having the assumption that
&lt;em&gt;everything can fail for unknown reasons&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the grand scheme of things, the reason for why this is a huge problem is because
&lt;code&gt;IO&lt;/code&gt; should reflect the runtime, because &lt;code&gt;IO&lt;/code&gt; effectively replaces Java’s call-stack.
But the Bifunctor &lt;code&gt;IO&lt;/code&gt; no longer does.&lt;/p&gt;

&lt;p&gt;In the words of &lt;a href=&quot;https://x.com/djspiewak&quot;&gt;Daniel Spiewak&lt;/a&gt;, who initiated
the Cats-Effect project:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“
    The JVM runtime is typed to a first order. Which happens to be exactly what the type
    parameter of IO reflects. I&apos;m not talking about code in general, just IO.
    IO is the runtime, the runtime is IO.
  ”&lt;/em&gt;&lt;/p&gt;
  &lt;p&gt;
    &lt;a href=&quot;https://x.com/djspiewak/status/983807277613236230&quot;&gt;
      Source
    &lt;/a&gt;
  &lt;/p&gt;
  &lt;p&gt;&lt;em&gt;“
    The whole purpose of IO as an abstraction is to control the runtime.
    If you pretend that the runtime has a property which it does not, then that
    control is weakened and can be corrupted (in this case, by uncontrolled crashes).
  ”&lt;/em&gt;&lt;/p&gt;
  &lt;p&gt;
    &lt;a href=&quot;https://x.com/djspiewak/status/983808880349073408&quot;&gt;
      Source
    &lt;/a&gt;
  &lt;/p&gt;
  &lt;p&gt;&lt;em&gt;“
    IO needs to reflect and describe the capabilities of the runtime, for good or for bad.
    All it takes is an &quot;innocent&quot; throw to turn it all into a lie, and you can&apos;t prevent that.
  ”&lt;/em&gt;&lt;/p&gt;
  &lt;p&gt;
    &lt;a href=&quot;https://x.com/djspiewak/status/983805298526699520&quot;&gt;
      Source
    &lt;/a&gt;
  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I agree with that and it shows which developers worked a lot in dynamic environments,
this great divide being between those that think types can prove correctness in all cases
and those that don’t.&lt;/p&gt;

&lt;p&gt;If you’re in the former camp, I think &lt;a href=&quot;https://x.com/Hillelogram&quot;&gt;Hillel Wayne&lt;/a&gt;
is eager to &lt;a href=&quot;https://hillelwayne.com/post/theorem-prover-showdown/&quot;&gt;prove you wrong&lt;/a&gt; 😉&lt;/p&gt;

&lt;h2 id=&quot;io-cannot-be-an-alias-of-the-bifunctor-io&quot;&gt;IO Cannot Be an Alias of the Bifunctor IO&lt;/h2&gt;

&lt;p&gt;You might be temped to say that:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type IO[A] = BIO[Throwable, A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is not true and it gave birth to, what I like to call, the great
“&lt;em&gt;No True Functor&lt;/em&gt;” debate and fallacy 😜&lt;/p&gt;

&lt;p&gt;But details about it would take another article to explain.&lt;/p&gt;

&lt;p&gt;So it’s enough to say that &lt;code&gt;cats.effect.IO&lt;/code&gt; and &lt;code&gt;monix.eval.Task&lt;/code&gt; has got you
covered in all cases, whereas a Bifunctor &lt;code&gt;IO&lt;/code&gt; needs to pretend that developers
on top of the JVM can work only with total functions, on top of an environment
that actively proves you wrong, thus applying the “&lt;em&gt;let it crash&lt;/em&gt;” philosophy
on top of a runtime that makes this really expensive to do so
(i.e. the JVM is not Erlang).&lt;/p&gt;

&lt;p&gt;This is another great divide in mentality, although I can see the merits of
the arguments on the other side. In such cases it’s relevant by what kind
of problems you got burned or not in the past I guess.&lt;/p&gt;

&lt;h2 id=&quot;final-words&quot;&gt;Final Words&lt;/h2&gt;

&lt;p&gt;I am not saying that the Bifunctor &lt;code&gt;IO[E, A]&lt;/code&gt; is not useful.&lt;/p&gt;

&lt;p&gt;I’m pretty sure it will prove useful for some use-cases, the same kind of use-cases
for which &lt;code&gt;EitherT&lt;/code&gt; is useful, except with a less orthogonal design. Well you gain
some performance in that process, although when you’re using &lt;code&gt;EitherT&lt;/code&gt; it’s debatable
whether it matters for those particular use cases.&lt;/p&gt;

&lt;p&gt;What I am saying is that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;let’s not ignore the two decades of experience we had with Java’s checked exceptions,
preceded by another two decades of experience with exceptions in other languages&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;EitherT&lt;/code&gt; is useful because it can be bolted on when the need arises, or otherwise
it can be totally ignored by people like myself, so let’s not throw the baby with the
bath water&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I do think that &lt;code&gt;IO[E, A]&lt;/code&gt; will be a great addition to the ecosystem, as an option over
the current status quo. Scala is a great environment.&lt;/p&gt;

&lt;p&gt;That’s all.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2018/05/06/bifunctor-io/?pk_campaign=rss&quot;&gt;On Bifunctor IO and Java&apos;s Checked Exceptions&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 06 May 2018 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2018/05/06/bifunctor-io/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2018/05/06/bifunctor-io/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Best Of</category>
  <category>FP</category>
  <category>Haskell</category>
  <category>OOP</category>
  <category>Scala</category>
  <category>Typelevel</category>
  </item>


<item>
  <title>In Defense of OOFP</title>
  <description>OOP versus Type Classes, exemplified and in defense of the Scala collections redesign.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2018/02/12/in-defense-oofp/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala-stairs.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;1200&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  This article is about OOP hierarchies, in comparisson with
  &lt;a href=&quot;https://en.wikipedia.org/wiki/Type_class&quot;&gt;type classes&lt;/a&gt;, using as
  example Scala’s standard collections, which are involved in a recent
  debate around their redesign.
&lt;/p&gt;

&lt;h2 id=&quot;1-background&quot;&gt;1. Background&lt;/h2&gt;

&lt;p&gt;Scala is a hybrid language, being at the same time its greatest
strength and weakness.&lt;/p&gt;

&lt;p&gt;The
&lt;a href=&quot;https://github.com/scala/collection-strawman&quot;&gt;collection-strawman&lt;/a&gt;
represents a redesign of Scala’s standard collections, planned to be
shipped in Scala 2.13, as part of a
&lt;a href=&quot;https://github.com/scalacenter/advisoryboard/blob/master/proposals/007-collections.md&quot;&gt;Scala Center proposal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are at the moment of writing two blog posts explaining the
upcoming changes on Scala’s blog:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://scala-lang.org/blog/2017/05/30/tribulations-canbuildfrom.html&quot;&gt;Tribulations of CanBuildFrom&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://scala-lang.org//blog/2017/11/28/view-based-collections.html&quot;&gt;Let Them Be Lazy!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.scala-lang.org/blog/2017/02/28/collections-rework.html&quot;&gt;Scala 2.13 Collections Rework&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.scala-lang.org/blog/2018/02/09/collections-performance.html&quot;&gt;On Performance of the New Collections&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s now also receiving some criticism. This article represents my
2¢ on why I like this redesign and on why criticism of an
OOP hierarchy are not warranted, even if you love FP.&lt;/p&gt;

&lt;h3 id=&quot;11-my-road-to-scala&quot;&gt;1.1. My Road to Scala&lt;/h3&gt;

&lt;p&gt;Like many others in the Scala community, I was attracted to Scala because
it seemed to be a better, more expressive language, with stricter
static type checks than Java or the other languages I worked
with. Coming from Python at that time, Scala seemed like a breath of
fresh air.&lt;/p&gt;

&lt;p&gt;Yes, I came to Scala in 2012 looking for a better OOP language and
what I got was a great combination of Smalltalk-esque OOP features,
mixed with an
&lt;a href=&quot;https://alexn.org/blog/2017/10/15/functional-programming/&quot;&gt;actual FP culturre&lt;/a&gt;. I
have an article about
&lt;a href=&quot;https://alexn.org/blog/2012/11/02/scala-functional-programming-type-classes/&quot;&gt;what I liked about it&lt;/a&gt;
written back then and to be honest, not much has changed.&lt;/p&gt;

&lt;p&gt;But what really sold me were the standard collections. In spite of their
internal complexity and problems being leaked at the call sites, it
was the first time I felt my needs for standard data structures were
met and even exceeded.&lt;/p&gt;

&lt;h2 id=&quot;2-criticism&quot;&gt;2. Criticism&lt;/h2&gt;

&lt;p&gt;There’s plenty to complain about in the current implementation and
here I’m doing my best to summarize it:&lt;/p&gt;

&lt;h3 id=&quot;21-canbuildfrom&quot;&gt;2.1. CanBuildFrom&lt;/h3&gt;

&lt;p&gt;Checkout this classic StackOverflow issue:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/1722726/is-the-scala-2-8-collections-library-a-case-of-the-longest-suicide-note-in-hist&quot;&gt;Is the Scala 2.8 collections library a case of “the longest suicide note in history”?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In it the author rightfully complains that this method signature for
&lt;code&gt;List&lt;/code&gt; is scary and he doesn’t understand it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def map[B, That](f: A =&gt; B)(implicit bf: CanBuildFrom[Repr, B, That]): That
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Scala core developers first tried to hide this signature, so if
you’ll take a look at the
&lt;a href=&quot;https://www.scala-lang.org/api/current/scala/collection/immutable/List.html#map[B](f:A=%3EB):List[B]&quot;&gt;current ScalaDoc for List.map&lt;/a&gt;,
you won’t see it. But that’s only a documentation trick, because
the actual source-code (and your IDE) tells a different story, see
&lt;a href=&quot;https://github.com/scala/scala/blob/v2.12.4/src/library/scala/collection/immutable/List.scala#L280&quot;&gt;List.scala#280&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In essence &lt;code&gt;CanBuildFrom&lt;/code&gt; is a clever abstraction, as
&lt;a href=&quot;https://stackoverflow.com/a/1728140/3280&quot;&gt;Martin Odersky&lt;/a&gt; himself
explains, however at this point we can all agree that its complexity
is not justified. Not only because it is difficult to understand, but
because it has historically created issues for people at the call-sites.&lt;/p&gt;

&lt;p&gt;Here’s what Coda Hale &lt;a href=&quot;https://gist.github.com/anonymous/1406238&quot;&gt;was writing&lt;/a&gt;
back in 2011:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“
    Replacing a `scala.collection.mutable.HashMap` with a
    `java.util.HashMap` in a wrapper produced an order-of-magnitude
    performance benefit for one of these loops. Again, this led to some
    heinous code as any of its methods which took a `Builder` or
    `CanBuildFrom` would immediately land us with a mutable.HashMap. (We
    ended up using explicit external iterators and a while-loop, too.)
    &lt;br&gt;...&lt;br&gt;
    The number of concepts I had to explain to new members of our team
    for even the simplest usage of a collection was surprising: implicit
    parameters, builder typeclasses, &quot;operator overloading&quot;, return type
    inference, etc. etc.
  ”&lt;/em&gt;&lt;/p&gt;
  &lt;footer&gt;
    &lt;p&gt;
      &lt;a href=&quot;https://gist.github.com/anonymous/1406238&quot;&gt;Source&lt;/a&gt;
    &lt;/p&gt;
  &lt;/footer&gt;
&lt;/blockquote&gt;

&lt;p&gt;But if you’ll take a look at
&lt;a href=&quot;https://github.com/scala/collection-strawman/blob/master/collections/src/main/scala/strawman/collection/immutable/List.scala#L214&quot;&gt;List.scala in collection-strawman&lt;/a&gt;,
that signature now looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def map[B](f: A =&gt; B): List[B]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There, that brings justice to everybody that complained for all these
years.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: &lt;code&gt;CanBuildFrom&lt;/code&gt; was a clever solution to an exaggerated
problem, but you’ll no longer have to worry about it. Beware of clever
solutions to problems you don’t have!
&lt;/p&gt;

&lt;h3 id=&quot;22-complex-hierarchy&quot;&gt;2.2. Complex Hierarchy&lt;/h3&gt;

&lt;p&gt;This is an awesome infographic, showing how complex the implementation is for
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/immutable/List.html&quot;&gt;List&lt;/a&gt;,
by &lt;a href=&quot;https://github.com/tpolecat&quot;&gt;Rob Norris&lt;/a&gt;:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/scala-list.jpg&quot; width=&quot;1650&quot; height=&quot;1275&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;This is indeed a disaster, there’s no nicer way of saying it.&lt;/p&gt;

&lt;p&gt;And this is &lt;code&gt;List&lt;/code&gt;, after the &lt;code&gt;collection-strawman&lt;/code&gt; refactoring:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/scala-list-strawman.jpg&quot; width=&quot;1200&quot; height=&quot;845&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;(Again credit goes to Rob Norris)&lt;/p&gt;

&lt;p&gt;This is indeed vastly simplified and actually understandable.&lt;/p&gt;

&lt;p&gt;Some questions are left to be answered. Just by looking at this
info-graphic I wonder in what capacity is there still code sharing
between the immutable collections and the mutable versions, or between
the lazy and the strict - ideally there should be no code sharing
between mutable or immutable, between lazy and strict and I hope
they’ve been extra careful this time around.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: a complex OOP hierarchy, as clever as it may be,
brings with it complexity beyond reason and is counter-productive for
subtype polymorphism!
&lt;/p&gt;

&lt;h3 id=&quot;23-seq-or-other-super-types&quot;&gt;2.3. Seq or Other Super-types&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/djspiewak&quot;&gt;Daniel Spiewak&lt;/a&gt; made a good attempt at a
&lt;a href=&quot;https://gist.github.com/djspiewak/2ae2570c8856037a7738&quot;&gt;proposal in 2015&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some recent impressions, as a short introduction to this
criticism:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“
    You always care about the asymptotic properties of your data
    structures. So there is never a case where Seq makes sense, even as
    a concept!
  ”&lt;/em&gt;&lt;/p&gt;
  &lt;footer&gt;
    &lt;p&gt;
      &lt;a href=&quot;https://x.com/djspiewak/status/962767948774457344&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
    &lt;/p&gt;
  &lt;/footer&gt;
&lt;/blockquote&gt;

&lt;p&gt;The example that Daniel gives in his proposal is this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def foo(is: Seq[Int]): MyThingy = {
  val t = new MyThingy
  for (idx &lt;- 0 until is.length) {
    t.accumulate(is(idx))
  }
  t
}
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“If I showed you this code and asked you what the big-O complexity of
it was, could you tell me the answer? No, you cannot, because it
depends on the runtime type of &lt;code&gt;is&lt;/code&gt;!”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a very good example showing a very frequent booby trap for
beginners that aren’t paying attention to their data structures.&lt;/p&gt;

&lt;p&gt;He goes on saying:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“Choosing a collection is a very deliberate and intentional thing. We
want to select our collection to match the complexity bounds of our
problem. Encouraging (and even enabling!) users to work in terms of
generic types that throw away this information is wrong, and very
very much an anti-pattern.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I very much respect this opinion and I know from where he’s coming
from, however I disagree with it.&lt;/p&gt;

&lt;p&gt;Choosing a collection type means committing to an implementation, it
means specializing, which is a bad idea in many cases. And arguing
against this is also like arguing against Haskell’s
&lt;a href=&quot;https://hackage.haskell.org/package/base-4.10.1.0/docs/Data-Traversable.html&quot;&gt;Traversable&lt;/a&gt;
(&lt;a href=&quot;https://github.com/typelevel/cats/blob/v1.0.1/core/src/main/scala/cats/Traverse.scala&quot;&gt;cats.Traverse&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;N.B. we are not arguing against the merits of Haskell’s &lt;code&gt;Traversable&lt;/code&gt;
type class and how that compares with &lt;code&gt;Iterable&lt;/code&gt;. More on that below.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: OOP interfaces might expose leaky operations that
are booby traps (e.g. &lt;code&gt;Seq&lt;/code&gt; indexing), but this is not specific
to OOP interfaces, vigilance in design is always needed!
&lt;/p&gt;

&lt;h3 id=&quot;24-not-using-type-classes&quot;&gt;2.4. Not Using Type-classes&lt;/h3&gt;

&lt;p&gt;This is actually a separate argument that does have merit:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“
    I&apos;ll stick to scalaz&apos;s separation of functionality and
    implementation through typeclasses... it&apos;s much easier to
    understand, faster, and easier to extend.
  ”&lt;/em&gt;&lt;/p&gt;
  &lt;footer&gt;
    &lt;p&gt;
      &lt;a href=&quot;https://x.com/fommil/status/962736382467813376&quot; target=&quot;_blank&quot;&gt;Sam Halliday&lt;/a&gt;
    &lt;/p&gt;
  &lt;/footer&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“
   You do not need a top-down hierarchy of collections. They&apos;re ready
   to break back compatibility, so why not do it right like Spiewak&apos;s
   suggestion 3 years ago? `Builder` and `IterableOnce` are symptoms of a
   deeper problem: poor design choices.
  ”&lt;/em&gt;&lt;/p&gt;
  &lt;footer&gt;
    &lt;p&gt;
      &lt;a href=&quot;https://x.com/emi1ypi/status/962743355192020992&quot; target=&quot;_blank&quot;&gt;Emily Pillmore&lt;/a&gt;
    &lt;/p&gt;
  &lt;/footer&gt;
&lt;/blockquote&gt;

&lt;p&gt;The argument for those amongst you not familiar with it is that
type-classes can yield a better design for the standard collections,
instead of an OOP hierarchy of interfaces.&lt;/p&gt;

&lt;p&gt;To re-use the example above:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.Foldable

def foo[F[_] : Foldable](list: F[Int]): MyThingy =
  implicitly[Foldable[F]].foldLeft(list, new MyThingy)(_ accumulate _)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ah, now we are getting somewhere. But the astute reader should notice at this
point that this means exposure of an extra &lt;code&gt;F[_]&lt;/code&gt; type parameter that
you don’t actually need with OOP — well, OK, this syntax heaviness is
an artifact of the Scala language, as in Haskell this wouldn’t be an
issue.&lt;/p&gt;

&lt;p&gt;Also, not clearly visible here is that type-classes such as &lt;code&gt;Foldable&lt;/code&gt;
or &lt;code&gt;Traversable&lt;/code&gt;, while more generic are also strictly less capable
than &lt;code&gt;Iterable&lt;/code&gt;. Yes, that’s because of &lt;code&gt;Iterator&lt;/code&gt;’s side effecting,
but highly efficient and flexible protocol. More on that below.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: type-classes are nice, playing well with
parametric polymorphism, but in Scala the syntax is heavier than
when using OOP, although this isn’t an issue with Haskell
&lt;/p&gt;

&lt;h2 id=&quot;3-oop-vs-constrained-parametric-polymorphism-type-classes&quot;&gt;3. OOP vs Constrained Parametric Polymorphism (Type-classes)&lt;/h2&gt;

&lt;p&gt;Lets imagine a function that sums up numbers:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.math.Numeric

def sum[A](list: Seq[A])(implicit A: Numeric[A]): A =
  list.foldLeft(A.zero)(A.plus)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note we are already using &lt;code&gt;Numeric&lt;/code&gt;, which is a type class exposed by
Scala’s standard library. And it’s actually not the best type class we
could use, as what we’d need here is a
&lt;a href=&quot;https://github.com/typelevel/cats/blob/v1.0.1/kernel/src/main/scala/cats/kernel/Monoid.scala&quot;&gt;Monoid&lt;/a&gt;,
but ignore that.&lt;/p&gt;

&lt;p&gt;Meet Haskell’s
&lt;a href=&quot;https://hackage.haskell.org/package/base-4.10.1.0/docs/Data-Foldable.html&quot;&gt;Data.Foldable&lt;/a&gt;,
also described in
&lt;a href=&quot;https://github.com/typelevel/cats/blob/v1.0.1/core/src/main/scala/cats/Foldable.scala&quot;&gt;cats.Foldable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With it we can fold arbitrary data-structures, e.g. we could sum up numbers:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.Foldable
import scala.math.Numeric

def sum[F[_], A](list: F[A])
  (implicit F: Foldable[F], A: Numeric[A]): A = {

  F.foldLeft(list, A.zero)(A.plus)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(N.B. using &lt;code&gt;F&lt;/code&gt; and &lt;code&gt;A&lt;/code&gt; as the type names &lt;em&gt;and&lt;/em&gt; as the name of the
implicit parameters is nothing special, just a convention)&lt;/p&gt;

&lt;p&gt;Is this better?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;PRO:&lt;/strong&gt; describing &lt;code&gt;foldLeft&lt;/code&gt; as a method on &lt;code&gt;F[_]&lt;/code&gt; is no longer
required, which makes &lt;code&gt;F[_]&lt;/code&gt; data types more generic, more reusable;
not very clear in this case, but if you’re unfamiliar with
type-class based design, trust me on this one&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;CON:&lt;/strong&gt; this method makes &lt;code&gt;F[_]&lt;/code&gt; clearly visible, exposing it at the
type system level - this is no longer subtyping, this is no longer the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Liskov_substitution_principle&quot;&gt;Liskov substitution principle&lt;/a&gt;,
this is parametric polymorphism and it moves the dispatch cost at
compile time, with both the good and the bad&lt;/li&gt;
&lt;/ul&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: With Scala you can actually pick and choose the best
approach - this can lead to choice paralysis however and lots of drama!
&lt;/p&gt;

&lt;h3 id=&quot;4-case-study-monix-iterant&quot;&gt;4. Case Study: Monix Iterant&lt;/h3&gt;

&lt;figure&gt;
  &lt;a href=&quot;https://www.youtube.com/watch?v=JFbYQGG2Nb4&quot; target=&quot;_blank&quot; title=&quot;A Tale of Two Monix Streams, by Alexandru Nedelcu&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/JFbYQGG2Nb4/maxresdefault.jpg&quot;&gt;
  &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;At &lt;a href=&quot;https://scala.world/schedule&quot;&gt;Scala World&lt;/a&gt; I had a talk titled
&lt;a href=&quot;https://www.youtube.com/watch?v=JFbYQGG2Nb4&quot;&gt;A Tale of Two Monix Streams&lt;/a&gt;
in which I described the design of the upcoming &lt;code&gt;monix.tail.Iterant&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It’s a wonderful data structure for modelling streams that makes use
of type-classes defined in
&lt;a href=&quot;https://github.com/typelevel/cats-effect&quot;&gt;cats-effect&lt;/a&gt; for being able
to describe asynchronous computations.  In the presentation I describe
how I made use of type-classes, with actual restrictions placed on the
operations themselves.&lt;/p&gt;

&lt;p&gt;If you’re a beginner in FP design via type-classes, I highly recommend
the second part of the presentation.&lt;/p&gt;

&lt;p&gt;Here’s the gist - suppose we want a pure
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/Iterator.html&quot;&gt;Iterator&lt;/a&gt;
that is also capable of deferring the evaluation to a given &lt;code&gt;F[_]&lt;/code&gt;
(e.g. &lt;code&gt;monix.eval.Task&lt;/code&gt;, &lt;code&gt;cats.effect.IO&lt;/code&gt;), such that it’s also
capable of streaming events from asynchronous sources, we could
describe it like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed trait Iterant[F[_], A]

case class Next[F[_], A](first: A, rest: F[Iterant[F, A]], stop: F[Unit])
  extends Iterant[F, A]

case class Suspend[F[_], A](rest: F[Iterant[F, A]], stop: F[Unit])
  extends Iterant[F, A]

case class Halt[F[_], A](error: Option[Throwable])
  extends ITerant[F, A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a data structure that resembles &lt;code&gt;List&lt;/code&gt;, but that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;defers evaluation to an &lt;code&gt;F[_]&lt;/code&gt; data type that’s capable of
suspending side effects, but note that the &lt;em&gt;actual type class
restrictions&lt;/em&gt; are not defined on the data structure itself&lt;/li&gt;
  &lt;li&gt;is capable of asynchronous processing, in case &lt;code&gt;F[_]&lt;/code&gt; is
capable of asynchronous processing (thus also being equivalent to
the async iterators in JavaScript or Ix.NET)&lt;/li&gt;
  &lt;li&gt;is lazy, if &lt;code&gt;F[_]&lt;/code&gt; is lazy, thus being equivalent to Scala’s
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/immutable/Stream.html&quot;&gt;Stream&lt;/a&gt;,
or Java’s
&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html&quot;&gt;Stream&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;is able to do resource handling, to close any open connections in
case of interruption (by following &lt;code&gt;stop&lt;/code&gt;), thus making it safer
than plain iterators&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;41-type-classes-for-super-powers&quot;&gt;4.1. Type-classes For Super Powers&lt;/h3&gt;

&lt;p&gt;So how can this simple data structure possibly have such super powers?&lt;/p&gt;

&lt;p&gt;The answer is that it defers the hard work to any &lt;code&gt;F[_]&lt;/code&gt; data type
whose capabilities are defined via type classes.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.Sync

def map[F[_], A](fa: Iterant[F, A])(f: A =&gt; B)
  (implicit F: Sync[F]): Iterant[F, B] = {

  def loop(current: Iterant[F, A]): Iterant[F, A] =
    current match {
      case Next(a, rest, stop) =&gt;
        Next(f(b), rest.map(loop), stop)
      case Suspend(rest, stop) =&gt;
        Suspend(rest.map(loop), stop)
      case Halt(e) =&gt;
        Halt(e)
    }
  loop(fa)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That part about “&lt;code&gt;implicit F: Sync[F]&lt;/code&gt;”, that’s the restriction we
have for &lt;code&gt;F[_]&lt;/code&gt;, defining its capabilities.&lt;/p&gt;

&lt;p&gt;What we need here is for &lt;code&gt;F[_]&lt;/code&gt; to implement a &lt;code&gt;map&lt;/code&gt; operation and
thus it needs to have a
&lt;a href=&quot;https://github.com/typelevel/cats/blob/v1.0.1/core/src/main/scala/cats/Functor.scala&quot;&gt;Functor&lt;/a&gt;
instance, however our &lt;code&gt;map&lt;/code&gt; is used in fact recursively and due to
Scala being a strict language, if this &lt;code&gt;map&lt;/code&gt; were to be strictly
evaluated, then we’d
&lt;a href=&quot;https://github.com/typelevel/cats-effect/issues/92&quot;&gt;end up with a stack overflow&lt;/a&gt;.
This is why we require &lt;code&gt;cats.effect.Sync&lt;/code&gt;, which implies a &lt;code&gt;Functor&lt;/code&gt;,
because &lt;code&gt;Sync&lt;/code&gt; now suspends evaluation in &lt;code&gt;map&lt;/code&gt; by law.&lt;/p&gt;

&lt;p&gt;You can see how this process goes: you only add the restrictions you
want on the operations themselves, depending on your needs, not on
the data structure, thus making the data structure more reusable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT:&lt;/strong&gt; &lt;code&gt;F&lt;/code&gt; gets exposed via the type system at compile
time. It’s should be obvious that given &lt;code&gt;F&lt;/code&gt; and &lt;code&gt;G&lt;/code&gt;, then an
&lt;code&gt;Iterant[F, A]&lt;/code&gt; cannot be composed with an &lt;code&gt;Iterant[G, A]&lt;/code&gt;. So an
&lt;code&gt;Iterant[Task, A]&lt;/code&gt; (see
&lt;a href=&quot;https://monix.io/docs/2x/eval/task.html&quot;&gt;Task&lt;/a&gt;) cannot be composed
with an &lt;code&gt;Iterant[Coeval, A]&lt;/code&gt; (see
&lt;a href=&quot;https://monix.io/docs/2x/eval/coeval.html&quot;&gt;Coeval&lt;/a&gt;), or with an
&lt;code&gt;Iterant[IO, A]&lt;/code&gt; (see
&lt;a href=&quot;https://github.com/typelevel/cats-effect/blob/v0.8/core/shared/src/main/scala/cats/effect/IO.scala&quot;&gt;IO&lt;/a&gt;),
unless you convert between these data types explicitly.&lt;/p&gt;

&lt;p&gt;For example this should trigger a compile time error:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val tasks: Iterant[Task, Int] = ???
val ios: Iterant[IO, Int] = ???

// Nope, can&apos;t do this ;-)
tasks ++ ios
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: constrained parametric polymorphism via type-classes
can give you super powers by effectively outsourcing the processing to
pluggable data types with various capabilities, the restrictions being on
the operations themselves!
&lt;/p&gt;

&lt;h3 id=&quot;42-liskov-substitution-principle-oop-strikes-back&quot;&gt;4.2. Liskov Substitution Principle: OOP Strikes Back&lt;/h3&gt;

&lt;p&gt;That last example should make you think - parametric polymorphism implies:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;exposing &lt;code&gt;F&lt;/code&gt; type parameters at compile time&lt;/li&gt;
  &lt;li&gt;homogeneity&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because on top of Scala we are looking for opportunities to optimize
performance, due to the runtime not being optimized for laziness and
&lt;code&gt;IO&lt;/code&gt; data types (like Haskell), we want to process items in batches,
where possible. For example we’d like to stream arrays, because arrays
are contiguous memory blocks and if you don’t find ways to work with
arrays, then you’re screwed in terms of throughput:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class NextBatch[F[_], A](
  batch: Array[A],
  rest: F[Iterant[F, A]],
  stop: F[Unit])
  extends Iterant[F, A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But why only arrays? What if we allowed Scala’s &lt;code&gt;List&lt;/code&gt; or &lt;code&gt;Vector&lt;/code&gt; as
well? There’s no harm in that and it would still have better
throughput, so might as well use Scala’s
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/Seq.html&quot;&gt;Seq&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class NextBatch[F[_], A](
  batch: Seq[A],
  rest: F[Iterant[F, A]],
  stop: F[Unit])
  extends Iterant[F, A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But wait, because somebody told us that OOP sucks or that the standard
collections should not have a hierarchy, lets use type parameters, like we
did with &lt;code&gt;F&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class NextBatch[F[_], Seq[_], A](
  batch: Seq[A],
  rest: F[Iterant[F, A]],
  stop: F[Unit])
  extends Iterant[F, A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh wait, this doesn’t work, unless we’d expose &lt;code&gt;Seq[_]&lt;/code&gt; in &lt;code&gt;Iterant&lt;/code&gt; as well:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed trait Iterant[F[_], Seq[_], A]

case class NextBatch[F[_], Seq[_], A](
  batch: Seq[A],
  rest: F[Iterant[F, A]],
  stop: F[Unit])
  extends Iterant[F, Seq, A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But this sucks, not only due to the types getting more complicated
(your Scala compiler is giving you ugly looks right about now), but
also because you can’t have heterogeneity:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val node1 = NextBatch(Array(1,2,3), IO(Halt(None)), IO.unit)
// Ooops, not compatible, List is not Array, will trigger error ;-)
val node2 = NextBatch(List(1,2,3), IO(node1), IO.unit)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;No, screw that, let’s backtrack - at this point we need
the type class restriction to be on the data structure itself:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class NextBatch[F[_], Seq[_], A](
  batch: Seq[A],
  rest: F[Iterant[F, A]],
  stop: F[Unit])
  (implicit Seq: Foldable[Seq])
  extends Iterant[F, A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s better, right?&lt;/p&gt;

&lt;p&gt;Wrong - if you’re passing that type-class instance around, that’s
effectively a
&lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_method_table&quot;&gt;vtable&lt;/a&gt; so
congratulations, you have an OOP encoding with extra garbage.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: with constrained parametric polymorphism you
either expose the data type as a type parameter, making types more
complicated and saying goodbye to heterogeneity, or you end up with a
shitty OOP substitute!
&lt;/p&gt;

&lt;h3 id=&quot;43-iterator-vs-foldable-and-traverse&quot;&gt;4.3. Iterator vs Foldable and Traverse&lt;/h3&gt;

&lt;p&gt;Many people are under the impression that you can substitute the classic
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/Iterator.html&quot;&gt;Iterator&lt;/a&gt;
with the &lt;a href=&quot;https://github.com/typelevel/cats/blob/v1.0.1/core/src/main/scala/cats/Foldable.scala&quot;&gt;Foldable&lt;/a&gt;
and &lt;a href=&quot;https://github.com/typelevel/cats/blob/v1.0.1/core/src/main/scala/cats/Traverse.scala&quot;&gt;Traverse&lt;/a&gt;
type-classes. This is understandable, because these type classes are
really potent, really generic, great actually.&lt;/p&gt;

&lt;p&gt;Here’s  Phil Freeman’s opinion, the creator of the PureScript language:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“
    ES2018 will include a whole new language feature in order to
    implement one instantiation of “traverse”. I’ll say it again - JS
    won’t be fixed by adding more
    things. &lt;a href=&quot;http://2ality.com/2017/02/ecmascript-2018.html&quot;&gt;2ality.com/2017/02/ecmascript-2018.html&lt;/a&gt;
  ”&lt;/em&gt;&lt;/p&gt;
  &lt;footer&gt;
    &lt;p&gt;
      &lt;a href=&quot;https://x.com/paf31/status/960270750903975936&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
    &lt;/p&gt;
  &lt;/footer&gt;
&lt;/blockquote&gt;

&lt;p&gt;But that is simply &lt;em&gt;false&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the big difference: &lt;code&gt;Iterator&lt;/code&gt; allows you to &lt;em&gt;pause&lt;/em&gt; the
processing, until the current iteration cycle has finished, before
processing the next item, being a pull-based protocol with the user
being &lt;em&gt;completely in charge&lt;/em&gt;. The user being responsible for advancing
the cursor to the next item, whenever he wants, in a destructive
manner is also what makes it error prone, but it’s flexible
nonetheless.&lt;/p&gt;

&lt;p&gt;So for example, how do you think this works?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val ios: Iterable[IO[Int]] = ???

ios.foldLeft(IO(0)) { (acc, elem) =&gt;
  for (a &lt;- acc; e &lt;- elem) yield a + e
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The short answer - it works, but if that stream is too big, it will
blow up your process because there’s no back-pressure in that fold.
But I digress.&lt;/p&gt;

&lt;p&gt;Iterating over arrays in our &lt;code&gt;NextBatch&lt;/code&gt; might prove tricky but is
doable, for example in a &lt;code&gt;mapEval&lt;/code&gt; implementation that needs to pop an
item out of our &lt;code&gt;Array&lt;/code&gt;, process that in the &lt;code&gt;F[_]&lt;/code&gt; monadic context,
then continue from where it left off:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def mapEval[F[_], A](fa: Iterant[F, A])(f: A =&gt; F[B])
  (implicit F: Sync[F]): Iterant[F, B] = {

  def loop(index: Int)(fa: Iterant[F, A]): Iterant[F, B] =
    fa match {
      case NextBatch(batch, rest, stop) =&gt;
        val eval =
          if (index &gt;= batch.length)
            rest.map(loop(0))
          else
            f(batch(index)).map { a =&gt;
              Next(a, F.pure(loop(index + 1)(fa)), stop)
            }
        Suspend(eval, stop)

      case _ =&gt; ???
    }
  loop(0)(fa)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, &lt;code&gt;Array&lt;/code&gt; can be indexed, but that indexing would be death for
&lt;code&gt;List&lt;/code&gt;, isn’t it?&lt;/p&gt;

&lt;p&gt;Turns out we have a perfectly capable abstraction for iterating over
arrays, lists, vectors or what have you, the classic
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/Iterator.html&quot;&gt;Iterator&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class NextCursor[F[_], A](
  cursor: Iterator[A],
  rest: F[Iterant[F, A]],
  stop: F[Unit])
  extends Iterant[F, A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now we can express this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def mapEval[F[_], A](fa: Iterant[F, A])(f: A =&gt; F[B])
  (implicit F: Sync[F]): Iterant[F, B] = {

  def loop(fa: Iterant[F, A]): Iterant[F, B] =
    fa match {
      case NextBatch(batch, rest, stop) =&gt;
        loop(NextCursor(batch.iterator(), rest, stop))
      case NextCursor(cursor, rest, stop) =&gt;
        val eval =
          if (cursor.hasNext)
            rest.map(loop)
          else
            f(batch.next()).map { a =&gt;
              Next(a, F.pure(loop(fa)), stop)
            }
        Suspend(eval, stop)
      case _ =&gt;
        ???
    }
  // Suspends execution, because NextCursor is side-effectful ;-)
  Suspend(F.delay(loop(fa)), F.unit)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Can you do that with &lt;code&gt;Foldable&lt;/code&gt; / &lt;code&gt;Traverse&lt;/code&gt;? No, you can’t!&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
If a tree falls in a forest and no one is around to hear it, is that a
&lt;a href=&quot;https://en.wikipedia.org/wiki/Side_effect_(computer_science)&quot;&gt;&lt;i&gt;side effect&lt;/i&gt;&lt;/a&gt;?
&lt;br&gt;&lt;br&gt;
The &lt;code&gt;Iterator&lt;/code&gt; interface relies on side effects and is thus
incompatible with functional programming. However if its mutation is
properly suspended and encapsulated, such that &lt;i&gt;referential
transparency&lt;/i&gt; is preserved, then it really doesn’t matter 😉
&lt;/p&gt;

&lt;p&gt;To work with type-classes and pure functions, our first intuition
should be something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait IteratorTypeClass[F[_]] {
  def next[A](fa: F[A]): Option[(A, F[A])]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a variation on the
&lt;a href=&quot;https://wiki.haskell.org/State_Monad&quot;&gt;state monad&lt;/a&gt;, because yes,
we’ve got state to evolve.&lt;/p&gt;

&lt;p&gt;Here’s the performance characteristics of such a decomposition
for the &lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt; operations, needed for this type
class:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;http://www.scala-lang.org/api/2.12.4/scala/collection/immutable/Vector.html&quot;&gt;Vector&lt;/a&gt;,
has “&lt;em&gt;effectively constant time&lt;/em&gt;”, which is worse than &lt;code&gt;List&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;http://www.scala-lang.org/api/2.12.4/scala/collection/immutable/Queue.html&quot;&gt;Queue&lt;/a&gt;
has “&lt;em&gt;amortized constant time&lt;/em&gt;”, which is worse than &lt;code&gt;List&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;http://www.scala-lang.org/api/2.12.4/scala/Array.html&quot;&gt;Array&lt;/a&gt;
has linear O(N) time for &lt;code&gt;tail&lt;/code&gt;, aka you can change your job now&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, &lt;code&gt;Iterator&lt;/code&gt; is efficient for all of them, so it wins by a wide
margin. The above is actually horrible and why a type class like
that isn’t popular, because it relies on &lt;code&gt;List&lt;/code&gt;’s encoding to be
efficient 😉&lt;/p&gt;

&lt;p&gt;So that’s not it. The pure type-class equivalent is actually this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait IteratorTypeClass[F[_]] {
  type Pointer[T]

  def start[A](fa: F[A]): Pointer[A]
  def next[A](fa: F[A], cursor: Pointer[A]): Option[(A, Pointer[A])]
}

// Sample instance for Array
object ArrayIterator extends IteratorTypeClass[Array] {
  type Pointer[T] = Int

  def start[A](fa: Array[A]) = 0
  def next[A](fa: Array[A], cursor: Int) =
    if (cursor &gt;= fa.length) None
    else Some((fa(cursor), cursor + 1))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But this will leak implementation details - not bad for our &lt;code&gt;Array&lt;/code&gt;
instance, but what if we had some sort of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree&quot;&gt;self-balancing tree&lt;/a&gt;
which you then changed to a
&lt;a href=&quot;https://en.wikipedia.org/wiki/Hash_array_mapped_trie&quot;&gt;HAMT&lt;/a&gt;.
In that case our &lt;code&gt;Pointer&lt;/code&gt; would be some sort of node with links
to its neighbors, so is it wise exposing it like that? How
is Haskell’s binary compatibility anyway? Does it even support
dynamic linking?&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: &lt;code&gt;Iterator&lt;/code&gt; actually beats pure, type-class
based solution in performance, flexibility or encapsulation! It’s
also lower-level, impure and error prone, but sorely needed sometimes.
&lt;/p&gt;

&lt;h2 id=&quot;5-seq-my-love&quot;&gt;5. Seq My Love&lt;/h2&gt;

&lt;p&gt;I actually like
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/Seq.html&quot;&gt;Seq&lt;/a&gt;
and have never regretted using it.&lt;/p&gt;

&lt;p&gt;Not everybody agrees and as mentioned in section
&lt;a href=&quot;#23-seq-or-other-super-types&quot;&gt;2.3.&lt;/a&gt;, there are people advising against its usage:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“
    You always care about the asymptotic properties of your data
    structures. So there is never a case where Seq makes sense, even as
    a concept!
  ”&lt;/em&gt;&lt;/p&gt;
  &lt;footer&gt;
    &lt;p&gt;
      &lt;a href=&quot;https://x.com/djspiewak/status/962767948774457344&quot;&gt;Daniel Spiewak&lt;/a&gt;
    &lt;/p&gt;
  &lt;/footer&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s why I disagree …&lt;/p&gt;

&lt;h3 id=&quot;51-seq-on-return&quot;&gt;5.1. Seq on Return&lt;/h3&gt;

&lt;p&gt;Returning &lt;code&gt;Seq&lt;/code&gt; from a function gives you the freedom to change the
implementation and this works well because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;you preserve backwards binary compatibility&lt;/li&gt;
  &lt;li&gt;users might only care to traverse it / fold it, which should be an
O(n) operation for any sequence&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Real use-case from Monix, the
&lt;a href=&quot;https://github.com/monix/monix/blob/v3.0.0-M3/monix-reactive/shared/src/main/scala/monix/reactive/Observable.scala#L372&quot;&gt;Observable.bufferSliding&lt;/a&gt;
operator:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;/** Returns an observable that emits buffers of items it collects from
  * the source observable. The resulting observable emits buffers
  * every `skip` items, each containing `count` items.
  *
  * If the source observable completes, then the current buffer gets
  * signaled downstream. If the source triggers an error then the
  * current buffer is being dropped and the error gets propagated
  * immediately.
  *
  * For `count` and `skip` there are 3 possibilities:
  *
  *  1. in case `skip == count`, then there are no items dropped and
  *     no overlap, the call being equivalent to `buffer(count)`
  *  1. in case `skip &lt; count`, then overlap between buffers
  *     happens, with the number of elements being repeated being
  *     `count - skip`
  *  1. in case `skip &gt; count`, then `skip - count` elements start
  *     getting dropped between windows
  *
  * @param count the maximum size of each buffer before it should
  *        be emitted
  * @param skip how many items emitted by the source observable should
  *        be skipped before starting a new buffer. Note that when
  *        skip and count are equal, this is the same operation as
  *        `buffer(count)`
  */
final def bufferSliding(count: Int, skip: Int): Observable[Seq[A]] =
  liftByOperator(new BufferSlidingOperator(count, skip))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Facts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/monix/monix/blob/v3.0.0-M1/monix-reactive/shared/src/main/scala/monix/reactive/internal/operators/BufferSlidingOperator.scala#L43&quot;&gt;current version (3.0.0-M3)&lt;/a&gt;
uses an &lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/Array.html&quot;&gt;Array&lt;/a&gt;
as the internal buffer, emitting arrays
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/mutable/WrappedArray.html&quot;&gt;wrapped in Seq&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/monix/monix/blob/v2.0.0/monix-reactive/shared/src/main/scala/monix/reactive/internal/operators/BufferSlidingOperator.scala#L41&quot;&gt;version 2.0.0&lt;/a&gt;
used a &lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/mutable/ListBuffer.html&quot;&gt;ListBuffer&lt;/a&gt;,
thus emitting &lt;code&gt;List&lt;/code&gt; chunks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The change from &lt;code&gt;List&lt;/code&gt; to &lt;code&gt;Array&lt;/code&gt; was done:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;without breaking backwards compatibility&lt;/li&gt;
  &lt;li&gt;with no consequence to the user, since these chunks are meant to be
&lt;i&gt;small and manageable&lt;/i&gt;, so all the user cares about is being
able to traverse or fold them or to convert them into something else&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the infamous “&lt;em&gt;program to an interface, not to an implementation&lt;/em&gt;”
mantra that OOP developers like to repeat so much. You won’t
actually need this capability that often, but when you do, it’s golden.&lt;/p&gt;

&lt;p&gt;Also note that when using a super-type such as &lt;code&gt;Seq&lt;/code&gt; in an interface, due to the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)&quot;&gt;covariance&lt;/a&gt;
of return types, you’re always allowed to override with a more
specific type in implementing classes (e.g.  to go from &lt;code&gt;Seq&lt;/code&gt; to
&lt;code&gt;List&lt;/code&gt;), and the Liskov substitution principle still applies.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: there are perfectly valid use-cases for &lt;code&gt;Seq&lt;/code&gt; as the return type!
&lt;/p&gt;

&lt;h3 id=&quot;52-seq-on-input&quot;&gt;5.2. Seq on Input&lt;/h3&gt;

&lt;p&gt;The necessity for &lt;code&gt;Seq&lt;/code&gt; is the same as for
&lt;a href=&quot;https://github.com/typelevel/cats/blob/v1.0.1/core/src/main/scala/cats/Foldable.scala&quot;&gt;Foldable&lt;/a&gt;,
the need to traverse a collection, aggregating its items into some final result.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Seq&lt;/code&gt; also implies that items come in a
&lt;a href=&quot;https://en.wikipedia.org/wiki/Sequence&quot;&gt;sequence&lt;/a&gt; in which order
matters and repetition is allowed. For example a
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/immutable/Set.html&quot;&gt;Set&lt;/a&gt;
shouldn’t be a &lt;code&gt;Seq&lt;/code&gt;, because &lt;code&gt;Set&lt;/code&gt; does not allow repetition and has
no ordering.&lt;/p&gt;

&lt;p&gt;So here’s another real-world use-case, also from Monix, the
&lt;a href=&quot;https://github.com/monix/monix/blob/v3.0.0-M3/monix-reactive/shared/src/main/scala/monix/reactive/Observable.scala#L2148&quot;&gt;Observable.startWith&lt;/a&gt;
operator:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;/** Creates a new Observable that emits the given elements and then
  * it also emits the events of the source (prepend operation).
  */
final def startWith[B &gt;: A](elems: Seq[B]): Observable[B] =
  Observable.fromIterable(elems) ++ self
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we might have used an
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/Iterator.html&quot;&gt;Iterator&lt;/a&gt;,
however the result wouldn’t have been pure and we might have used an
&lt;a href=&quot;https://www.scala-lang.org/api/2.12.4/scala/collection/Iterable.html&quot;&gt;Iterable&lt;/a&gt;,
but as the author of this operator I felt that the input being a sequence
is important for getting back a predictable result - after all, that ordering
is important is implied by what this operator does.&lt;/p&gt;

&lt;p&gt;And note that all the implementation does is to care about traversal, via
an &lt;code&gt;Iterator&lt;/code&gt; loop.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;b&gt;&lt;u&gt;TL;DR&lt;/u&gt;&lt;/b&gt;: yes, there are perfectly valid use-cases for &lt;code&gt;Seq&lt;/code&gt; as the input!
&lt;/p&gt;

&lt;h2 id=&quot;6-conclusion&quot;&gt;6. Conclusion&lt;/h2&gt;

&lt;p&gt;Here’s a summary:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;#21-canbuildfrom&quot;&gt;2.1.&lt;/a&gt; — &lt;code&gt;CanBuildFrom&lt;/code&gt; was a clever solution to an
exagerated problem, but you’ll no longer have to worry about
it&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;#22-complex-hierarchy&quot;&gt;2.2.&lt;/a&gt; — a complex OOP hierarchy, as clever as it may be,
brings with it complexity beyond reason and is counter-productive
for subtype polymorphism&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;#23-seq-or-other-super-types&quot;&gt;2.3.&lt;/a&gt; — OOP interfaces might expose leaky operations that are
booby traps (e.g. &lt;code&gt;Seq&lt;/code&gt; indexing), but this is not specific to OOP
interfaces, vigilance in design is always needed&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;#24-not-using-type-classes&quot;&gt;2.4.&lt;/a&gt; — type-classes are nice, playing well with
parametric polymorphism, but in Scala the syntax is heavier than
when using OOP, although this isn’t an issue with Haskell&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;#3-oop-vs-constrained-parametric-polymorphism-type-classes&quot;&gt;3.&lt;/a&gt; with Scala you can actually pick and choose the best
approach - this can lead to choice paralysis however and lots of
drama&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;#41-type-classes-for-super-powers&quot;&gt;4.1.&lt;/a&gt; — constrained parametric polymorphism via type-classes
can give you super powers by effectively outsourcing the processing
to pluggable data types with various capabilities, the restrictions
being on the operations themselves&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;#42-liskov-substitution-principle-oop-strikes-back&quot;&gt;4.2.&lt;/a&gt; — with constrained parametric polymorphism you either
expose the data type as a type parameter, making types more
complicated and saying goodbye to heterogeneity, or you end up with
a shitty OOP substitute&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;#43-iterator-vs-foldable-and-traverse&quot;&gt;4.3.&lt;/a&gt; — &lt;code&gt;Iterator&lt;/code&gt; actually beats pure, type-class based
solution in performance, flexibility or encapsulation. It’s also
lower-level, impure and error prone, but sorely needed sometimes&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;#51-seq-on-return&quot;&gt;5.1.&lt;/a&gt; — there are perfectly valid use-cases for &lt;code&gt;Seq&lt;/code&gt; as
the return type&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;#52-seq-on-input&quot;&gt;5.2.&lt;/a&gt; — there are perfectly valid use-cases for &lt;code&gt;Seq&lt;/code&gt; as
the input&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So yes, there will be people out there, such as myself, genuinely enjoying
Scala’s OOP and the new collections.&lt;/p&gt;

&lt;p&gt;Thanks for reading ️❤️&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2018/02/12/in-defense-oofp/?pk_campaign=rss&quot;&gt;In Defense of OOFP&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 12 Feb 2018 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2018/02/12/in-defense-oofp/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2018/02/12/in-defense-oofp/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Best Of</category>
  <category>OOP</category>
  <category>FP</category>
  <category>Haskell</category>
  <category>Scala</category>
  </item>


<item>
  <title>Minitest: Zero Crap Scala Testing Library</title>
  <description>Minitest is my minimal testing library that I’ve been using for developing Monix.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2017/11/10/minitest-no-crap-scala-library/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;&lt;a href=&quot;https://github.com/monix/minitest&quot;&gt;Minitest&lt;/a&gt; is my minimal testing library that I’ve been using for developing &lt;a href=&quot;https://monix.io&quot;&gt;Monix&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;raison-dêtre&quot;&gt;Raison d’être&lt;/h2&gt;

&lt;p&gt;I dislike most testing frameworks, because of bloat and of heavy DSLs
trying to mimic the English language. When I created Minitest, I
wasn’t satisfied with any of the available alternatives.&lt;/p&gt;

&lt;p&gt;Then I found that &lt;a href=&quot;http://www.scala-sbt.org/&quot;&gt;SBT&lt;/a&gt; can do all the
heavy lifting (e.g. running the tests, reporting, etc), exposing a
nice &lt;a href=&quot;https://github.com/sbt/test-interface&quot;&gt;sbt/test-interface&lt;/a&gt; that
you can integrate with. All you need to do is to build your own
API on top. And so I did.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; My opinions in this article disagree with the design
choices of popular testing libraries. I know that libraries like
&lt;a href=&quot;http://www.scalatest.org/&quot;&gt;ScalaTest&lt;/a&gt; or
&lt;a href=&quot;https://etorreborre.github.io/specs2/&quot;&gt;Specs2&lt;/a&gt; are the way they
are because people want them that way. And those are awesome
projects, having awesome authors. They are just not for me.
&lt;/p&gt;

&lt;h3 id=&quot;portability&quot;&gt;Portability&lt;/h3&gt;

&lt;p&gt;The natural tendency of testing frameworks is to grow beyond all
imagination in order to accommodate the various testing styles that
people want, these testing frameworks also end up hard to port to new
platforms - which is especially relevant in Scala due to new major
versions and new targets released all the time
(e.g. &lt;a href=&quot;http://www.scala-js.org/&quot;&gt;Scala.js&lt;/a&gt;, &lt;a href=&quot;https://github.com/scala-native/scala-native&quot;&gt;Scala
Native&lt;/a&gt;,
&lt;a href=&quot;https://github.com/lampepfl/dotty&quot;&gt;Dotty&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In 2014 I started to work on &lt;a href=&quot;https://monix.io&quot;&gt;Monix&lt;/a&gt; and during that
time &lt;a href=&quot;http://www.scala-js.org/&quot;&gt;Scala.js&lt;/a&gt; was also born.&lt;/p&gt;

&lt;p&gt;This awesome Scala compiler that targets JavaScript was really fresh
back then and I wanted to target it, however none of the testing
libraries (e.g. &lt;a href=&quot;http://www.scalatest.org/&quot;&gt;ScalaTest&lt;/a&gt;) were
supporting it yet, except for
&lt;a href=&quot;https://github.com/lihaoyi/utest&quot;&gt;µTest&lt;/a&gt;. µTest seemed fine, but it
had problems when displaying error messages, plus its DSL was and
still is weird.&lt;/p&gt;

&lt;p&gt;For some reason I don’t like magic in my tests — and by magic I mean
expressions or statements that I don’t immediately understand. That,
and I wanted an easy transition in Monix from ScalaTest’s
&lt;a href=&quot;http://www.scalatest.org/getting_started_with_fun_suite&quot;&gt;FunSuite&lt;/a&gt;,
which is what I was using.&lt;/p&gt;

&lt;h3 id=&quot;say-no-to-dsls&quot;&gt;Say No to DSLs&lt;/h3&gt;

&lt;p&gt;I do not want to write &lt;code&gt;x shouldBe greaterThan(y)&lt;/code&gt; or other such
nonsense. I do not have the memory for that, I always forget the API
and the IDE doesn’t help much due to the implicit conversions going on.&lt;/p&gt;

&lt;p&gt;Unit tests might be business driven, but so is software in
general, nothing makes tests a special snowflake to warrant the abuse
of the programming language to make it look like English.&lt;/p&gt;

&lt;p&gt;Yes, there are advantages to such a DSL. For example if you express
the above with a simple &lt;code&gt;assert&lt;/code&gt;, then you won’t get a meaningful
error message back, depending on whether the implementation does or
doesn’t do macros for &lt;code&gt;assert&lt;/code&gt;, but if it does, then that’s a whole
other can of worms:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;assert(x &gt; y)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Fact:&lt;/strong&gt; most assertions that you need to do in testing are &lt;em&gt;equality
tests&lt;/em&gt; and for that rare moment in which you need inequality tests, you
can simply add a custom error message:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;assert(x &gt; y, s&quot;$x &gt; $y&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yes, it’s repetitive, but I don’t care, because this is such a rare
event that I don’t want to optimize it with a special DSL or even with
macros.&lt;/p&gt;

&lt;p&gt;Another thing that I absolutely hate are tests marked with English
words like “&lt;code&gt;it&lt;/code&gt;”, forcing you to phrase the test’s description in a
certain way. I frequently end up with “sentences” that makes no sense:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;it(&quot;left identity&quot;) {
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This tendency actually stems from Java OOP, with its “kingdom of
nouns”, the idea being that the things you’re testing are all nouns
that interact with the world, aka objects. Well, I’m not testing just
objects, so &lt;code&gt;it&lt;/code&gt; is a bad trend.&lt;/p&gt;

&lt;p&gt;And the idea that business folks might be writing tests, hell no, that
almost never happens and if they are inclined to do that (like once in
a million), then they can just learn programming. It’s not like an
English-like DSL is any closer to natural language.&lt;/p&gt;

&lt;h3 id=&quot;minimal-implementation-less-is-more&quot;&gt;Minimal Implementation, Less is More&lt;/h3&gt;

&lt;p&gt;Because the implementation is minimal, there’s nothing that I can’t
fix in it, there’s nothing that I can’t implement should I need
anything.&lt;/p&gt;

&lt;p&gt;It’s also easy to port to new targets. I intend to port it to
&lt;a href=&quot;https://github.com/scala-native/scala-native&quot;&gt;Scala Native&lt;/a&gt; as soon as it
is available for Scala 2.12 (at the moment of writing, it isn’t).&lt;/p&gt;

&lt;p&gt;In fact, if you want to build your own testing framework, Minitest can
serve as a sample ;-)&lt;/p&gt;

&lt;h2 id=&quot;hypothesis&quot;&gt;Hypothesis&lt;/h2&gt;

&lt;p&gt;All you need is the ability to express:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;synchronous tests, returning &lt;code&gt;Unit&lt;/code&gt; (or an equivalent, as I ended
up doing in order to avoid Scala’s annoying implicit conversion)&lt;/li&gt;
  &lt;li&gt;asynchronous tests, returning &lt;code&gt;Future&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;the ability to setup an environment before every test, then
tear it down after each test&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All the asserts that you need:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;code&gt;assert(boolean, string?)&lt;/code&gt;: general purpose assertion for any
condition&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;assertEquals(received, expected)&lt;/code&gt;: for equality testing with a
nice error message&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;intercept&lt;/code&gt;: for testing that exceptions are thrown&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;fail(reason?)&lt;/code&gt;: fails the current test&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;ignore(reason?)&lt;/code&gt;: ignores the current test&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;cancel(reason?)&lt;/code&gt;: cancels the current test&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What you don’t need:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;nesting in tests&lt;/li&gt;
  &lt;li&gt;an English-like DSL&lt;/li&gt;
  &lt;li&gt;a purely functional &lt;em&gt;base&lt;/em&gt; API&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;tutorial&quot;&gt;Tutorial&lt;/h2&gt;

&lt;p&gt;Test suites MUST BE objects, not classes. To create a simple test
suite, it could inherit from &lt;code&gt;SimpleTestSuite&lt;/code&gt;. Here’s a simple test:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import minitest.SimpleTestSuite

object MySimpleSuite extends SimpleTestSuite {
  test(&quot;should be&quot;) {
    assertEquals(2, 1 + 1)
  }

  test(&quot;should not be&quot;) {
    assert(1 + 1 != 3)
  }

  test(&quot;should throw&quot;) {
    class DummyException extends RuntimeException(&quot;DUMMY&quot;)
    def test(): String = throw new DummyException

    intercept[DummyException] {
      test()
    }
  }

  test(&quot;test result of&quot;) {
    assertResult(&quot;hello world&quot;) {
      &quot;hello&quot; + &quot; &quot; + &quot;world&quot;
    }
  }

  test(&quot;should be ignored&quot;) {
    if (Platform.isJS) ignore(&quot;Blocking not supported on top of JS&quot;)
    val r = Await.result(Future(1), Duration.Inf)
    assertEquals(r, 1)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In case you want to setup an environment for each test and need
&lt;code&gt;setup&lt;/code&gt; and &lt;code&gt;tearDown&lt;/code&gt; semantics, you could inherit from
&lt;a href=&quot;https://github.com/monix/minitest/blob/v2.0.0/shared/src/main/scala/minitest/TestSuite.scala&quot;&gt;TestSuite&lt;/a&gt;.
Then on each &lt;code&gt;test&lt;/code&gt; definition, you’ll receive a fresh value:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import monix.execution.schedulers.TestScheduler
import minitest.TestSuite

object MyTestSuite extends TestSuite[TestScheduler] {
  def setup() = TestScheduler()

  def tearDown(env: TestScheduler): Unit =
    assert(env.state.tasks.isEmpty, &quot;Scheduler should not have tasks left&quot;)

  test(&quot;simulated async&quot;) { implicit ec =&gt;
    val f = Future(1).map(_ + 1)
    ec.tick()

    assertEquals(f.value, Some(Success(2)))
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Minitest supports asynchronous results in tests, just use &lt;code&gt;testAsync&lt;/code&gt;
and return a &lt;code&gt;Future[Unit]&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent.ExecutionContext.Implicits.global

object MySimpleSuite extends SimpleTestSuite {
  testAsync(&quot;asynchronous execution&quot;) {
    val future = Future(100).map(_+1)

    for (result &lt;- future) yield {
      assertEquals(result, 101)
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Minitest has integration with
&lt;a href=&quot;https://www.scalacheck.org/&quot;&gt;ScalaCheck&lt;/a&gt;.
So for property-based testing:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import minitest.laws.Checkers

object MyLawsTest extends SimpleTestSuite with Checkers {
  test(&quot;addition of integers is commutative&quot;) {
    check2((x: Int, y: Int) =&gt; x + y == y + x)
  }

  test(&quot;addition of integers is transitive&quot;) {
    check3((x: Int, y: Int, z: Int) =&gt; (x + y) + z == x + (y + z))
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s everything!&lt;/p&gt;

&lt;h2 id=&quot;common-complaints&quot;&gt;Common Complaints&lt;/h2&gt;

&lt;h3 id=&quot;i-do-not-like-future&quot;&gt;I do not like Future&lt;/h3&gt;

&lt;p&gt;That’s too bad, because the &lt;code&gt;Future&lt;/code&gt; is needed by the runtime and
regardless what alternative you use (e.g. &lt;code&gt;cats.effect.IO&lt;/code&gt;,
&lt;code&gt;monix.eval.Task&lt;/code&gt;), you’ll have to convert it into a &lt;code&gt;Future&lt;/code&gt; anyway.&lt;/p&gt;

&lt;p&gt;Besides, a good testing framework cannot have dependencies, because it
would end in conflict with the project’s dependencies. It’s unwise to
depend on Cats or Scalaz.&lt;/p&gt;

&lt;p&gt;And you can always build your own &lt;code&gt;testTask&lt;/code&gt;, &lt;code&gt;testEffect&lt;/code&gt; or &lt;code&gt;testIO&lt;/code&gt;
utilities on top of &lt;code&gt;testAsync&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;i-want-a-purely-functional-api&quot;&gt;I want a purely functional API&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://etorreborre.github.io/specs2/&quot;&gt;Specs2&lt;/a&gt; has a nice functional
API. You might like that, however I don’t like it for all the reasons
stated above.&lt;/p&gt;

&lt;p&gt;And if pure FP is what you want, nothing stops you from implementing
your own utilities and I recommend piggybacking on ScalaCheck, e.g:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import cats.effect.IO
import org.scalacheck.{Prop, Test}
import scala.concurrent.ExecutionContext.Implicits.global

trait PureTestSuite extends minitest.api.AbstractTestSuite {
  private[this] val ts = new SimpleTestSuite {}
  lazy val properties = ts.properties

  def test(name: String)(f: =&gt; Prop): Unit =
    ts.test(name) {
      val result = Test.check(config, f)
      if (!result.passed) fail(Pretty.pretty(result))
    }

  def testIO(name: String)(f: =&gt; IO[Prop]): Unit =
    ts.testAsync(name) {
      f.unsafeToFuture.map { result =&gt;
        val result = Test.check(config, f)
        if (!result.passed) fail(Pretty.pretty(result))
      }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There’s your purely functional API in just a couple of lines of code.&lt;/p&gt;

&lt;p&gt;I don’t want that in Monix though - the integration that we have with
ScalaCheck is minimal and enough.&lt;/p&gt;

&lt;h3 id=&quot;it-does-not-support-maven-cbt-or-others&quot;&gt;It does not support Maven, CBT or others&lt;/h3&gt;

&lt;p&gt;Sorry about that, but this library is meant to be minimal and stable,
and I don’t have the time to expand support beyond SBT right now.&lt;/p&gt;

&lt;p&gt;Pull requests open and only accepted if they don’t complicate the
codebase much.&lt;/p&gt;

&lt;h2 id=&quot;final-words&quot;&gt;Final Words&lt;/h2&gt;

&lt;p&gt;Forget DSLs.&lt;/p&gt;

&lt;p&gt;All you need for testing are
&lt;a href=&quot;https://github.com/monix/minitest/&quot;&gt;Minitest&lt;/a&gt; and
&lt;a href=&quot;https://www.scalacheck.org/&quot;&gt;ScalaCheck&lt;/a&gt;.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2017/11/10/minitest-no-crap-scala-library/?pk_campaign=rss&quot;&gt;Minitest: Zero Crap Scala Testing Library&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 10 Nov 2017 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2017/11/10/minitest-no-crap-scala-library/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2017/11/10/minitest-no-crap-scala-library/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Testing</category>
  <category>Scala</category>
  </item>


<item>
  <title>What is Functional Programming?</title>
  <description>FP is programming with (mathematical) functions, there’s no room for interpretation.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2017/10/15/functional-programming/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/functions.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;900&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;Functional Programming (FP) is programming with &lt;em&gt;functions&lt;/em&gt;. &lt;a href=&quot;https://goo.gl/q8dToC&quot;&gt;Mathematical functions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There’s no other definition that’s correct, unless it’s equivalent
to this one. There’s no other definition that matters.&lt;/p&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;

&lt;p&gt;I first read the rigorous definition of a mathematical function
in my first year of high-school, the 9-th grade. A &lt;em&gt;function&lt;/em&gt;
represents a unique association between elements of a domain
(the input set) to the elements of a codomain (the output
set). This means that applying the function to some input, you always
get the same output.&lt;/p&gt;

&lt;p&gt;My 9-th grade self actually read this in a high-school math manual:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Given f: A → B, ∀ x,y ∈ A
If f(x) ≠ f(y) then x ≠ y
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And in my young mind this condition seemed obvious and redundant, but
that’s what you get with mathematical rigorosity, which in our
profession is sorely needed.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
Given that I’m from Romania, being exposed to an education centered
on rote learning, influenced by the French and the Russian / Soviet
educational systems, I’m now pretty sure that I have an atypical background,
compared to my U.S. peers. &lt;br&gt;&lt;br&gt; For example we learned some
category theory in our 12-th grade, of which I’m grateful, being really
intriguing to me how some 6-figures Ivy League graduates can complain about
never hearing of the word &lt;code&gt;Monoid&lt;/code&gt;, or having to learn the math material of
normal teenagers. And don’t get me wrong, our educational system isn’t great,
being in a continued decline.
&lt;/p&gt;

&lt;p&gt;If you want to get even more technical, functional programming has
at its foundation the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Lambda_calculus&quot;&gt;Lambda Calculus&lt;/a&gt;, a
system for expressing computations that is equivalent to Turing
machines, a universal model of computation built on function
abstraction and application.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
Some languages like Haskell are actually compiled / reduced to
an intermediate language that’s very close to Lambda Calculus,
which is cool to have as a theoretical foundation, because then you
can prove things about your language and have the ability to add new
features safely, e.g. without risking type unsoundness. As an aside, Scala
doesn’t have that luxury because it’s also an OOP language, so they are
developing &lt;a href=&quot;http://lampwww.epfl.ch/%7Eamin/dot/soundness_oopsla16.pdf&quot;&gt;DOT calculus&lt;/a&gt;
as an alternative. Interesting stuff.
&lt;/p&gt;

&lt;h2 id=&quot;why-functional-programming&quot;&gt;Why Functional Programming?&lt;/h2&gt;

&lt;p&gt;Many people are enamored with Functional Programming because it
gives us:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Referential_transparency&quot;&gt;Referential Transparency&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.haskell.org/Equational_reasoning_examples&quot;&gt;Equational Reasoning&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Software has
&lt;a href=&quot;http://www.cs.nott.ac.uk/~pszcah/G51ISS/Documents/NoSilverBullet.html&quot;&gt;essential complexity&lt;/a&gt;
in it and it doesn’t help that our tools also contribute a decent
amount of accidental complexity. If for example you think about
&lt;a href=&quot;https://en.wikipedia.org/wiki/Asynchrony_(computer_programming)&quot;&gt;asynchrony&lt;/a&gt; and
&lt;a href=&quot;https://en.wikipedia.org/wiki/Concurrency_(computer_science)&quot;&gt;concurrency&lt;/a&gt;,
which often lead to
&lt;a href=&quot;https://en.wikipedia.org/wiki/Nondeterministic_algorithm&quot;&gt;non-determinism&lt;/a&gt;,
the challenges involved have had tremendous cost for this industry.&lt;/p&gt;

&lt;p&gt;Functional Programming keeps complexity at a manageable level because
FP components can be divorced from their surrounding context and
analysed independently. FP components can also be freely composed,
an insanely useful property in an industry where software projects
are seemingly built like houses of cards.&lt;/p&gt;

&lt;p&gt;Memory locks for example don’t compose. Two functions yielding
asynchronous results might or might not compose, depending on what
shared mutable state they access, or what condition they are waiting
on for completion.&lt;/p&gt;

&lt;p&gt;There are a few alternatives to FP, like Rust’s draconic borrow
checker, which essentially bans uncontrolled sharing. There are
advantages and disadvantages to both approaches, however if you ever
found it weird or frustrating to deal with pure functions, then
fighting Rust’s borrow checker should be even more weird or
frustrating (mind you, I think Rust is awesome, but that’s beside the
point).&lt;/p&gt;

&lt;p&gt;If you no longer require purity, if you change the definition of what
kind of “&lt;em&gt;functions&lt;/em&gt;” we can accept, then we are no longer talking of
Functional Programming, but about …&lt;/p&gt;

&lt;h2 id=&quot;procedural-programming&quot;&gt;Procedural Programming&lt;/h2&gt;

&lt;p&gt;We wouldn’t need the “&lt;em&gt;pure&lt;/em&gt;” qualification if we, as programmers,
wouldn’t overload terms.&lt;/p&gt;

&lt;p&gt;Back in the day of assembly language and Turbo Pascal, we had perfectly
good terms for impure functions, such as:
&lt;a href=&quot;https://en.wikipedia.org/wiki/Subroutine&quot;&gt;procedure, routine, subroutine&lt;/a&gt;,
these being blocks of code on which you jumped with the code pointer,
executed some side-effects, pushed some results on the stack, then
jumped back to where you were, with the contract being that such
subroutines had a single entry point and a single exit point.&lt;/p&gt;

&lt;p&gt;We have had a perfectly good term for describing programming made of
procedures / subroutines: &lt;a href=&quot;https://en.wikipedia.org/wiki/Procedural_programming&quot;&gt;Procedural Programming&lt;/a&gt; 😉&lt;/p&gt;

&lt;h3 id=&quot;impure-is-uninteresting&quot;&gt;Impure is Uninteresting&lt;/h3&gt;

&lt;p&gt;Lately the trend is to classify code making use of “lambda expressions”
as functional programming and to classify programming languages that
have “first-class functions” as being functional programming languages.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
“Lambda expressions” are anonymous functions that can capture the
variables in the scope they’ve been defined (implemented using closures).
&lt;/p&gt;

&lt;p&gt;Well, the problem is that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The venerable &lt;a href=&quot;https://goo.gl/wfmLG6&quot;&gt;C language&lt;/a&gt; has had the
ability to pass function pointers around since forever, I know
of no mainstream language that doesn’t allow you to pass function
references, which makes functions “first class”;&lt;/li&gt;
  &lt;li&gt;You don’t actually need anonymous functions for doing functional
programming, if you have an equivalent — for example Java had
“anonymous classes” before Java 8, with the newer lambda expressions
actually creating anonymous classes; take a look at this
&lt;a href=&quot;http://www.functionaljava.org/&quot;&gt;Functional Java&lt;/a&gt; library, which was
built before Java 8;&lt;/li&gt;
  &lt;li&gt;It’s 2017 and most languages in use have usable lambda expressions, except
for Python which has inherent limitations due to it being statement
oriented and the developers refusing to introduce multi-line
anonymous functions, which has led to a dozen or so non-orthogonal
features to replace the need for it, under the mantra
“&lt;em&gt;only one way of doing things&lt;/em&gt;”, which by now is surely some
kind of joke.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you reduce your “&lt;em&gt;functional programming&lt;/em&gt;” qualifier
to usage of first class (impure) functions and lambda expressions,
I think the top 15 languages and their use on GitHub qualifies.&lt;/p&gt;

&lt;h2 id=&quot;anti-intellectualism-phenomenon&quot;&gt;Anti-intellectualism Phenomenon&lt;/h2&gt;

&lt;p&gt;For all the learning that we are doing, software developers are
a really conservative bunch, unwilling to accept new concepts easily
and in this context “&lt;em&gt;new&lt;/em&gt;” is relative to what we’ve
learned either in university or at our first job. The vigor with which
we defend what we already know is proportional with the
time we’ve invested in our knowledge and whatever it is that we
are currently doing.&lt;/p&gt;

&lt;p&gt;Many people advise against mentioning “&lt;em&gt;Monad&lt;/em&gt;”, because it will
strike fear in the hearts of the unfaithful, the advice being apparently
to either sidestep the issue, to rename it into something that can
be supposedly easier to understand, or to compare it with burritos.&lt;/p&gt;

&lt;p&gt;Such efforts are like renaming “&lt;em&gt;Water&lt;/em&gt;” into “&lt;em&gt;Drinkable&lt;/em&gt;” —
which obviously makes no sense in certain contexts and deprives
people of the correct jargon for seeking help. Although I’ll grant
that “&lt;em&gt;Monad&lt;/em&gt;” is pretty awful if you’ll look at its etymology,
but it doesn’t matter, because it has evolved into a proper noun and has
been used by book authors and researchers.&lt;/p&gt;

&lt;p&gt;Anyway, want to discredit an idea, opinion, fact, or tool?
Classify it as “&lt;em&gt;academic&lt;/em&gt;”, a term that now has negative connotations,
even though most interesting breakthroughs in computer science come
from academia.&lt;/p&gt;

&lt;h2 id=&quot;can-we-do-fp-in-any-language&quot;&gt;Can We do FP in Any Language?&lt;/h2&gt;

&lt;p&gt;Yes, although some programming languages are better than others.&lt;/p&gt;

&lt;p&gt;Doing FP in a programming language like Java feels like
doing OOP in C with &lt;a href=&quot;https://en.wikipedia.org/wiki/GObject&quot;&gt;GObject&lt;/a&gt;.
Doable, but it makes one think of switching professions in the long run.&lt;/p&gt;

&lt;p&gt;But actually it’s not the programming language that’s the biggest
problem, because technical challenges can usually be worked around, but
the surrounding culture created by the community, along with the libraries
available, because as a developer you won’t want to reinvent the wheel
and swim against the tide.&lt;/p&gt;

&lt;p&gt;This is why in addition to Haskell and OCaml, which are the languages
that people refer to when speaking of FP,
&lt;a href=&quot;https://scala-lang.org/&quot;&gt;Scala&lt;/a&gt; also shines amongst them, because it
has managed to attract and retain talent to
work on &lt;a href=&quot;https://typelevel.org/projects/&quot;&gt;awesome libraries for FP&lt;/a&gt;,
that don’t have an equal outside of Haskell.&lt;/p&gt;

&lt;p&gt;And for example, yes, you can do actual Functional Programming in
JavaScript and there have been libraries helping with that, including
really popular ones like
&lt;a href=&quot;https://github.com/Reactive-Extensions/RxJS&quot;&gt;RxJS&lt;/a&gt;,
&lt;a href=&quot;https://reactjs.org/&quot;&gt;React&lt;/a&gt;,
&lt;a href=&quot;http://redux.js.org/&quot;&gt;Redux&lt;/a&gt;,
&lt;a href=&quot;https://github.com/facebook/immutable-js/&quot;&gt;Immutable.js&lt;/a&gt;,
&lt;a href=&quot;http://underscorejs.org/&quot;&gt;Underscore.js&lt;/a&gt; amongst others,
which were partially inspired by the community’s experience with
&lt;a href=&quot;https://clojurescript.org/&quot;&gt;ClojureScript&lt;/a&gt; and now
&lt;a href=&quot;https://github.com/reasonml&quot;&gt;ReasonML&lt;/a&gt;,
&lt;a href=&quot;http://www.purescript.org/&quot;&gt;PureScript&lt;/a&gt; and others.
There are also community efforts, such as my own
&lt;a href=&quot;https://funfix.org&quot;&gt;Funfix&lt;/a&gt;, plus a growing ecosystem around
&lt;a href=&quot;https://github.com/fantasyland/fantasy-land&quot;&gt;Fantasy Land&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;But bring up a problem like
&lt;a href=&quot;https://alexn.org/blog/2017/10/11/javascript-promise-leaks-memory/&quot;&gt;JavaScript’s Promise Leaks Memory&lt;/a&gt;
in &lt;code&gt;then&lt;/code&gt; chains and dozens of developers will jump on you to
re-educate you on how promises work and to make you understand that
the concerns you have are a niche, functional programming be damned.&lt;/p&gt;

&lt;p&gt;Which does highlight that if you want functional programming,
the communities of languages being bred for FP, like Haskell,
PureScript, OCaml, Scala, etc. are probably richer and bigger than
the FP sub-communities of the top mainstream languages, Java and
JavaScript included.&lt;/p&gt;

&lt;h2 id=&quot;learning-resources&quot;&gt;Learning Resources&lt;/h2&gt;

&lt;p&gt;Don’t believe the opinions of people on the Internet, mine included.
Learn some Functional Programming instead, the real stuff, not the
pop lambda-infused mumbo jumbo, then you can make up your own mind.
At the very least, it’s fun, and you’ve got nothing to lose.&lt;/p&gt;

&lt;p&gt;Thus far, I found these two books to be good as an introduction to FP:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://haskellbook.com/&quot;&gt;Haskell Programming from First Principles&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.manning.com/books/functional-programming-in-scala&quot;&gt;Functional Programming in Scala&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learning Haskell first is not a bad idea, because Haskell is currently
the &lt;em&gt;lingua franca&lt;/em&gt; of FP and most interesting research is happening in
Haskell or in Haskell-derived languages (e.g. Idris, PureScript, etc).
Even if you move on, you’ll still refer to concepts you learned in
Haskell by name, you’ll still be inspired by ideas from Haskell’s
ecosystem, etc. But if you’re into Scala already, then the “red book”
is pretty awesome.&lt;/p&gt;

&lt;p&gt;After that, you might want to read
&lt;a href=&quot;https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/&quot;&gt;Category Theory for Programmers&lt;/a&gt;
(&lt;a href=&quot;https://github.com/hmemcpy/milewski-ctfp-pdf&quot;&gt;PDF version&lt;/a&gt;),
which should come only after you’ve gone through one of the above books
from cover to cover.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
Note you don’t need category theory for FP, but it’s better if you
eventually learn the basics, since it’s a formal language for talking
about &lt;em&gt;composition&lt;/em&gt; and we want &lt;em&gt;composition&lt;/em&gt; in our lives 😎 &lt;br&gt;&lt;br&gt;
If you want motivation, remember that kids in Romania do it —
put that on your fridge 😜
&lt;/p&gt;

&lt;p&gt;More good books might be out there, but for learning FP, I’d advise
against going with anything that’s dynamically typed or LISP based. For one
because dynamic languages tend to be more pragmatic, plus their limited
type system don’t allow many of the useful abstractions that
we’ve discovered in the last decade, so you’d be depriving yourself
of many useful concepts and libraries. You should feel free to pick a
dynamic language once you have the knowledge to make an informed choice.&lt;/p&gt;

&lt;p&gt;Also, &lt;a href=&quot;https://mitpress.mit.edu/sicp/full-text/book/book.html&quot;&gt;SICP&lt;/a&gt;
(see &lt;a href=&quot;https://github.com/sarabander/sicp-pdf&quot;&gt;modern PDF compilation&lt;/a&gt;)
might have been good for its time and is still a good book,
but it’s not that good for learning FP in 2017.&lt;/p&gt;

&lt;p&gt;Now go forth and spread the true FP love 💘&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2017/10/15/functional-programming/?pk_campaign=rss&quot;&gt;What is Functional Programming?&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 15 Oct 2017 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 29 Sep 2023 05:51:11 +0000</dc:modified>
  <atom:modified>Fri, 29 Sep 2023 05:51:11 +0000</atom:modified>
  <link>https://alexn.org/blog/2017/10/15/functional-programming/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2017/10/15/functional-programming/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Best Of</category>
  <category>FP</category>
  <category>Haskell</category>
  <category>Scala</category>
  <category>JavaScript</category>
  </item>


<item>
  <title>Scala Days 2017 — Monix Task</title>
  <description>My presentation from Scala Days 2017, Chicago (April) and Copenhagen (June), on the design of Monix’s Task.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      
&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=wi97X8_JQUk&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/wi97X8_JQUk/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=wi97X8_JQUk&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;Presentation from &lt;a href=&quot;http://scaladays.org/&quot;&gt;Scala Days&lt;/a&gt;, held in
&lt;a href=&quot;http://event.scaladays.org/scaladays-chicago-2017&quot;&gt;Chicago&lt;/a&gt;
and &lt;a href=&quot;http://event.scaladays.org/scaladays-cph-2017&quot;&gt;Copenhagen&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://alexn.org/assets/pdfs/monix-task-scaladays.pdf&quot;&gt;Slides (PDF file)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wi97X8_JQUk&quot;&gt;Video (YouTube)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=wi97X8_JQUk&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/wi97X8_JQUk/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=wi97X8_JQUk&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/scaladays.jpg&quot; width=&quot;900&quot; height=&quot;900&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;Scala’s Future from the standard library is great, but sometimes we need more. A Future strives to be a value, one detached from time and for this reason its capabilities are restricted and for some use-cases its behavior ends up being unintuitive. Therefore, while the Future/Promise pattern is great for representing asynchronous results of processes that may or may not be started yet, it cannot be used as a specification for an asynchronous computation.&lt;/p&gt;

&lt;p&gt;The Monix Task is in essence about dealing with asynchronous computations and non-determinism, being inspired by the Scalaz Task and designed from the ground up for performance and to be compatible with Scala.js/Javascript runtimes and with the Cats library. It also makes use of Scala’s Future to represent results, the two being complementary.&lt;/p&gt;

&lt;p&gt;In this talk I’ll show you its design, when you should use it and why in dealing with asynchronicity it’s better to work with Task instead of blocking threads.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2017/10/13/scaladays-copenhagen/?pk_campaign=rss&quot;&gt;Scala Days 2017 — Monix Task&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 13 Oct 2017 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2017/10/13/scaladays-copenhagen/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2017/10/13/scaladays-copenhagen/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Monix</category>
  <category>Video</category>
  </item>


<item>
  <title>Introduction</title>
  <description>JavaScript’s Promise leaks memory in recursive loops and what you can do about it.</description>
  <content:encoded>&lt;p&gt;This piece of code will leak memory and eventually crash your Node.js
process or browser:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// Tested on Node.js 7.10, Firefox 57 and Chrome 61
//
// Usage of `setImmediate` is to prove that we have
// async boundaries, can be removed for browsers
// not supporting it.

function signal(i) {
  return new Promise(cb =&gt; setImmediate(() =&gt; cb(i)))
}

function loop(n) {
  return signal(n).then(i =&gt; {
    if (i % 1000 == 0) console.log(i)
    return loop(n + 1)
  })
}

loop(0).catch(console.error)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;https://alexn.org/assets/html/js-promise-leak.html&quot; target=&quot;_blank&quot;&gt;&lt;b&gt;→ Load Sample for Browser&lt;/b&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It takes a while to fill GBs of heap, plus Node is less conservative, the GC eventually
freezing the process trying to recover memory, so give it a few seconds.&lt;/p&gt;

&lt;p&gt;This is equivalent with this &lt;code&gt;async&lt;/code&gt; function:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;async function loop(n) {
  const i = await signal(n)
  if (i % 1000 == 0) console.log(i)

  // Recursive call
  return loop(n + 1)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course, if this loop would be synchronous, not using &lt;code&gt;Promise&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt; / &lt;code&gt;await&lt;/code&gt;,
then the process would blow up with a stack overflow error because
at the moment of writing JavaScript does not do
&lt;a href=&quot;https://en.wikipedia.org/wiki/Tail_call&quot;&gt;tail calls optimizations&lt;/a&gt;
(until everybody implements ECMAScript 6 fully at least).&lt;/p&gt;

&lt;p&gt;But before you jump to conclusions, this has nothing to do with JavaScript’s
lack of TCO support. This is because in our recursive function it’s
not JavaScript’s &lt;a href=&quot;https://en.wikipedia.org/wiki/Call_stack&quot;&gt;call stack&lt;/a&gt;
that’s managing that loop, but rather the &lt;code&gt;Promise&lt;/code&gt; implementation.
That recursive call is asynchronous and so it does not abuse the call stack
by definition.&lt;/p&gt;

&lt;p&gt;Unfortunately, just like a regular function using the call stack for those
recursive calls, the &lt;code&gt;Promise&lt;/code&gt; implementation is abusing the heap memory,
not chaining &lt;code&gt;then&lt;/code&gt; calls correctly. And that sample should not leak,
the &lt;code&gt;Promise&lt;/code&gt; implementation should be able to do the equivalent of TCO
and in such a case eliminate frames in the &lt;code&gt;then&lt;/code&gt; chain being created.&lt;/p&gt;

&lt;h2 id=&quot;the-spec-is-the-problem&quot;&gt;The Spec is The Problem&lt;/h2&gt;

&lt;figure&gt;
  &lt;a href=&quot;https://promisesaplus.com/&quot;&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/js-then.png&quot; width=&quot;1000&quot; height=&quot;1000&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;We’re talking of the &lt;a href=&quot;https://promisesaplus.com/&quot;&gt;Promise/A+ specification&lt;/a&gt;.
Relevant links to known issues on GitHub, explaining why:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Node.js issue, now closed:
&lt;strong&gt;&lt;a href=&quot;https://github.com/nodejs/node/issues/6673&quot;&gt;node/#6673&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
  &lt;li&gt;Promise/A+ spec issue, open since 2014:
&lt;strong&gt;&lt;a href=&quot;https://github.com/promises-aplus/promises-spec/issues/179&quot;&gt;promises-spec/#179&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you’ll see, there are some reasonable arguments for why the &lt;code&gt;Promise&lt;/code&gt;
implementation is allowed to leak memory. But I can’t agree.&lt;/p&gt;

&lt;h2 id=&quot;the-non-leaky-solution&quot;&gt;The Non-leaky Solution&lt;/h2&gt;

&lt;p&gt;The solution, if you insist on using JavaScript’s &lt;code&gt;Promise&lt;/code&gt;, is to work
with non-recursive functions:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;async function loop(n) {
  let i = 0

  while (true) {
    i = await signal(i + 1)
    if (i % 1000 == 0) console.log(i)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But at this point any semblance of functional programming, if you ever had
any, goes out the window, see below.&lt;/p&gt;

&lt;h2 id=&quot;common-objections&quot;&gt;Common Objections&lt;/h2&gt;

&lt;p&gt;Gathering feedback from people, here are the common objections:&lt;/p&gt;

&lt;h3 id=&quot;1-this-is-normal&quot;&gt;1. This is Normal&lt;/h3&gt;

&lt;p&gt;No, if you judge this implementation, relative to other &lt;code&gt;Promise&lt;/code&gt; / &lt;code&gt;Future&lt;/code&gt;
implementations in the industry, which are setting expectations.&lt;/p&gt;

&lt;p&gt;Here are the implementations that I know about that DO NOT leak memory:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;a href=&quot;http://bluebirdjs.com/docs/getting-started.html&quot;&gt;Bluebird&lt;/a&gt;, probably
the most popular non-standard &lt;code&gt;Promise&lt;/code&gt; implementation for JavaScript&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://www.scala-lang.org/&quot;&gt;Scala&lt;/a&gt;’s standard
&lt;a href=&quot;http://www.scala-lang.org/api/2.12.3/scala/concurrent/Future.html&quot;&gt;Future&lt;/a&gt;,
in the wild since 2013; the fix for the leaky &lt;code&gt;flatMap&lt;/code&gt;
chains was added by &lt;a href=&quot;https://x.com/richdougherty&quot;&gt;Rich Dougherty&lt;/a&gt;
in &lt;a href=&quot;https://github.com/scala/scala/pull/2674&quot;&gt;this PR&lt;/a&gt;, inspired
by Twitter’s &lt;code&gt;Future&lt;/code&gt; implementation&lt;/li&gt;
  &lt;li&gt;Twitter’s &lt;a href=&quot;https://twitter.github.io/util/docs/com/twitter/util/Future.html&quot;&gt;Future&lt;/a&gt;,
which is used in all of Twitter’s backend infrastructure, being integrated
in &lt;a href=&quot;https://twitter.github.io/finagle/&quot;&gt;Finagle&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;http://trane.io/&quot;&gt;Trane.io&lt;/a&gt;, a Java Future implementation providing a &lt;code&gt;TailRec&lt;/code&gt;
builder meant precissely for this use-case&lt;/li&gt;
  &lt;li&gt;My very own Funfix &lt;a href=&quot;https://funfix.org/api/exec/classes/future.html&quot;&gt;Future&lt;/a&gt;
and Monix &lt;a href=&quot;https://monix.io/api/3.0/monix/execution/CancelableFuture.html&quot;&gt;CancelableFuture&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Interestingly, complaints for Scala’s &lt;code&gt;Future&lt;/code&gt; happened due to usage of
Play’s &lt;a href=&quot;https://www.playframework.com/documentation/2.6.x/Iteratees&quot;&gt;Iteratees&lt;/a&gt;,
with which people have been modeling stream processing.&lt;/p&gt;

&lt;h3 id=&quot;2-but-it-does-unlimited-chaining-of-promises&quot;&gt;2. But It Does Unlimited Chaining of Promises&lt;/h3&gt;

&lt;p&gt;Yes, that’s why it’s leaking memory.&lt;/p&gt;

&lt;p&gt;No, the implementation should not chain promises like that and an
alternative implementation is possible and well known, as evidenced by
the implementations mentioned that don’t leak.&lt;/p&gt;

&lt;p&gt;The fault lies with the standard &lt;code&gt;Promise&lt;/code&gt; implementation, not with
the shown sample, being a legitimate use-case.&lt;/p&gt;

&lt;h3 id=&quot;3-that-sample-does-not-use-the-return-value&quot;&gt;3. That Sample Does Not Use the Return Value&lt;/h3&gt;

&lt;p&gt;The sample is kept simple for didactic purposes, however:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;you can easily imagine a loop that processes a very long stream of data,
aggregating information along the way, returning a result later&lt;/li&gt;
  &lt;li&gt;the script does do error handling and without that inner
&lt;code&gt;return&lt;/code&gt;, the &lt;code&gt;.catch(console.error)&lt;/code&gt; would have no effect&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;4-thats-the-equivalent-of-a-stack-overflow&quot;&gt;4. That’s the Equivalent of a Stack Overflow&lt;/h3&gt;

&lt;p&gt;Yes, I’ve mentioned this above, but just to set your mind at rest on this point,
proper Tail-Calls Optimizations are coming for normal call sites, being part of
ECMAScript, see:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.ecma-international.org/ecma-262/6.0/#sec-tail-position-calls&quot;&gt;ECMAScript specification&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://webkit.org/blog/6240/ecmascript-6-proper-tail-calls-in-webkit/&quot;&gt;ECMAScript 6 Proper Tail Calls in WebKit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can’t rely on it yet, but you can rest assured that in the future
if that sample would be synchronous, it would not trigger a stack overflow.&lt;/p&gt;

&lt;p&gt;Therefore, given that asynchronous calls are by definition processes / events
happening independently of the current call stack / run loop, this behavior
is actually surprising, since one of the reasons to go async is to escape
the limitations of the call stack.&lt;/p&gt;

&lt;h3 id=&quot;5-you-dont-understand-how-promises-work&quot;&gt;5. You Don’t Understand How Promises Work&lt;/h3&gt;

&lt;p&gt;I’ve been told that I don’t understand promises. So I apologize for the
appeal to authority that I’m about to make.&lt;/p&gt;

&lt;p&gt;Data types for dealing with &lt;em&gt;asynchrony&lt;/em&gt; have been a hobby of mine since
2012 and I’ve been authoring several projects in which I implemented
Promise-like data types:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://monix.io/&quot;&gt;Monix&lt;/a&gt;, which implements &lt;code&gt;Task&lt;/code&gt;, one of the best ports
of Haskell’s &lt;code&gt;IO&lt;/code&gt;, along with a complementary &lt;code&gt;CancelableFuture&lt;/code&gt; and
what I think is the best back-pressured Rx &lt;code&gt;Observable&lt;/code&gt; implementations
in existence&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/funfix/funfix&quot;&gt;Funfix&lt;/a&gt;, a JavaScript library for FP,
delivering a &lt;code&gt;Future&lt;/code&gt; and an &lt;code&gt;IO&lt;/code&gt; implementation, see below&lt;/li&gt;
  &lt;li&gt;have contributed to &lt;a href=&quot;https://github.com/typelevel/cats-effect&quot;&gt;cats-effect&lt;/a&gt;,
a more conservative &lt;code&gt;IO&lt;/code&gt; port&lt;/li&gt;
&lt;/ul&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
Bonus — see my &lt;a href=&quot;https://www.youtube.com/watch?v=wi97X8_JQUk&quot;&gt;presentation from Scala Days&lt;/a&gt;!
&lt;/p&gt;

&lt;p&gt;My work, good or bad, has followed a certain pattern, which is why I do
understand promises, I do understand at least two solutions to this, hence
this article.&lt;/p&gt;

&lt;h3 id=&quot;6-no-use-cases-this-is-a-niche&quot;&gt;6. No Use-cases, This is a Niche&lt;/h3&gt;

&lt;p&gt;Functional programming might be a niche, however more and more projects,
including at big companies such as Facebook, are now using an
&lt;a href=&quot;https://alexn.org/blog/2017/10/15/functional-programming/&quot;&gt;actual FP style&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You cannot describe any functional programming algorithm involving loops
without tail recursions. If folds are used, then folds are described with
tail recursions as well. That’s because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;any loop can be described with a tail recursion&lt;/li&gt;
  &lt;li&gt;you can’t have immutability of the state you’re evolving without it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An example of a use-case is the processing of really long / infinite streams of
events, for which it’s really natural to describe algorithms using tail recursions
and for which you can’t really work with imperative, mutation-based loops.&lt;/p&gt;

&lt;p&gt;Imagine reading chunks of data from a file and describing them with a data
structure like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;interface List&lt;A&gt;

class Next&lt;A&gt; implements List&lt;A&gt; {
  constructor(
    public readonly head: A,
    public readonly next: () =&gt; Promise&lt;List&lt;A&gt;&gt;
  ) {}
}

class Halt implements List&lt;A&gt; {
  constructor(public readonly error?: any) {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sample is using TypeScript (could be Flow) for making it clear what the types are.
You can work with plain JavaScript of course.&lt;/p&gt;

&lt;p&gt;This structure is really cheap and effective, being a lazy, asynchronous,
referentially transparent stream. And in fact it’s really similar to JavaScript
implementations of async iterators, so yes, you are going to work with
something like this in the future, even if you don’t like it ;-)&lt;/p&gt;

&lt;p&gt;And describing transformation functions like this one is really fun too:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;function map&lt;A, B&gt;(list: List&lt;A&gt;, f: (a: A) =&gt; B): List&lt;B&gt; {
  if (list instanceof Next) {
    try {
      const cons = list as Next&lt;A&gt;
      return new Next(f(cons.head), () =&gt; cons.next().then(xs =&gt; map(xs, f)))
    } catch (e) {
      return new Halt(e)
    }
  } else {
    return list
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Alas, with the &lt;code&gt;Promise&lt;/code&gt; implementation leaking, this doesn’t work ;-)&lt;/p&gt;

&lt;h2 id=&quot;alternatives&quot;&gt;Alternatives&lt;/h2&gt;

&lt;h3 id=&quot;fluture&quot;&gt;Fluture&lt;/h3&gt;

&lt;p&gt;Project Page: &lt;a href=&quot;https://github.com/fluture-js/Fluture&quot;&gt;github.com/fluture-js/Fluture&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the most popular &lt;code&gt;Promise&lt;/code&gt; alternative that I know of.&lt;/p&gt;

&lt;p&gt;It isn’t a direct replacement however because it has lazy behavior, being meant for suspending side effects. This is more like an &lt;code&gt;IO&lt;/code&gt; data type. Which is cool, you should use something like it, but it’s also apples vs oranges.&lt;/p&gt;

&lt;p&gt;I don’t have enough experience with it, making this recommendation solely based on its popularity and I double checked that it indeed preserves stack safety.&lt;/p&gt;

&lt;h3 id=&quot;funfix&quot;&gt;Funfix&lt;/h3&gt;

&lt;p&gt;I’ve been building a new project, &lt;a href=&quot;https://funfix.org/&quot;&gt;Funfix&lt;/a&gt;,
a JavaScript library for functional programming (capital FP), supporting
&lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt; and &lt;a href=&quot;https://flow.org/&quot;&gt;Flow&lt;/a&gt;
types out of the box.&lt;/p&gt;

&lt;p&gt;Funfix exposes &lt;a href=&quot;https://funfix.org/api/exec/classes/future.html&quot;&gt;Future&lt;A&gt;&lt;/a&gt;, an
eager &lt;code&gt;Promise&lt;/code&gt; alternative that’s safe, cancellable and filled with goodies,
along with &lt;a href=&quot;https://funfix.org/api/effect/classes/io.html&quot;&gt;IO&lt;A&gt;&lt;/a&gt;, a lazy, lawful,
cancellable data type for handling all kinds of side effects, inspired by Haskell,
the two being complementary.&lt;/p&gt;

&lt;p&gt;This piece of code powered by &lt;code&gt;Future&lt;/code&gt; does not leak:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { Future } from &quot;funfix&quot;

function loop(n) {
  return Future.of(() =&gt; n).flatMap(i =&gt; {
    if (i % 1000 == 0) console.log(i)
    return loop(n + 1)
  })
}

loop(0).recover(console.error)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And neither does this one, powered by &lt;code&gt;IO&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { IO } from &quot;funfix&quot;

function loop(n) {
  return IO.of(() =&gt; n).flatMap(i =&gt; {
    if (i % 1000 == 0) console.log(i)
    return loop(n + 1)
  })
}

loop(0).run().recover(console.error)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This &lt;code&gt;IO&lt;/code&gt; is a port of &lt;a href=&quot;https://monix.io/&quot;&gt;Monix&lt;/a&gt;’s
&lt;a href=&quot;https://monix.io/docs/2x/eval/task.html&quot;&gt;Task&lt;/a&gt;, being a better
&lt;code&gt;IO&lt;/code&gt; than Haskell’s &lt;code&gt;IO&lt;/code&gt; due to its cancellable nature ;-)&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://github.com/funfix/funfix/pull/57&quot;&gt;this PR&lt;/a&gt; I’ve also
fixed the memory leak for &lt;code&gt;Future&lt;/code&gt;, doing the same tricks that
Scala’s &lt;a href=&quot;http://www.scala-lang.org/api/2.12.3/scala/concurrent/Future.html&quot;&gt;Future&lt;/a&gt;
is doing. Now released in &lt;a href=&quot;https://github.com/funfix/funfix/releases/tag/v6.2.0&quot;&gt;v6.2.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And note that this is harder to do for Funfix’s &lt;code&gt;Future&lt;/code&gt; due to also
having to deal with chains of &lt;code&gt;Cancelable&lt;/code&gt; references, which can
also leak.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;Author’s Rant —&lt;/strong&gt; in response to this article I’ve been called a scumbag
for “&lt;em&gt;shameless self promotion&lt;/em&gt;”.&lt;br&gt;&lt;br&gt;
I’m building stuff that I share with the world and I like talking about
it on my personal blog. I’m not going to apologize for it.
&lt;/p&gt;

&lt;h2 id=&quot;final-words&quot;&gt;Final Words&lt;/h2&gt;

&lt;p&gt;That the current JavaScript &lt;code&gt;Promise&lt;/code&gt; implementation has this leak
is a big problem, because tail-recursive calls are the cornerstone
of functional programming.&lt;/p&gt;

&lt;p&gt;Yes, it’s true that &lt;code&gt;Promise&lt;/code&gt; is not a useful monadic type for doing FP,
since it does not suspend side effects (which is why you should
use &lt;a href=&quot;https://funfix.org/api/effect/classes/io.html&quot;&gt;IO&lt;/a&gt;), but that’s
beside the point, plus for the FP purists out there, you can always
suspend it in a thunk, assuming that it doesn’t leak in &lt;code&gt;then&lt;/code&gt; chains.&lt;/p&gt;

&lt;p&gt;This is also why I fear standardization by committee in general. Along with
the totally awkward &lt;code&gt;then&lt;/code&gt; signature that can’t be safely described with
TypeScript’s or Flow’s types, this is another example of how standard
solutions can be harmful, because by being pushed as a standard, it makes
it hard for alternatives to exist, since most people are just going to
use the standard implementation, especially in JavaScript’s ecosystem
where people are afraid to take on dependencies.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2017/10/11/javascript-promise-leaks-memory/?pk_campaign=rss&quot;&gt;Introduction&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 11 Oct 2017 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2017/10/11/javascript-promise-leaks-memory/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2017/10/11/javascript-promise-leaks-memory/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Concurrency</category>
  <category>FP</category>
  <category>JavaScript</category>
  </item>


<item>
  <title>Automatic Releases to Maven Central with Travis and SBT</title>
  <description>Enabling automatic releases for your open source Scala project with Travis and SBT.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2017/08/16/automatic-releases-sbt-travis/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/sbt.png?202603060940&quot; alt=&quot;&quot; width=&quot;641&quot; height=&quot;277&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;Builds and deployments of new versions and snapshots is a pain. This article is an explanation to how I automated this process for &lt;a href=&quot;https://monix.io&quot;&gt;monix.io&lt;/a&gt;, an open source Scala library that’s making use of &lt;a href=&quot;http://www.scala-sbt.org/&quot;&gt;SBT&lt;/a&gt; as the build tool and &lt;a href=&quot;https://travis-ci.org/&quot;&gt;travis-ci.org&lt;/a&gt; as the continuous integration.&lt;/p&gt;

&lt;p&gt;What this setup does is to trigger a &lt;code&gt;publish&lt;/code&gt; script that
automatically deploys packages on Maven Central:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;whenever you tag a release by pushing a version tag in Git, like
&lt;code&gt;v1.10.0&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;whenever you push into the &lt;code&gt;snapshot&lt;/code&gt; branch, the result being
hashed versions, e.g. &lt;code&gt;1.10.0-36fa3d3&lt;/code&gt;, where the hash appended
as a suffix is the Git commit hash; these hashed versions are like
snapshot releases, but better because people can rely on them to
remain in Maven Central and thus less volatile&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After you read this article, you can use the setup of these projects
for inspiration:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/monix/shade/&quot;&gt;github.com/monix/shade&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/monix/monix/&quot;&gt;github.com/monix/monix&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; with this process you’ll have to
trust &lt;a href=&quot;https://travis-ci.org/&quot;&gt;Travis-ci.org&lt;/a&gt; with your PGP private
key for signing the published binaries. If that’s an acceptable risk
or not, that’s up to you. See below.&lt;/p&gt;

&lt;h2 id=&quot;generating-a-pgp-key-pair&quot;&gt;Generating a PGP Key Pair&lt;/h2&gt;

&lt;p&gt;For deployments to Sonatype / Maven Central the built packages need to
be signed. If you don’t have an existing PGP key, one can be easily
generated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WARNING:&lt;/strong&gt; do not give out your personal PGP private key that you
use to sign emails or for online transactions. Generate a special PGP
key pair just for your project.&lt;/p&gt;

&lt;p&gt;I’m currently using a MacOS machine, so for managing PGP
keys I’m using the open source &lt;a href=&quot;https://gpgtools.org/&quot;&gt;GPG Suite&lt;/a&gt;,
coming with a nice GUI interface.&lt;/p&gt;

&lt;p&gt;As far as I know GPG comes installed by default on all major Linux
operating systems and for Windows checkout this
&lt;a href=&quot;https://www.gnupg.org/download/index.en.html&quot;&gt;download page on gnupg.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With the GPG command line tools installed you can generate a PGP key pair
like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gpg --gen-key
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;accept the default &lt;code&gt;RSA&lt;/code&gt; for the kind of key&lt;/li&gt;
  &lt;li&gt;enter the desired key size, the bigger the better, so enter &lt;code&gt;4096&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;for expiration, I preferred a key that doesn’t expire, although this might not be wise&lt;/li&gt;
  &lt;li&gt;for an email address, enter a valid one&lt;/li&gt;
  &lt;li&gt;I recommend encrypting your private key with a generous passphrase
that you then store in 1Password / LastPass ;-)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To get the ID of the newly generated key you can do:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gpg --list-secret-keys --keyid-format LONG
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To export this newly generated key, assuming that &lt;code&gt;2673B174C4071B0E&lt;/code&gt;
is the key ID, you’ll need both the public key and the private one,
but they can be dumped in the same file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gpg -a --export 2673B174C4071B0E &gt; my-key.asc
gpg -a --export-secret-keys 2673B174C4071B0E &gt;&gt; my-key.asc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I also keep these in 1Password btw.&lt;/p&gt;

&lt;p&gt;To configure SBT to sign your packages with a key living in the
project’s repository you’ll need a PGP key ring. Such a key ring is
basically a database of multiple PGP keys. You need to have one to
keep in the repository of your project. Normally these keys are kept
in:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code&gt;$HOME/.gnupg/pubring.gpg&lt;/code&gt; for the public keys&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;$HOME/.gnupg/secring.gpg&lt;/code&gt; for the private keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;code&gt;$PROJECT&lt;/code&gt; root we need a custom key ring containing just the
key we need, like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code&gt;$PROJECT/project/.gnupg/pubring.gpg&lt;/code&gt; for the public keys&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;$PROJECT/project/.gnupg/secring.gpg&lt;/code&gt; for the private keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These files are going to be encrypted, to provide minimal protection.
To generate this ring in your project, go to you’re project’s root
directory and then:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gpg --no-default-keyring \
  --primary-keyring `pwd`/project/.gnupg/pubring.gpg \
  --secret-keyring `pwd`/project/.gnupg/secring.gpg \
  --keyring `pwd`/project/.gnupg/pubring.gpg \
  --fingerprint \
  --import path/to/my-key.asc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;my-key.asc&lt;/code&gt; file is the one that you’ve created in the previous step.&lt;/p&gt;

&lt;p&gt;After you create these files, make sure to delete any junk from
&lt;code&gt;$PROJECT/project/.gnupg&lt;/code&gt;, so verify the newly created files with
&lt;code&gt;git status&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;NOTE: check the newly created files, because the &lt;code&gt;gpg&lt;/code&gt; command line
tools might generate junk. We only want those 2 files (&lt;code&gt;pubring.gpg&lt;/code&gt;
and &lt;code&gt;secring.gpg&lt;/code&gt;), so check your project directory with &lt;code&gt;git status&lt;/code&gt;
and delete anything extra.&lt;/p&gt;

&lt;h2 id=&quot;configuring-sbt&quot;&gt;Configuring SBT&lt;/h2&gt;

&lt;p&gt;Curently in &lt;a href=&quot;https://monix.io&quot;&gt;monix.io&lt;/a&gt; I’m using the following plugins:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/sbt/sbt-pgp&quot;&gt;sbt-pgp&lt;/a&gt; for signing packages with PGP&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/sbt/sbt-git&quot;&gt;sbt-git&lt;/a&gt; for making use of Git from
SBT, relevant here if you want to do Git-enabled version hashes&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/xerial/sbt-sonatype&quot;&gt;sbt-sonatype&lt;/a&gt; for automatically
publishing artifacts to Maven Central&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For PGP the configuration is as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;useGpg := false
usePgpKeyHex(&quot;2673B174C4071B0E&quot;)
pgpPublicRing := baseDirectory.value / &quot;project&quot; / &quot;.gnupg&quot; / &quot;pubring.gpg&quot;
pgpSecretRing := baseDirectory.value / &quot;project&quot; / &quot;.gnupg&quot; / &quot;secring.gpg&quot;
pgpPassphrase := sys.env.get(&quot;PGP_PASS&quot;).map(_.toArray)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Explanation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code&gt;useGpg := false&lt;/code&gt; says that we do not want to use the GPG tools
installed on your computer, but rather the implementation that
&lt;code&gt;sbt-pgp&lt;/code&gt; ships with; in my experience this is a must, otherwise
depending on the GPG tools you have, you won’t be able to make it
use a different pgp ring&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;usePgpKeyHex&lt;/code&gt; forces a certain key to be used for signing by
specifying its key&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;pgpPublicRing&lt;/code&gt; and &lt;code&gt;pgpPublicRing&lt;/code&gt; specify the path to a GPG ring
that contains the key you want, instead of the default one which is
usually &lt;code&gt;$HOME/.gnupg/pubring.gpg&lt;/code&gt; and &lt;code&gt;$HOME/.gnupg/secring.gpg&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;pgpPassphrase&lt;/code&gt; is a GPG passphrase for the used key, that’s taken
from the env variable named &lt;code&gt;PGP_PASS&lt;/code&gt;; Travis has the ability to
set such env variables to be available in your build&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For publishing to Sonatype, we’ll need these settings:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sonatypeProfileName := organization.value

credentials += Credentials(
  &quot;Sonatype Nexus Repository Manager&quot;,
  &quot;oss.sonatype.org&quot;,
  sys.env.getOrElse(&quot;SONATYPE_USER&quot;, &quot;&quot;),
  sys.env.getOrElse(&quot;SONATYPE_PASS&quot;, &quot;&quot;)
)

isSnapshot := version.value endsWith &quot;SNAPSHOT&quot;

publishTo := Some(
  if (isSnapshot.value)
    Opts.resolver.sonatypeSnapshots
  else
    Opts.resolver.sonatypeStaging
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In addition to these options, for Sonatype we also need the required
artifact info (e.g. license, homepage, authors). Here’s what I have
for Shade, adjust accordingly:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;licenses := Seq(&quot;MIT&quot; -&gt; url(&quot;https://opensource.org/licenses/MIT&quot;))
homepage := Some(url(&quot;https://github.com/monix/shade&quot;))

scmInfo := Some(
  ScmInfo(
    url(&quot;https://github.com/monix/shade&quot;),
    &quot;scm:git@github.com:monix/shade.git&quot;
  ))

developers := List(
  Developer(
    id=&quot;alexelcu&quot;,
    name=&quot;Alexandru Nedelcu&quot;,
    email=&quot;noreply@alexn.org&quot;,
    url=url(&quot;https://alexn.org&quot;)
  ))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;TIP, to find out the ID of a license type, see this cool list:
&lt;a href=&quot;https://spdx.org/licenses/&quot;&gt;spdx.org/licenses/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You’ll need those two environment variables set in Travis’s settings,
more details below.&lt;/p&gt;

&lt;p&gt;And then to enable Git versioning for snapshots (e.g. &lt;code&gt;3.0.0-9d94d3d&lt;/code&gt;)
you can do:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;enablePlugins(GitVersioning)

/* The BaseVersion setting represents the in-development (upcoming) version,
 * as an alternative to SNAPSHOTS.
 */
git.baseVersion := &quot;3.0.0&quot;

val ReleaseTag = &quot;&quot;&quot;^v([\d\.]+)$&quot;&quot;&quot;.r
git.gitTagToVersionNumber := {
  case ReleaseTag(v) =&gt; Some(v)
  case _ =&gt; None
}

git.formattedShaVersion := {
  val suffix = git.makeUncommittedSignifierSuffix(git.gitUncommittedChanges.value, git.uncommittedSignifier.value)

  git.gitHeadCommit.value map { _.substring(0, 7) } map { sha =&gt;
    git.baseVersion.value + &quot;-&quot; + sha + suffix
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now test your setup with this command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ PGP_PASS=&quot;xxxxxx&quot; sbt publishLocalSigned
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Replace &lt;code&gt;xxxxxx&lt;/code&gt; with your passphrase. If this command works, then we
are good thus far.&lt;/p&gt;

&lt;h2 id=&quot;configuring-travis&quot;&gt;Configuring Travis&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;build.sbt&lt;/code&gt; I configured these 2 commands:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;addCommandAlias(&quot;ci-all&quot;,  &quot;;+clean ;+compile ;+test ;+package&quot;)
addCommandAlias(&quot;release&quot;, &quot;;+publishSigned ;sonatypeReleaseAll&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then the &lt;code&gt;.travis.yml&lt;/code&gt; file has something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-yml&quot;&gt;language: scala
sudo: required
dist: trusty
group: edge

matrix:
  include:
    - jdk: oraclejdk8
      scala: 2.12.3
      env: COMMAND=ci-all PUBLISH=true

script:
  - sbt -J-Xmx6144m ++$TRAVIS_SCALA_VERSION $COMMAND

after_success:
  - ./project/publish
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then the &lt;code&gt;project/publish&lt;/code&gt; script, which I’ve built with Ruby
(since I don’t know Bash well :)):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;#!/usr/bin/env ruby

def exec(cmd)
  abort(&quot;Error encountered, aborting&quot;) unless system(cmd)
end

puts &quot;CI=#{ENV[&apos;CI&apos;]}&quot;
puts &quot;TRAVIS_BRANCH=#{ENV[&apos;TRAVIS_BRANCH&apos;]}&quot;
puts &quot;TRAVIS_PULL_REQUEST=#{ENV[&apos;TRAVIS_PULL_REQUEST&apos;]}&quot;
puts &quot;PUBLISH=#{ENV[&apos;PUBLISH&apos;]}&quot;
puts

unless ENV[&apos;CI&apos;] == &apos;true&apos;
  abort(&quot;ERROR: Not running on top of Travis, aborting!&quot;)
end

unless ENV[&apos;PUBLISH&apos;] == &apos;true&apos;
  puts &quot;Publish is disabled&quot;
  exit
end

branch = ENV[&apos;TRAVIS_BRANCH&apos;]
version = nil

unless branch =~ /^v(\d+\.\d+\.\d+)$/ ||
  (branch == &quot;snapshot&quot; &amp;&amp; ENV[&apos;TRAVIS_PULL_REQUEST&apos;] == &apos;false&apos;)

  puts &quot;Only triggering deployment on the `snapshot` branch, or for version tags &quot; +
       &quot;and not for pull requests or other branches, exiting!&quot;
  exit 0
else
  version = $1
  puts &quot;Version branch detected: #{version}&quot; if version
end

# Forcing a change to the root directory, if not there already
Dir.chdir(File.absolute_path(File.join(File.dirname(__FILE__), &quot;..&quot;)))

# Go, go, go
exec(&quot;sbt release&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Give execution permissions to this script:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ chmod +x ./project/publish
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Remember to push your changes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git add .
$ git commit -am &apos;Build changes for automatic releases&apos;
$ git push
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;setting-environment-variables&quot;&gt;Setting environment variables&lt;/h3&gt;

&lt;p&gt;As a final step we need to set the following environment variables in Travis:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;code&gt;PGP_PASS&lt;/code&gt;: the passphrase we used to encrypt our private PGP key&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;SONATYPE_USER&lt;/code&gt;: a user to login to Sonatype, used by SBT to publish and deploy releases on Sonatype&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;SONATYPE_PASS&lt;/code&gt;: a password to login to Sonatype, used by SBT to publish and deploy releases on Sonatype&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the article on
&lt;a href=&quot;https://docs.travis-ci.com/user/environment-variables/&quot;&gt;adding environment variables to Travis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;NOTE: to get a &lt;code&gt;SONATYPE_USER&lt;/code&gt; and a &lt;code&gt;SONATYPE_PASS&lt;/code&gt; go to the
&lt;a href=&quot;https://oss.sonatype.org/#profile;User%20Token&quot;&gt;User Profile on Sonatype&lt;/a&gt; page
and access the “&lt;em&gt;User Token&lt;/em&gt;”, or generate a new one.&lt;/p&gt;

&lt;p&gt;Here’s a screenshot of how my setup currently looks like:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/travis-env-vars.png&quot; width=&quot;2032&quot; height=&quot;734&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;h3 id=&quot;alternative-env-with-travis-encryption&quot;&gt;Alternative Env with Travis Encryption&lt;/h3&gt;

&lt;p&gt;As an alternative to setting those environment variables in Travis’s
UI, you can use Travis’s mechanism for encrypting stuff to set these
values in &lt;code&gt;.travis.yml&lt;/code&gt;. See
the &lt;a href=&quot;https://docs.travis-ci.com/user/encryption-keys&quot;&gt;Encryption Keys&lt;/a&gt;
document.&lt;/p&gt;

&lt;p&gt;First install the &lt;code&gt;travis&lt;/code&gt; command line tool:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ gem install travis
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then do the following, replacing &lt;code&gt;xxxxx&lt;/code&gt; with your key:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ travis encrypt &apos;PGP_PASS=xxxxx&apos; --add

$ travis encrypt &apos;SONATYPE_USER=xxxxx&apos; --add

$ travis encrypt &apos;SONATYPE_PASS=xxxxx&apos; --add
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;NOTE: if your env values have special chars, they might need to be
escaped for Bash to not trigger any errors. See document above.&lt;/p&gt;

&lt;p&gt;These commands will modify your &lt;code&gt;.travis.yml&lt;/code&gt; file, adding a section
that resembles the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;env:
  global:
  - secure: GRdfKNrJn/zqjaDWE+16HCfuCSf/wsDpL...
  - secure: SPSIblLKFVns7pVY1x3SEs4/16htY5HUz...
  - secure: YVx2BSSsqF7LdYTwinf6o8nqJiYL9FeFA...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this can be committed in your repository and Travis will take care
of decrypting those values.&lt;/p&gt;

&lt;h2 id=&quot;publishing&quot;&gt;Publishing&lt;/h2&gt;

&lt;p&gt;For publishing hashed snapshot versions, we need a &lt;code&gt;snapshot&lt;/code&gt; branch,
as that’s what the script above looks for.&lt;/p&gt;

&lt;p&gt;So create this branch by forking &lt;code&gt;master&lt;/code&gt; and pushing it, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git checkout master

$ git checkout -b snapshot
$ git push --set-upstream origin snapshot
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If everything goes well, we should have a new hashed version published,
but watch the output of Travis for any problems.&lt;/p&gt;

&lt;h2 id=&quot;extra-resources&quot;&gt;Extra Resources&lt;/h2&gt;

&lt;p&gt;I’ve written this document while preparing the Shade project for
automatic deployments. So here’s for inspiration:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/monix/shade/compare/1c373f8714e92b48a8bb2337158f61e5650d260a...d712897f122642835cbcd32d159e917c59e7685c&quot;&gt;commits in monix/shade&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://travis-ci.org/monix/shade/jobs/265215531&quot;&gt;snapshot release sample&lt;/a&gt;
(that published &lt;code&gt;1.10.0-d712897&lt;/code&gt; on Maven Central)&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://travis-ci.org/monix/shade/jobs/265221087&quot;&gt;release of v1.10.0&lt;/a&gt;
(that published the final &lt;code&gt;1.10.0&lt;/code&gt; on Maven Central)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;in-closing&quot;&gt;In Closing&lt;/h2&gt;

&lt;p&gt;So that’s about it. Pretty painful if you ask me, but hopefully we
don’t have to do this too often.&lt;/p&gt;

&lt;p&gt;I’ve written this article for myself actually, because I keep
forgetting what I did the first time.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2017/08/16/automatic-releases-sbt-travis/?pk_campaign=rss&quot;&gt;Automatic Releases to Maven Central with Travis and SBT&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 16 Aug 2017 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2017/08/16/automatic-releases-sbt-travis/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2017/08/16/automatic-releases-sbt-travis/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>sbt</category>
  <category>Scala</category>
  </item>


<item>
  <title>Functional Programming Inception (Presentation)</title>
  <description>My presentation from the Bucharest FP meetup.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  My presentation from the &lt;a href=&quot;http://bucharestfp.ro/&quot;&gt;Bucharest FP&lt;/a&gt; meetup.
&lt;/p&gt;

&lt;p&gt;Resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://alexn.org/assets/pdfs/FP-Inception-Bucharest.pdf&quot;&gt;Slides (PDF file)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Links from the presentation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://monix.io&quot;&gt;Monix&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://typelevel.org/cats/&quot;&gt;Typelevel Cats&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/typelevel/discipline&quot;&gt;Discipline&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.scalacheck.org/&quot;&gt;ScalaCheck&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/monix/monix/pull/280&quot;&gt;Generic Iterant Implementation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/monix/monix/pull/331&quot;&gt;Simplified Task-based Implementation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;Designing functionality that exhibits the properties of functional
programming is hard because it requires a mentality change, coping
with immutability and consideration for recursion, performance and
polymorphism. This talk is a lesson in FP design that makes use of
Scala’s hybrid OOP+FP nature.&lt;/p&gt;

&lt;p&gt;We are going to start from Scala’s (and Java’s) ubiquitous
Iterator/Iterable types which expose the famous iterator pattern,
analyzing its strengths and weaknesses. And then we are going to work
our way up to a fully featured FP replacement that has referential
transparency and that fixes everything that’s wrong with Iterator,
while being more generic.&lt;/p&gt;

&lt;p&gt;This lesson in design involves talking about immutability, imperative
programming, asynchrony and problems encountered when going FP, like
performance considerations, recursion and memory leaks. We are also
going to talk about ADTs, higher kinded polymorphism and type-classes
versus OOP subtyping. Interestingly the example presented will use
both OOP subtyping and type-classes and thus we can make a clear
comparison about what to use and when - a problem that the Scala
developer has in his daily work.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2017/03/15/fp-inception/?pk_campaign=rss&quot;&gt;Functional Programming Inception (Presentation)&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 15 Mar 2017 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2017/03/15/fp-inception/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2017/03/15/fp-inception/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Monix</category>
  </item>


<item>
  <title>Asynchronous Programming and Scala</title>
  <description>Asynchrony is everywhere and it subsumes concurrency. This article explains what asynchronous processing is and its challenges.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;Asynchrony is everywhere and it subsumes concurrency. This article explains what asynchronous processing is and its challenges.&lt;/p&gt;

&lt;h2 id=&quot;1-introduction&quot;&gt;1. Introduction&lt;/h2&gt;

&lt;p&gt;As a concept it is more general than &lt;em&gt;multithreading&lt;/em&gt;, although some
people confuse the two. If you’re looking for a relationship, you
could say:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;Multithreading &lt;: Asynchrony
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can represent asynchronous computations with a type:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Async[A] = (Try[A] =&gt; Unit) =&gt; Unit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If it looks ugly with those &lt;code&gt;Unit&lt;/code&gt; return types, that’s because
asynchrony is ugly. An asynchronous computation is any task, thread,
process, node somewhere on the network that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;executes outside of your program’s main flow or from the point of
view of the caller, it doesn’t execute on the current call-stack&lt;/li&gt;
  &lt;li&gt;receives a callback that will get called once the result is
finished processing&lt;/li&gt;
  &lt;li&gt;it provides no guarantee about when the result is signaled, no
guarantee that a result will be signaled at all&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s important to note asynchrony subsumes &lt;em&gt;concurrency&lt;/em&gt;, but not
necessarily &lt;em&gt;multithreading&lt;/em&gt;. Remember that in Javascript the majority
of all I/O actions (input or output) are asynchronous and even heavy
business logic is made asynchronous (with &lt;code&gt;setTimeout&lt;/code&gt; based scheduling)
in order to keep the interface responsive. But no kernel-level
multithreading is involved, Javascript being an N:1 multithreaded
platform.&lt;/p&gt;

&lt;p&gt;Introducing asynchrony into your program means you’ll have concurrency
problems because you never know when asynchronous computations will be
finished, so &lt;em&gt;composing&lt;/em&gt; the results of multiple asynchronous
computations running at the same time means you have to do
synchronization, as you can no longer rely on ordering. And not
relying on an order is a recipe for &lt;em&gt;nondeterminism&lt;/em&gt;.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Nondeterministic_algorithm&quot;&gt;Wikipedia says&lt;/a&gt;:
a &lt;em&gt;nondeterministic&lt;/em&gt; algorithm is an algorithm that, even for the same
input, can exhibit different behaviors on different runs, as opposed
to a &lt;em&gt;deterministic&lt;/em&gt; algorithm … A &lt;em&gt;concurrent&lt;/em&gt; algorithm can perform
differently on different runs due to a race condition.
&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/nondet.png&quot; width=&quot;775&quot; height=&quot;458&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;The astute reader could notice that the type in question can be seen &lt;em&gt;everywhere&lt;/em&gt;,
with some modifications depending on use-case and contract:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Observer_pattern&quot;&gt;Observer pattern&lt;/a&gt;
from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Design_Patterns&quot;&gt;Gang of Four&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;in Scala’s &lt;a href=&quot;http://www.scala-lang.org/api/current/scala/concurrent/Future.html&quot;&gt;Future&lt;/a&gt;,
which is defined by its abstract &lt;code&gt;onComplete&lt;/code&gt; method&lt;/li&gt;
  &lt;li&gt;in Java’s &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#submit-java.util.concurrent.Callable-&quot;&gt;ExecutorService.submit(Callable)&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;in Javascript’s &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener&quot;&gt;EventTarget.addEventListener&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;in &lt;a href=&quot;http://akka.io/&quot;&gt;Akka&lt;/a&gt; actors, although there the given callback
is replaced by the &lt;code&gt;sender()&lt;/code&gt; reference&lt;/li&gt;
  &lt;li&gt;in the Monix &lt;a href=&quot;https://github.com/monix/monix/blob/v2.2.1/monix-eval/shared/src/main/scala/monix/eval/Task.scala#L1253&quot;&gt;Task.Async&lt;/a&gt; definition&lt;/li&gt;
  &lt;li&gt;in the Monix &lt;a href=&quot;https://monix.io/api/2.2/monix/reactive/Observable.html&quot;&gt;Observable&lt;/a&gt;
and &lt;a href=&quot;https://monix.io/api/2.2/monix/reactive/Observer.html&quot;&gt;Observer&lt;/a&gt; pair&lt;/li&gt;
  &lt;li&gt;in the &lt;a href=&quot;http://www.reactive-streams.org/reactive-streams-1.0.0-javadoc/&quot;&gt;Reactive Streams&lt;/a&gt; specification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What do all of these abstractions have in common? They provide ways to
deal with asynchrony, some more successful than others.&lt;/p&gt;

&lt;h2 id=&quot;2-the-big-illusion&quot;&gt;2. The Big Illusion&lt;/h2&gt;

&lt;p&gt;We like to pretend that we can describe functions that can convert
asynchronous results to synchronous ones:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def await[A](fa: Async[A]): A
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Fact of the matter is that we can’t pretend that asynchronous
processes are equivalent with normal functions. If you need a lesson
in history for why we can’t pretend that, you only need to take a look
at why CORBA failed.&lt;/p&gt;

&lt;p&gt;With asynchronous processes we have the following very common
&lt;a href=&quot;https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing&quot;&gt;fallacies of distributed computing&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The network is reliable&lt;/li&gt;
  &lt;li&gt;Latency is zero&lt;/li&gt;
  &lt;li&gt;Bandwidth is infinite&lt;/li&gt;
  &lt;li&gt;The network is secure&lt;/li&gt;
  &lt;li&gt;Topology doesn’t change&lt;/li&gt;
  &lt;li&gt;There is one administrator&lt;/li&gt;
  &lt;li&gt;Transport cost is zero&lt;/li&gt;
  &lt;li&gt;The network is homogeneous&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of them are true of course. Which means code gets written with
little error handling for network failures, ignorance of network
latency or packet loss, ignorance of bandwidth limits and in general
ignorance of the ensuing nondeterminism.&lt;/p&gt;

&lt;p&gt;People have tried to cope with this by:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;callbacks, callbacks everywhere, equivalent to basically ignoring
the problem, as it happens in Javascript, which leads to the well
known effect of &lt;em&gt;callback hell&lt;/em&gt;, paid for with the sweat and blood
of programmers that constantly imagine having chosen a different
life path&lt;/li&gt;
  &lt;li&gt;blocking threads, on top of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Thread_(computing)#1:1_.28kernel-level_threading.29&quot;&gt;1:1 (kernel-level) multithreading&lt;/a&gt;
platforms&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Continuation&quot;&gt;first-class continuations&lt;/a&gt;,
implemented for example by Scheme in
&lt;a href=&quot;https://en.wikipedia.org/wiki/Call-with-current-continuation&quot;&gt;call/cc&lt;/a&gt;,
being the ability to save the execution state at any point and
return to that point at a later point in the program&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;async&lt;/code&gt; / &lt;code&gt;await&lt;/code&gt; language extension from C#, also implemented in
the &lt;a href=&quot;https://github.com/scala/async&quot;&gt;scala-async&lt;/a&gt; library and in the
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function&quot;&gt;latest ECMAScript&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Green_threads&quot;&gt;Green threads&lt;/a&gt;
managed by the runtime, possibly in combination with
&lt;a href=&quot;https://en.wikipedia.org/wiki/Thread_(computing)#M:N_.28hybrid_threading.29&quot;&gt;M:N multithreading&lt;/a&gt;,
to simulate blocking for asynchronous actions; examples including
Golang but also Haskell&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Actor_model&quot;&gt;actor model&lt;/a&gt; as implemented in Erlang or Akka,
or &lt;a href=&quot;https://en.wikipedia.org/wiki/Communicating_sequential_processes&quot;&gt;CSP&lt;/a&gt; such as
in &lt;a href=&quot;https://github.com/clojure/core.async&quot;&gt;Clojure’s core.async&lt;/a&gt; or in Golang&lt;/li&gt;
  &lt;li&gt;Monads being used for ordering and composition, such as Haskell’s
&lt;a href=&quot;https://hackage.haskell.org/package/async-2.1.1/docs/Control-Concurrent-Async.html&quot;&gt;Async&lt;/a&gt; type
in combination with the &lt;a href=&quot;https://wiki.haskell.org/IO_inside&quot;&gt;IO&lt;/a&gt; type, or
&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/asynchronous-workflows&quot;&gt;F# asynchronous workflows&lt;/a&gt;,
or &lt;a href=&quot;http://docs.scala-lang.org/overviews/core/futures.html&quot;&gt;Scala’s Futures and Promises&lt;/a&gt;,
or the &lt;a href=&quot;https://monix.io/docs/2x/eval/task.html&quot;&gt;Monix Task&lt;/a&gt;
or the &lt;a href=&quot;https://github.com/scalaz/scalaz/blob/scalaz-seven/concurrent/src/main/scala/scalaz/concurrent/Task.scala&quot;&gt;Scalaz Task&lt;/a&gt;,
etc, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there are so many solutions, that’s because none of them is
suitable as a general purpose mechanism for dealing with asynchrony.
The &lt;a href=&quot;https://en.wikipedia.org/wiki/No_Silver_Bullet&quot;&gt;no silver bullet&lt;/a&gt;
dilemma is relevant here, with memory management and concurrency being
the biggest problems that we face as software developers.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;WARNING - personal opinion and rant:&lt;/strong&gt; People like to boast about M:N
platforms like Golang, however I prefer 1:1 multithreaded platforms,
like the JVM or dotNET.
&lt;br&gt;&lt;br&gt;
Because you can build M:N multithreading on top of 1:1 given enough
expressiveness in the programming language (e.g. Scala’s Futures and
Promises, Task, Clojure’s core.async, etc), but if that M:N runtime starts being
unsuitable for your usecase, then you can’t fix it or replace it
without replacing the platform. And yes, most M:N platforms are broken
in one way or another.
&lt;br&gt;&lt;br&gt;
Indeed learning about all the possible solutions and making choices is
freaking painful, but it is much less painful than making uninformed
choices, with the TOOWTDI and “worse is better” mentalities being in
this case actively harmful. People complaining about the difficulty of
learning a new and expressive language like Scala or Haskell are
missing the point, because if they have to deal with concurrency, then
learning a new programming language is going to be the least of their
problems. I know people that have quit the software industry because
of the shift to concurrency.
&lt;/p&gt;

&lt;h2 id=&quot;3-callback-hell&quot;&gt;3. Callback Hell&lt;/h2&gt;

&lt;p&gt;Let’s build an artificial example made to illustrate our challenges.
Say we need to initiate two asynchronous processes and combine their
result.&lt;/p&gt;

&lt;p&gt;First let’s define a function that executes stuff asynchronously:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent.ExecutionContext.global

type Async[A] = (A =&gt; Unit) =&gt; Unit

def timesTwo(n: Int): Async[Int] =
  onFinish =&gt; {
    global.execute(new Runnable {
      def run(): Unit = {
        val result = n * 2
        onFinish(result)
      }
    })
  }

// Usage
timesTwo(20) { result =&gt; println(s&quot;Result: $result&quot;) }
//=&gt; Result: 40
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;31-sequencing-purgatory-of-side-effects&quot;&gt;3.1. Sequencing (Purgatory of Side-effects)&lt;/h3&gt;

&lt;p&gt;Let’s combine two asynchronous results, with the execution happening
one after another, in a neat sequence:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def timesFour(n: Int): Async[Int] =
  onFinish =&gt; {
    timesTwo(n) { a =&gt;
      timesTwo(n) { b =&gt;
        // Combining the two results
        onFinish(a + b)
      }
    }
  }

// Usage
timesFour(20) { result =&gt; println(s&quot;Result: $result&quot;) }
//=&gt; Result: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Looks simple now, but we are only combining two results, one after another.&lt;/p&gt;

&lt;p&gt;The big problem however is that &lt;em&gt;asynchrony infects everything it touches&lt;/em&gt;.
Let’s assume for  the sake of argument that we start with a pure function:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def timesFour(n: Int): Int = n * 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But then your enterprise architect, after hearing about these Enterprise JavaBeans and
a lap dance, decides that you should depend on this asynchronous &lt;code&gt;timesTwo&lt;/code&gt;
function. And now our &lt;code&gt;timesFour&lt;/code&gt; implementation changes from a pure mathematical
function to a side-effectful one and we have no choice in the matter.
And without a well grown &lt;code&gt;Async&lt;/code&gt; type, we are forced to deal with side-effectful
callbacks for the whole pipeline. And blocking for the result won’t help,
as you’re just hiding the problem, see &lt;a href=&quot;#2-the-big-illusion&quot;&gt;section 2&lt;/a&gt; for why.&lt;/p&gt;

&lt;p&gt;But wait, things are about to get worse 😷&lt;/p&gt;

&lt;h3 id=&quot;32-parallelism-limbo-of-nondeterminism&quot;&gt;3.2. Parallelism (Limbo of Nondeterminism)&lt;/h3&gt;

&lt;p&gt;The second call we made above is not dependent on the first call,
therefore it can run in parallel. On the JVM we can run CPU-bound
tasks in parallel, but this is relevant for Javascript as well, as we
could be making Ajax requests or talking with web workers.&lt;/p&gt;

&lt;p&gt;Unfortunately here things can get a little complicated. First of all
the naive way to do it is terribly wrong:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// REALLY BAD SAMPLE

def timesFourInParallel(n: Int): Async[Int] =
  onFinish =&gt; {
    var cacheA = 0

    timesTwo(n) { a =&gt; cacheA = a }

    timesTwo(n) { b =&gt;
      // Combining the two results
      onFinish(cacheA + b)
    }
  }

timesFourInParallel(20) { result =&gt; println(s&quot;Result: $result&quot;) }
//=&gt; Result: 80

timesFourInParallel(20) { result =&gt; println(s&quot;Result: $result&quot;) }
//=&gt; Result: 40
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This right here is an example showing &lt;em&gt;nondeterminism&lt;/em&gt; in action. We
get &lt;em&gt;no ordering guarantees&lt;/em&gt; about which one finishes first, so if we
want parallel processing, we need to model a mini state machine for
doing synchronization.&lt;/p&gt;

&lt;p&gt;First, we define our ADT describing the state-machine:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Defines the state machine
sealed trait State
// Initial state
case object Start extends State
// We got a B, waiting for an A
final case class WaitForA(b: Int) extends State
// We got a A, waiting for a B
final case class WaitForB(a: Int) extends State
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then we can evolve this state machine asynchronously:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// BAD SAMPLE FOR THE JVM (only works for Javascript)

def timesFourInParallel(n: Int): Async[Int] = {
  onFinish =&gt; {
    var state: State = Start

    timesTwo(n) { a =&gt;
      state match {
        case Start =&gt;
          state = WaitForB(a)
        case WaitForA(b) =&gt;
          onFinish(a + b)
        case WaitForB(_) =&gt;
          // Can&apos;t be caught b/c async, hopefully it gets reported
          throw new IllegalStateException(state.toString)
      }
    }

    timesTwo(n) { b =&gt;
      state match {
        case Start =&gt;
          state = WaitForA(b)
        case WaitForB(a) =&gt;
          onFinish(a + b)
        case WaitForA(_) =&gt;
          // Can&apos;t be caught b/c async, hopefully it gets reported
          throw new IllegalStateException(state.toString)
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To better visualize what we’re dealing with, here’s the state machine:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/callback-hell-stm.png&quot; width=&quot;642&quot; height=&quot;670&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;But wait, we aren’t over because the JVM has true 1:1 multi-threading, which means
we get to enjoy &lt;em&gt;shared memory concurrency&lt;/em&gt; and thus access to that &lt;code&gt;state&lt;/code&gt; has to
be synchronized.&lt;/p&gt;

&lt;p&gt;One solution is to use &lt;code&gt;synchronized&lt;/code&gt; blocks, also called &lt;em&gt;intrinsic locks&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// We need a common reference to act as our monitor
val lock = new AnyRef
var state: State = Start

timesTwo(n) { a =&gt;
  lock.synchronized {
    state match {
      case Start =&gt;
        state = WaitForB(a)
      case WaitForA(b) =&gt;
        onFinish(a + b)
      case WaitForB(_) =&gt;
        // Can&apos;t be caught b/c async, hopefully it gets reported
        throw new IllegalStateException(state.toString)
    }
  }
}

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

&lt;p&gt;Such high-level locks protect resources (such as our &lt;code&gt;state&lt;/code&gt;) from
being accessed in parallel by multiple threads. But I personally
prefer to avoid high-level locks because the kernel’s scheduler can
freeze any thread for any reason, including threads that hold locks,
freezing a thread holding a lock means that other threads will be
unable to make progress and if you want to guarantee constant progress
(e.g. soft real-time characteristics), then
&lt;a href=&quot;https://en.wikipedia.org/wiki/Non-blocking_algorithm&quot;&gt;non-blocking&lt;/a&gt;
logic is preferred when possible.&lt;/p&gt;

&lt;p&gt;So an alternative is to use an
&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html&quot;&gt;AtomicReference&lt;/a&gt;,
which is perfect for this case:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// CORRECT VERSION FOR JVM

import scala.annotation.tailrec
import java.util.concurrent.atomic.AtomicReference

def timesFourInParallel(n: Int): Async[Int] = {
  onFinish =&gt; {
    val state = new AtomicReference[State](Start)

    @tailrec def onValueA(a: Int): Unit =
      state.get match {
        case Start =&gt;
          if (!state.compareAndSet(Start, WaitForB(a)))
            onValueA(a) // retry
        case WaitForA(b) =&gt;
          onFinish(a + b)
        case WaitForB(_) =&gt;
          // Can&apos;t be caught b/c async, hopefully it gets reported
          throw new IllegalStateException(state.toString)
      }

    timesTwo(n)(onValueA)

    @tailrec def onValueB(b: Int): Unit =
      state.get match {
        case Start =&gt;
          if (!state.compareAndSet(Start, WaitForA(b)))
            onValueB(b) // retry
        case WaitForB(a) =&gt;
          onFinish(a + b)
        case WaitForA(_) =&gt;
          // Can&apos;t be caught b/c async, hopefully it gets reported
          throw new IllegalStateException(state.toString)
      }

    timesTwo(n)(onValueB)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;PRO-TIP:&lt;/strong&gt; if you want code that cross-compiles to Javascript / Scala.js,
along with performance tweaks and cool utilities for manipulating atomic references,
try the &lt;a href=&quot;https://monix.io/docs/2x/execution/atomic.html&quot;&gt;Atomic&lt;/a&gt; type
from &lt;a href=&quot;https://monix.io/&quot;&gt;Monix&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;Are you getting pumped? Let’s take it up a notch 😝&lt;/p&gt;

&lt;h3 id=&quot;33-recursivity-wrath-of-stackoverflow&quot;&gt;3.3. Recursivity (Wrath of StackOverflow)&lt;/h3&gt;

&lt;p&gt;What if I were to tell you that the above &lt;code&gt;onFinish&lt;/code&gt; call is
stack-unsafe and if you aren’t going to force an &lt;em&gt;asynchronous
boundary&lt;/em&gt; when calling it, then your program can blow up
with a &lt;code&gt;StackOverflowError&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;You shouldn’t take my word for it. Let’s first have some fun and
define the above operation in a generic way:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.annotation.tailrec
import java.util.concurrent.atomic.AtomicReference

type Async[+A] = (A =&gt; Unit) =&gt; Unit

def mapBoth[A,B,R](fa: Async[A], fb: Async[B])(f: (A,B) =&gt; R): Async[R] = {
  // Defines the state machine
  sealed trait State[+A,+B]
  // Initial state
  case object Start extends State[Nothing, Nothing]
  // We got a B, waiting for an A
  final case class WaitForA[+B](b: B) extends State[Nothing,B]
  // We got a A, waiting for a B
  final case class WaitForB[+A](a: A) extends State[A,Nothing]

  onFinish =&gt; {
    val state = new AtomicReference[State[A,B]](Start)

    @tailrec def onValueA(a: A): Unit =
      state.get match {
        case Start =&gt;
          if (!state.compareAndSet(Start, WaitForB(a)))
            onValueA(a) // retry
        case WaitForA(b) =&gt;
          onFinish(f(a,b))
        case WaitForB(_) =&gt;
          // Can&apos;t be caught b/c async, hopefully it gets reported
          throw new IllegalStateException(state.toString)
      }

    @tailrec def onValueB(b: B): Unit =
      state.get match {
        case Start =&gt;
          if (!state.compareAndSet(Start, WaitForA(b)))
            onValueB(b) // retry
        case WaitForB(a) =&gt;
          onFinish(f(a,b))
        case WaitForA(_) =&gt;
          // Can&apos;t be caught b/c async, hopefully it gets reported
          throw new IllegalStateException(state.toString)
      }

    fa(onValueA)
    fb(onValueB)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now we can define an operation similar to Scala’s &lt;code&gt;Future.sequence&lt;/code&gt;,
because our will is strong and our courage immensurable 😇&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def sequence[A](list: List[Async[A]]): Async[List[A]] = {
  @tailrec def loop(list: List[Async[A]], acc: Async[List[A]]): Async[List[A]] =
    list match {
      case Nil =&gt;
        onFinish =&gt; acc(r =&gt; onFinish(r.reverse))
      case x :: xs =&gt;
        val update = mapBoth(x, acc)(_ :: _)
        loop(xs, update)
    }

  val empty: Async[List[A]] = _(Nil)
  loop(list, empty)
}

// Invocation
sequence(List(timesTwo(10), timesTwo(20), timesTwo(30))) { r =&gt;
  println(s&quot;Result: $r&quot;)
}
//=&gt; Result: List(20, 40, 60)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh, you really think we are done?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val list = 0.until(10000).map(timesTwo).toList
sequence(list)(r =&gt; println(s&quot;Sum: ${r.sum}&quot;))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Behold the glorious memory error that will probably crash your program in production,
being considered a fatal error that Scala’s &lt;code&gt;NonFatal&lt;/code&gt; does not catch:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;java.lang.StackOverflowError
  at java.util.concurrent.ForkJoinPool.externalPush(ForkJoinPool.java:2414)
  at java.util.concurrent.ForkJoinPool.execute(ForkJoinPool.java:2630)
  at scala.concurrent.impl.ExecutionContextImpl$$anon$3.execute(ExecutionContextImpl.scala:131)
  at scala.concurrent.impl.ExecutionContextImpl.execute(ExecutionContextImpl.scala:20)
  at .$anonfun$timesTwo$1(&lt;pastie&gt;:27)
  at .$anonfun$timesTwo$1$adapted(&lt;pastie&gt;:26)
  at .$anonfun$mapBoth$1(&lt;pastie&gt;:66)
  at .$anonfun$mapBoth$1$adapted(&lt;pastie&gt;:40)
  at .$anonfun$mapBoth$1(&lt;pastie&gt;:67)
  at .$anonfun$mapBoth$1$adapted(&lt;pastie&gt;:40)
  at .$anonfun$mapBoth$1(&lt;pastie&gt;:67)
  at .$anonfun$mapBoth$1$adapted(&lt;pastie&gt;:40)
  at .$anonfun$mapBoth$1(&lt;pastie&gt;:67)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As I said, that &lt;code&gt;onFinish&lt;/code&gt; call being made without a &lt;em&gt;forced async
boundary&lt;/em&gt; can lead to a stack-overflow error. On top of Javascript
this can be solved by scheduling it with &lt;code&gt;setTimeout&lt;/code&gt; and on top of
the JVM you need a thread-pool or a Scala &lt;code&gt;ExecutionContext&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Are you feeling the fire yet? 🔥&lt;/p&gt;

&lt;h2 id=&quot;4-futures-and-promises&quot;&gt;4. Futures and Promises&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;scala.concurrent.Future&lt;/code&gt; describes strictly evaluated
asynchronous computations, being similar to our &lt;code&gt;Async&lt;/code&gt; type used
above.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Futures_and_promises&quot;&gt;Wikipedia says&lt;/a&gt;:
Future and Promise are constructs used for synchronizing program
execution in some concurrent programming languages. They describe an
object that acts as a proxy for a result that is initially unknown,
usually because the computation of its value is yet incomplete.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;Author’s Rant:&lt;/strong&gt; The &lt;code&gt;docs.scala-lang.org&lt;/code&gt; article on
&lt;a href=&quot;http://docs.scala-lang.org/overviews/core/futures.html&quot;&gt;Futures and Promises&lt;/a&gt; currently
says that “&lt;em&gt;Futures provide a way to reason about performing many
operations in parallel– in an efficient and non-blocking way&lt;/em&gt;”, but
that is misleading, a source of confusion.
&lt;br&gt;&lt;br&gt;
The &lt;code&gt;Future&lt;/code&gt; type describes &lt;em&gt;asynchrony&lt;/em&gt; and not parallelism. Yes, you
can do things in parallel with it, but it’s not meant only for
parallelism (async != parallelism) and for people looking into ways to
use their CPU capacity to its fullest, working with &lt;code&gt;Future&lt;/code&gt; can prove
to be expensive and unwise, because in certain cases it has performance
issues, see &lt;a href=&quot;#44-performance-considerations&quot;&gt;section 4.4&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Future&lt;/code&gt; is an interface defined by 2 primary operations, along with
many combinators defined based on those primary operations:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.util.Try
import scala.concurrent.ExecutionContext

trait Future[+T] {
  // abstract
  def value: Option[Try[T]]

  // abstract
  def onComplete(f: Try[T] =&gt; Unit)(implicit ec: ExecutionContext): Unit

  // Transforms values
  def map[U](f: T =&gt; U)(implicit ec: ExecutionContext): Future[U] = ???
  // Sequencing ;-)
  def flatMap[U](f: T =&gt; Future[U])(implicit ec: ExecutionContext): Future[U] = ???
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The properties of &lt;code&gt;Future&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Eager_evaluation&quot;&gt;Eagerly evaluated&lt;/a&gt;
(strict and not lazy), meaning that when the caller of a function
receives a &lt;code&gt;Future&lt;/code&gt; reference, whatever asynchronous process that
should complete it has probably started already.&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://en.wikipedia.org/wiki/Memoization&quot;&gt;Memoized&lt;/a&gt; (cached),
since being eagerly evaluated means that it behaves like a normal
value instead of a function and the final result needs to be
available to all listeners. The purpose of the &lt;code&gt;value&lt;/code&gt; property is
to return that memoized result or &lt;code&gt;None&lt;/code&gt; if it isn’t complete
yet. Goes without saying that calling its &lt;code&gt;def value&lt;/code&gt; yields a
non-deterministic result.&lt;/li&gt;
  &lt;li&gt;Streams a single result and it shows because of the memoization
applied. So when listeners are registered for completion, they’ll
only get called once at most.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Explanatory notes about the &lt;code&gt;ExecutionContext&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code&gt;ExecutionContext&lt;/code&gt; manages asynchronous execution and although
you can view it as a thread-pool, it’s not necessarily a thread-pool
(because async != multithreading or parallelism).&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;onComplete&lt;/code&gt; is basically our &lt;code&gt;Async&lt;/code&gt; type defined above,
however it takes an &lt;code&gt;ExecutionContext&lt;/code&gt; because all completion
callbacks need to be called asynchronously.&lt;/li&gt;
  &lt;li&gt;All combinators and utilities are built on top of &lt;code&gt;onComplete&lt;/code&gt;,
therefore all combinators and utilities must also take an
&lt;code&gt;ExecutionContext&lt;/code&gt; parameter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don’t understand why that &lt;code&gt;ExecutionContext&lt;/code&gt; is needed in all
those signatures, go back and re-read &lt;a href=&quot;#33-recursivity-wrath-of-stackoverflow&quot;&gt;section 3.3&lt;/a&gt; and don’t
come back until you do.&lt;/p&gt;

&lt;h3 id=&quot;41-sequencing&quot;&gt;4.1. Sequencing&lt;/h3&gt;

&lt;p&gt;Let’s redefine our function from &lt;a href=&quot;#3-callback-hell&quot;&gt;section 3&lt;/a&gt; in terms of &lt;code&gt;Future&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent.{Future, ExecutionContext}

def timesTwo(n: Int)(implicit ec: ExecutionContext): Future[Int] =
  Future(n * 2)

// Usage
{
  import scala.concurrent.ExecutionContext.Implicits.global

  timesTwo(20).onComplete { result =&gt; println(s&quot;Result: $result&quot;) }
  //=&gt; Result: Success(40)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Easy enough, the &lt;code&gt;Future.apply&lt;/code&gt; builder executes the given computation
on the given &lt;code&gt;ExecutionContext&lt;/code&gt;. So on the JVM, assuming the &lt;code&gt;global&lt;/code&gt;
execution context, it’s going to run on a different thread.&lt;/p&gt;

&lt;p&gt;Now to do sequencing like in &lt;a href=&quot;#31-sequencing-purgatory-of-side-effects&quot;&gt;section 3.1&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def timesFour(n: Int)(implicit ec: ExecutionContext): Future[Int] =
  for (a &lt;- timesTwo(n); b &lt;- timesTwo(n)) yield a + b

// Usage
{
  import scala.concurrent.ExecutionContext.Implicits.global

  timesFour(20).onComplete { result =&gt; println(s&quot;Result: $result&quot;) }
  //=&gt; Result: Success(80)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Easy enough. That “&lt;em&gt;for comprehension&lt;/em&gt;” magic right there is
translated to nothing more than calls to &lt;code&gt;flatMap&lt;/code&gt; and &lt;code&gt;map&lt;/code&gt;, being
literally equivalent with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def timesFour(n: Int)(implicit ec: ExecutionContext): Future[Int] =
  timesTwo(n).flatMap { a =&gt;
    timesTwo(n).map { b =&gt;
      a + b
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And if you import &lt;a href=&quot;https://github.com/scala/async&quot;&gt;scala-async&lt;/a&gt; in
your project, then you can do it like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.async.Async.{async, await}

def timesFour(n: Int)(implicit ec: ExecutionContext): Future[Int] =
  async {
    val a = await(timesTwo(a))
    val b = await(timesTwo(b))
    a + b
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;scala-async&lt;/code&gt; library is powered by macros and will translate your
code to something equivalent to &lt;code&gt;flatMap&lt;/code&gt; and &lt;code&gt;map&lt;/code&gt; calls. So in other
words &lt;code&gt;await&lt;/code&gt; does not block threads, even though it gives the
illusion that it does.&lt;/p&gt;

&lt;p&gt;This looks great actually, unfortunately it has many limitations.  The
library &lt;em&gt;cannot rewrite&lt;/em&gt; your code in case the &lt;code&gt;await&lt;/code&gt; is inside an
anonymous function and unfortunately Scala code is usually full of
such expressions. This does not work:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// BAD SAMPLE
def sum(list: List[Future[Int]])(implicit ec; ExecutionContext): Future[Int] =
  async {
    var sum = 0
    // Nope, not going to work because &quot;for&quot; is translated to &quot;foreach&quot;
    for (f &lt;- list) {
      sum += await(f)
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This approach gives the illusion of having &lt;em&gt;first-class
continuations&lt;/em&gt;, but these continuations are unfortunately not first
class, being just a compiler-managed rewrite of the code. And yes,
this restriction applies to C# and ECMAScript as well. Which is a
pity, because it means &lt;code&gt;async&lt;/code&gt; code will not be heavy on FP.&lt;/p&gt;

&lt;p&gt;Remember my rant from above about the no silver bullet? 😞&lt;/p&gt;

&lt;h3 id=&quot;42-parallelism&quot;&gt;4.2. Parallelism&lt;/h3&gt;

&lt;p&gt;Just as in &lt;a href=&quot;#32-parallelism-limbo-of-nondeterminism&quot;&gt;section 3.2&lt;/a&gt; those two function calls are
independent of each other, which means that we can call them in
parallel. With &lt;code&gt;Future&lt;/code&gt; this is easier, although its evaluation
semantics can be a little confusing for beginners:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def timesFourInParallel(n: Int)(implicit ec: ExecutionContext): Future[Int] = {
  // Future is eagerly evaluated, so this will trigger the
  // execution of both before the composition happens
  val fa = timesTwo(n)
  val fb = timesTwo(n)

  for (a &lt;- fa; b &lt;- fb) yield a + b
  // fa.flatMap(a =&gt; fb.map(b =&gt; a + b))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It can be a little confusing and it catches beginners
off-guard. Because of its execution model, in order to execute things
in parallel, you simply have to initialize those future references
before the composition happens.&lt;/p&gt;

&lt;p&gt;An alternative would be to use &lt;code&gt;Future.sequence&lt;/code&gt;, which works for
arbitrary collections:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def timesFourInParallel(n: Int)(implicit ec: ExecutionContext): Future[Int] =
  Future.sequence(timesTwo(n) :: timesTwo(n) :: Nil).map(_.sum)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This too can catch beginners by surprise, because those futures are
going to be executed in parallel only if the collection given to
&lt;code&gt;sequence&lt;/code&gt; is strict (not like Scala’s &lt;code&gt;Stream&lt;/code&gt; or some &lt;code&gt;Iterator&lt;/code&gt;). And
the name is sort of a misnomer obviously.&lt;/p&gt;

&lt;h3 id=&quot;43-recursivity&quot;&gt;4.3. Recursivity&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Future&lt;/code&gt; type is entirely safe for recursive operations (because
of the reliance on the &lt;code&gt;ExecutionContext&lt;/code&gt; for executing callbacks). So
retrying the sample in &lt;a href=&quot;#33-recursivity-wrath-of-stackoverflow&quot;&gt;section 3.3&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def mapBoth[A,B,R](fa: Future[A], fb: Future[B])(f: (A,B) =&gt; R)
  (implicit ec: ExecutionContext): Future[R] = {

  for (a &lt;- fa; b &lt;- fb) yield f(a,b)
}

def sequence[A](list: List[Future[A]])
  (implicit ec: ExecutionContext): Future[List[A]] = {

  val seed = Future.successful(List.empty[A])
  list.foldLeft(seed)((acc,f) =&gt; for (l &lt;- acc; a &lt;- f) yield a :: l)
    .map(_.reverse)
}

// Invocation
{
  import scala.concurrent.ExecutionContext.Implicits.global

  sequence(List(timesTwo(10), timesTwo(20), timesTwo(30))).foreach(println)
  // =&gt; List(20, 40, 60)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And this time we get no &lt;code&gt;StackOverflowError&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val list = 0.until(10000).map(timesTwo).toList
sequence(list).foreach(r =&gt; println(s&quot;Sum: ${r.sum}&quot;))
//=&gt; Sum: 99990000
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;44-performance-considerations&quot;&gt;4.4. Performance Considerations&lt;/h3&gt;

&lt;p&gt;The trouble with &lt;code&gt;Future&lt;/code&gt; is that each call to &lt;code&gt;onComplete&lt;/code&gt; will use
an &lt;code&gt;ExecutionContext&lt;/code&gt; for execution and in general this means that a
&lt;code&gt;Runnable&lt;/code&gt; is sent in a thread-pool, thus forking a (logical) thread.
If you have CPU-bounded tasks, this implementation detail is actually
a disaster for performance because jumping threads means
&lt;a href=&quot;https://en.wikipedia.org/wiki/Context_switch&quot;&gt;context switches&lt;/a&gt;,
along with the CPU
&lt;a href=&quot;https://en.wikipedia.org/wiki/Locality_of_reference&quot;&gt;cache locality&lt;/a&gt;
being destroyed. Of course, the implementation does have certain optimizations,
like the &lt;code&gt;flatMap&lt;/code&gt; implementation using an internal execution context that’s
trampolined, in order to avoid forks when chaining those internal
callbacks, but it’s not enough and benchmarking doesn’t lie.&lt;/p&gt;

&lt;p&gt;Also due to it being memoized means that upon completion the
implementation is forced to execute at least one
&lt;code&gt;AtomicReference.compareAndSet&lt;/code&gt; per producer, plus one &lt;code&gt;compareAndSet&lt;/code&gt;
call per listener registered before the &lt;code&gt;Future&lt;/code&gt; is complete. And such
calls are quite expensive, all because we need memoization that plays
well with multithreading.&lt;/p&gt;

&lt;p&gt;In other words if you want to exploit your CPU to its fullest for CPU-bound
tasks, then working with futures and promises is not such a good idea.&lt;/p&gt;

&lt;p&gt;If you want to see how Scala’s &lt;code&gt;Future&lt;/code&gt; implementation compares with
&lt;code&gt;Task&lt;/code&gt;, see the following
&lt;a href=&quot;https://github.com/rossabaker/benchmarks/pull/4&quot;&gt;recent benchmark&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[info] Benchmark                   (size)   Mode  Cnt     Score     Error  Units
[info] FlatMap.fs2Apply             10000  thrpt   20   291.459 ±   6.321  ops/s
[info] FlatMap.fs2Delay             10000  thrpt   20  2606.864 ±  26.442  ops/s
[info] FlatMap.fs2Now               10000  thrpt   20  3867.300 ± 541.241  ops/s
[info] FlatMap.futureApply          10000  thrpt   20   212.691 ±   9.508  ops/s
[info] FlatMap.futureSuccessful     10000  thrpt   20   418.736 ±  29.121  ops/s
[info] FlatMap.futureTrampolineEc   10000  thrpt   20   423.647 ±   8.543  ops/s
[info] FlatMap.monixApply           10000  thrpt   20   399.916 ±  15.858  ops/s
[info] FlatMap.monixDelay           10000  thrpt   20  4994.156 ±  40.014  ops/s
[info] FlatMap.monixNow             10000  thrpt   20  6253.182 ±  53.388  ops/s
[info] FlatMap.scalazApply          10000  thrpt   20   188.387 ±   2.989  ops/s
[info] FlatMap.scalazDelay          10000  thrpt   20  1794.680 ±  24.173  ops/s
[info] FlatMap.scalazNow            10000  thrpt   20  2041.300 ± 128.729  ops/s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see the &lt;a href=&quot;https://monix.io/docs/2x/eval/task.html&quot;&gt;Monix Task&lt;/a&gt; destroys
Scala’s &lt;code&gt;Future&lt;/code&gt; for CPU-bound tasks.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; this benchmark is limited, there are still use-cases where
usage of &lt;code&gt;Future&lt;/code&gt; is faster (e.g. the Monix &lt;a href=&quot;https://monix.io/docs/2x/reactive/observers.html&quot;&gt;Observer&lt;/a&gt;
uses &lt;code&gt;Future&lt;/code&gt; for back-pressure for a good reason) and performance is
often not relevant, like when doing I/O, in which case throughput
will not be CPU-bound.
&lt;/p&gt;

&lt;h2 id=&quot;5-task-scalas-io-monad&quot;&gt;5. Task, Scala’s IO Monad&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Task&lt;/code&gt; is a data type for controlling possibly lazy &amp; asynchronous computations,
useful for controlling side-effects, avoiding nondeterminism and callback-hell.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://monix.io/&quot;&gt;Monix&lt;/a&gt; library provides a very sophisticated
&lt;a href=&quot;https://monix.io/docs/2x/eval/task.html&quot;&gt;Task&lt;/a&gt; implementation, inspired by the
&lt;a href=&quot;https://github.com/scalaz/scalaz/blob/scalaz-seven/concurrent/src/main/scala/scalaz/concurrent/Task.scala&quot;&gt;Task in Scalaz&lt;/a&gt;.
Same concept, different implementation.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
The &lt;code&gt;Task&lt;/code&gt; type is also inspired by &lt;a href=&quot;https://wiki.haskell.org/IO_inside&quot;&gt;Haskell’s IO monad&lt;/a&gt;,
being in this author’s opinion the true &lt;code&gt;IO&lt;/code&gt; type for Scala.
&lt;br&gt;&lt;br&gt;
This is a matter of debate, as Scalaz also exposes a separate &lt;code&gt;IO&lt;/code&gt; type
that only deals with synchronous execution. The Scalaz &lt;code&gt;IO&lt;/code&gt; is not async, which
means that it doesn’t tell the whole story, because on top of the JVM you need
to represent async computations somehow. In Haskell on the other hand you have
the &lt;code&gt;Async&lt;/code&gt; type which is converted to &lt;code&gt;IO&lt;/code&gt;, possibly managed by the runtime
(green-threads and all).
&lt;br&gt;&lt;br&gt;
On the JVM, with the Scalaz implementation, we can’t represent async
computations with &lt;code&gt;IO&lt;/code&gt; and without blocking threads on evaluation, which is
something to avoid, because
&lt;a href=&quot;https://monix.io/docs/2x/best-practices/blocking.html&quot;&gt;blocking threads is error prone&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;In summary the &lt;code&gt;Task&lt;/code&gt; type:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;models lazy &amp; asynchronous evaluation&lt;/li&gt;
  &lt;li&gt;models a producer pushing only one value to one or multiple consumers&lt;/li&gt;
  &lt;li&gt;it is lazily evaluated, so compared with &lt;code&gt;Future&lt;/code&gt; it doesn’t trigger the execution, or any effects until &lt;code&gt;runAsync&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;it is not memoized by default on evaluation, but the Monix &lt;code&gt;Task&lt;/code&gt; can be&lt;/li&gt;
  &lt;li&gt;doesn’t necessarily execute on another logical thread&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specific to the Monix implementation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;allows for cancelling of a running computation&lt;/li&gt;
  &lt;li&gt;never blocks any threads in its implementation&lt;/li&gt;
  &lt;li&gt;does not expose any API calls that can block threads&lt;/li&gt;
  &lt;li&gt;all async operations are stack safe&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A visual representation of where &lt;code&gt;Task&lt;/code&gt; sits in the design space:&lt;/p&gt;

&lt;table&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: center&quot;&gt;Eager&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Lazy&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Synchronous&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;A&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;() =&gt; A&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&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;a href=&quot;https://monix.io/docs/2x/eval/coeval.html&quot;&gt;Coeval[A]&lt;/a&gt;, &lt;a href=&quot;https://github.com/scalaz/scalaz/blob/scalaz-seven/effect/src/main/scala/scalaz/effect/IO.scala&quot;&gt;IO[A]&lt;/a&gt;
&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;strong&gt;Asynchronous&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;(A =&gt; Unit) =&gt; Unit&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;(A =&gt; Unit) =&gt; Unit&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt; &lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;Future[A]&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;https://monix.io/docs/2x/eval/task.html&quot;&gt;Task[A]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;51-sequencing&quot;&gt;5.1. Sequencing&lt;/h3&gt;

&lt;p&gt;Redefining our function from &lt;a href=&quot;#3-callback-hell&quot;&gt;section 3&lt;/a&gt; in terms of &lt;code&gt;Task&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import monix.eval.Task

def timesTwo(n: Int): Task[Int] =
  Task(n * 2)

// Usage
{
  // Our ExecutionContext needed on evaluation
  import monix.execution.Scheduler.Implicits.global

  timesTwo(20).foreach { result =&gt; println(s&quot;Result: $result&quot;) }
  //=&gt; Result: 40
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The code seems to be almost the same as the &lt;code&gt;Future&lt;/code&gt; version in
&lt;a href=&quot;#41-sequencing&quot;&gt;section 4.1&lt;/a&gt;, the only difference is that our &lt;code&gt;timesTwo&lt;/code&gt;
function no longer takes an &lt;code&gt;ExecutionContext&lt;/code&gt; as a parameter.
This is because &lt;code&gt;Task&lt;/code&gt; references are lazy, being like functions,
so nothing gets printed until the call to &lt;code&gt;foreach&lt;/code&gt; which forces
the evaluation to happen. It is there that we need a
&lt;a href=&quot;https://monix.io/docs/2x/execution/scheduler.html&quot;&gt;Scheduler&lt;/a&gt;,
which is Monix’s enhanced &lt;code&gt;ExecutionContext&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now to do sequencing like in &lt;a href=&quot;#31-sequencing-purgatory-of-side-effects&quot;&gt;section 3.1&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def timesFour(n: Int): Task[Int] =
  for (a &lt;- timesTwo(n); b &lt;- timesTwo(n)) yield a + b

// Usage
{
  // Our ExecutionContext needed on evaluation
  import monix.execution.Scheduler.Implicits.global

  timesFour(20).foreach { result =&gt; println(s&quot;Result: $result&quot;) }
  //=&gt; Result: 80
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And just like with the &lt;code&gt;Future&lt;/code&gt; type, that “&lt;em&gt;for comprehension&lt;/em&gt;” magic
is translated by the Scala compiler to nothing more than calls to
&lt;code&gt;flatMap&lt;/code&gt; and &lt;code&gt;map&lt;/code&gt;, literally equivalent with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def timesFour(n: Int): Task[Int] =
  timesTwo(n).flatMap { a =&gt;
    timesTwo(n).map { b =&gt; a + b }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;52-parallelism&quot;&gt;5.2. Parallelism&lt;/h3&gt;

&lt;p&gt;The story for &lt;code&gt;Task&lt;/code&gt; and parallelism is better than with &lt;code&gt;Future&lt;/code&gt;, because
&lt;code&gt;Task&lt;/code&gt; allows fine-grained control when forking tasks, while trying
to execute transformations (e.g. &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;flatMap&lt;/code&gt;) on the current thread
and call-stack, thus preserving cache locality and avoiding context
switches for what is in essence sequential work.&lt;/p&gt;

&lt;p&gt;But first, translating the sample using &lt;code&gt;Future&lt;/code&gt; does not work:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// BAD SAMPLE (for achieving parallelism, as this will be sequential)
def timesFour(n: Int): Task[Int] = {
  // Will not trigger execution b/c Task is lazy
  val fa = timesTwo(n)
  val fb = timesTwo(n)
  // Evaluation will be sequential b/c of laziness
  for (a &lt;- fa; b &lt;- fb) yield a + b
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In order to achieve parallelism &lt;code&gt;Task&lt;/code&gt; requires you to be explicit about it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def timesFour(n: Int): Task[Int] =
  Task.mapBoth(timesTwo(n), timesTwo(n))(_ + _)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oh, does &lt;code&gt;mapBoth&lt;/code&gt; seem familiar? If those two tasks fork threads on
execution, then they will get executed in parallel as &lt;code&gt;mapBoth&lt;/code&gt; starts
them both at the same time.&lt;/p&gt;

&lt;h3 id=&quot;53-recursivity&quot;&gt;5.3. Recursivity&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Task&lt;/code&gt; is recursive and stack-safe (in &lt;code&gt;flatMap&lt;/code&gt;) and incredibly efficient, being powered
by an internal trampoline. You can checkout this cool paper by Rúnar Bjarnason on
&lt;a href=&quot;http://blog.higher-order.com/assets/trampolines.pdf&quot;&gt;Stackless Scala with Free Monads&lt;/a&gt;
for getting a hint on how &lt;code&gt;Task&lt;/code&gt; got implemented so efficiently.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;sequence&lt;/code&gt; implementation looks similar with the one for &lt;code&gt;Future&lt;/code&gt;
in &lt;a href=&quot;#43-recursivity&quot;&gt;section 4.3&lt;/a&gt;, except that you can see the laziness in
the signature of &lt;code&gt;sequence&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def sequence[A](list: List[Task[A]]): Task[List[A]] = {
  val seed = Task.now(List.empty[A])
  list.foldLeft(seed)((acc,f) =&gt; for (l &lt;- acc; a &lt;- f) yield a :: l)
    .map(_.reverse)
}

// Invocation
{
  // Our ExecutionContext needed on evaluation
  import monix.execution.Scheduler.Implicits.global

  sequence(List(timesTwo(10), timesTwo(20), timesTwo(30))).foreach(println)
  // =&gt; List(20, 40, 60)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;6-functional-programming-and-type-classes&quot;&gt;6. Functional Programming and Type-classes&lt;/h2&gt;

&lt;p&gt;When working with well grown functions such as &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;flatMap&lt;/code&gt; and &lt;code&gt;mapBoth&lt;/code&gt;,
we no longer care that underlying it all is an “&lt;code&gt;(A =&gt; Unit) =&gt; Unit&lt;/code&gt;”, because these
functions are, assuming lawfulness, pure and referentially transparent.
This means we can reason about them and their result, divorced from their
surrounding context.&lt;/p&gt;

&lt;p&gt;This is the great achievement of Haskell’s &lt;code&gt;IO&lt;/code&gt;. Haskell does not “fake” side-effects,
as functions returning &lt;code&gt;IO&lt;/code&gt; values are literally pure, the side-effects being
pushed at the edges of the program where they belong. And we can say the same
thing about &lt;code&gt;Task&lt;/code&gt;. Well, for &lt;code&gt;Future&lt;/code&gt; it’s more complicated given its eager
nature, but working with &lt;code&gt;Future&lt;/code&gt; is not bad either.&lt;/p&gt;

&lt;p&gt;And can we build interfaces that abstract over such types as &lt;code&gt;Task&lt;/code&gt;, &lt;code&gt;Future&lt;/code&gt;,
&lt;code&gt;Coeval&lt;/code&gt;, &lt;code&gt;Eval&lt;/code&gt;, &lt;code&gt;IO&lt;/code&gt;, &lt;code&gt;Id&lt;/code&gt;, &lt;code&gt;Observable&lt;/code&gt; and others?&lt;/p&gt;

&lt;p&gt;Yes we can, we’ve already seen that &lt;code&gt;flatMap&lt;/code&gt; describes sequencing, while
&lt;code&gt;mapBoth&lt;/code&gt; describes parallelism. But we can’t describe them with classic
OOP interfaces, for one because due to the covariance and contravariance rules of
&lt;code&gt;Function1&lt;/code&gt; parameters we’d lose type info in &lt;code&gt;flatMap&lt;/code&gt; (unless you use
F-bounded polymorphic types, which are more suitable for implementation reuse and
aren’t available in other OOP languages),
but also because we need to describe a data constructor that can’t be a
method (i.e. OOP subtyping applies to instances and not whole classes).&lt;/p&gt;

&lt;p&gt;Fortunately Scala is one of the very few languages capable of higher kinded
types and with the ability to encode
&lt;a href=&quot;https://en.wikipedia.org/wiki/Type_class&quot;&gt;type-classes&lt;/a&gt;, which means we’ve got
everything needed to port concepts from Haskell 😄&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;Author’s Rant:&lt;/strong&gt; The dreaded &lt;code&gt;Monad&lt;/code&gt;, &lt;code&gt;Applicative&lt;/code&gt; and &lt;code&gt;Functor&lt;/code&gt; words
strike fear in the hearts of the unfaithful, having given rise to the belief
that they are  “academic” notions disconnected from real-world concerns,
with book authors going to great length to avoid using these words, which
includes Scala’s API documentation and official tutorials.
&lt;br&gt;&lt;br&gt;
But this is a disservice to both the Scala language and its users.
In other languages they are only design patterns that are hard to explain
primarily because they can’t be expressed as types. You can count the
languages having this expressive capability with one hand. And users suffer
because in case of trouble they don’t know how to search for existing
literature on the subject, having been deprived of learning
the correct jargon.
&lt;br&gt;&lt;br&gt;
I also feel this is a flavor of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Anti-intellectualism&quot;&gt;anti-intellectualism&lt;/a&gt;,
as usual born out of fear of the unknown. You can see it coming from people
that really know what they are doing, as none of us is immune. For example Java’s
&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html&quot;&gt;Optional&lt;/a&gt;
type violates the functor laws (e.g. &lt;code&gt;opt.map(f).map(g) != opt.map(f andThen g)&lt;/code&gt;),
in Swift &lt;code&gt;5 == Some(5)&lt;/code&gt; which is preposterous and good luck explaining to
people that &lt;code&gt;Some(null)&lt;/code&gt; actually makes sense for as long as &lt;code&gt;null&lt;/code&gt; is a valid
value of &lt;code&gt;AnyRef&lt;/code&gt; and because otherwise you can’t define &lt;code&gt;Applicative[Option]&lt;/code&gt;.
&lt;/p&gt;

&lt;h3 id=&quot;61-monad-sequencing-and-recursivity&quot;&gt;6.1. Monad (Sequencing and Recursivity)&lt;/h3&gt;

&lt;p&gt;This article is not about explaining Monads. There are other great articles
for that. But if you’re looking to build an intuition, here’s another one: in the
context of data types such as &lt;code&gt;Future&lt;/code&gt; or &lt;code&gt;Task&lt;/code&gt;, Monads describe sequencing
of operations and is the &lt;em&gt;only reliable&lt;/em&gt; way to ensure ordering.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“&lt;em&gt;Observation: programmers doing concurrency with imperative languages
are tripped by the unchallenged belief that “;” defines sequencing.&lt;/em&gt;”
– &lt;a href=&quot;https://x.com/shipilev/status/822004316605206529&quot;&gt;Aleksey Shipilëv&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A simple encoding of the &lt;code&gt;Monad&lt;/code&gt; type in Scala:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// We shouldn&apos;t need to do this :-(
import scala.language.higherKinds

trait Monad[F[_]] {
  /** Constructor (said to lift a value `A` in the `F[A]`
    * monadic context). Also part of `Applicative`, see below.
    */
  def pure[A](a: A): F[A]

  /** FTW */
  def flatMap[A,B](fa: F[A])(f: A =&gt; F[B]): F[B]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And providing an implementation for &lt;code&gt;Future&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import scala.concurrent._

// Supplying an instance for Future isn&apos;t clean, ExecutionContext needed
class FutureMonad(implicit ec: ExecutionContext)
  extends Monad[Future] {

  def pure[A](a: A): Future[A] =
    Future.successful(a)

  def flatMap[A,B](fa: Future[A])(f: A =&gt; Future[B]): Future[B] =
    fa.flatMap(f)
}

object FutureMonad {
  implicit def instance(implicit ec: ExecutionContext): FutureMonad =
    new FutureMonad
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is really powerful stuff. We can now describe a generic function
that works with &lt;code&gt;Task&lt;/code&gt;, &lt;code&gt;Future&lt;/code&gt;, &lt;code&gt;IO&lt;/code&gt;, whatever, although it would be
great if the &lt;code&gt;flatMap&lt;/code&gt; operation is stack-safe:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;/** Calculates the N-th number in a Fibonacci series. */
def fib[F[_]](n: Int)(implicit F: Monad[F]): F[BigInt] = {
  def loop(n: Int, a: BigInt, b: BigInt): F[BigInt] =
    F.flatMap(F.pure(n)) { n =&gt;
      if (n &lt;= 1) F.pure(b)
      else loop(n - 1, b, a + b)
    }

  loop(n, BigInt(0), BigInt(1))
}

// Usage:
{
  // Needed in scope
  import FutureMonad.instance
  import scala.concurrent.ExecutionContext.Implicits.global

  // Invocation
  fib[Future](40).foreach(r =&gt; println(s&quot;Result: $r&quot;))
  //=&gt; Result: 102334155
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;PRO-TIP:&lt;/strong&gt; this is just a toy example. For getting serious,
see &lt;a href=&quot;http://typelevel.org/cats/&quot;&gt;Typelevel’s Cats&lt;/a&gt;
&lt;/p&gt;

&lt;h3 id=&quot;62-applicative-parallelism&quot;&gt;6.2. Applicative (Parallelism)&lt;/h3&gt;

&lt;p&gt;Monads define sequencing of operations, but sometimes we want to compose
the results of computations that are independent of each other,
that can be evaluated at the same time, possibly in parallel.
There’s also a case to be made that applicatives are more composable
than monads 😏&lt;/p&gt;

&lt;p&gt;Let’s expand our mini Typeclassopedia to put on your wall:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Functor[F[_]] {
  /** I hope we are all familiar with this one. */
  def map[A,B](fa: F[A])(f: A =&gt; B): F[B]
}

trait Applicative[F[_]] extends Functor[F] {
  /** Constructor (lifts a value `A` in the `F[A]` applicative context). */
  def pure[A](a: A): F[A]

  /** Maps over two references at the same time.
    *
    * In other implementations the applicative operation is `ap`,
    * but `map2` is easier to understand.
    */
  def map2[A,B,R](fa: F[A], fb: F[B])(f: (A,B) =&gt; R): F[R]
}

trait Monad[F[_]] extends Applicative[F] {
  def flatMap[A,B](fa: F[A])(f: A =&gt; F[B]): F[B]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And to expand our &lt;code&gt;Future&lt;/code&gt; implementation:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Supplying an instance for Future isn&apos;t clean, ExecutionContext needed
class FutureMonad(implicit ec: ExecutionContext)
  extends Monad[Future] {

  def pure[A](a: A): Future[A] =
    Future.successful(a)

  def flatMap[A,B](fa: Future[A])(f: A =&gt; Future[B]): Future[B] =
    fa.flatMap(f)

  def map2[A,B,R](fa: Future[A], fb: Future[B])(f: (A,B) =&gt; R): Future[R] =
    // For Future there&apos;s no point in supplying an implementation that&apos;s
    // not based on flatMap, but that&apos;s not the case for Task ;-)
    for (a &lt;- fa; b &lt;- fb) yield f(a,b)
}

object FutureMonad {
  implicit def instance(implicit ec: ExecutionContext): FutureMonad =
    new FutureMonad
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So we can now define generic functions based on &lt;code&gt;Applicative&lt;/code&gt; which is going
to work for &lt;code&gt;Future&lt;/code&gt;, &lt;code&gt;Task&lt;/code&gt;, etc:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def sequence[F[_], A](list: List[F[A]])
  (implicit F: Applicative[F]): F[List[A]] = {

  val seed = F.pure(List.empty[A])
  val r = list.foldLeft(seed)((acc,e) =&gt; F.map2(acc,e)((l,a) =&gt; a :: l))
  F.map(r)(_.reverse)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
&lt;strong&gt;PRO-TIP:&lt;/strong&gt; worth repeating, this is just a toy example. For getting serious,
see &lt;a href=&quot;http://typelevel.org/cats/&quot;&gt;Typelevel’s Cats&lt;/a&gt;
&lt;/p&gt;

&lt;h3 id=&quot;63-can-we-define-a-type-class-for-async-evaluation&quot;&gt;6.3. Can We Define a Type-class for Async Evaluation?&lt;/h3&gt;

&lt;p&gt;Missing from above is a way to actually trigger an evaluation and
get a value out. Thinking of Scala’s &lt;code&gt;Future&lt;/code&gt;, we want a way to abstract
over &lt;code&gt;onComplete&lt;/code&gt;. Thinking of Monix’s &lt;code&gt;Task&lt;/code&gt; we want to abstract over &lt;code&gt;runAsync&lt;/code&gt;.
Thinking of Haskell’s and Scalaz’s &lt;code&gt;IO&lt;/code&gt;, we want a way to abstract over
&lt;code&gt;unsafePerformIO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/functional-streams-for-scala/fs2/&quot;&gt;FS2&lt;/a&gt; library has
defined a type-class called &lt;a href=&quot;https://github.com/functional-streams-for-scala/fs2/blob/series/1.0/core/shared/src/main/scala/fs2/util/Effect.scala&quot;&gt;Effect&lt;/a&gt; that goes like this (simplified):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Effect[F[_]] extends Monad[F] {
  def unsafeRunAsync[A](fa: F[A])(cb: Try[A] =&gt; Unit): Unit
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This looks like our initial &lt;code&gt;Async&lt;/code&gt; type, very much similar with
&lt;code&gt;Future.onComplete&lt;/code&gt;, with &lt;code&gt;Task.runAsync&lt;/code&gt; and could be applied to
&lt;code&gt;IO.unsafePerformIO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, this is not a real type-class because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;it is lawless and while that’s not enough to disqualify it (after all,
useful lawless type-classes like &lt;code&gt;Show&lt;/code&gt; exist), the bigger problem is …&lt;/li&gt;
  &lt;li&gt;as shown in &lt;a href=&quot;#33-recursivity-wrath-of-stackoverflow&quot;&gt;section 3.3&lt;/a&gt;, in order to avoid the Wrath of &lt;code&gt;StackOverflowError&lt;/code&gt;,
we need some sort of execution context or thread-pool that can execute tasks
asynchronously without blowing up the stack&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And such an execution context is different from implementation to implementation.
Java will use &lt;code&gt;Executor&lt;/code&gt;, the Scala &lt;code&gt;Future&lt;/code&gt; uses &lt;code&gt;ExecutionContext&lt;/code&gt;, Monix
uses &lt;code&gt;Scheduler&lt;/code&gt; which is an enhanced &lt;code&gt;ExecutionContext&lt;/code&gt;, FS2 and Scalaz
use &lt;code&gt;Strategy&lt;/code&gt; which wraps an &lt;code&gt;Executor&lt;/code&gt; for forking threads and don’t inject
a context when their &lt;code&gt;unsafePerformIO&lt;/code&gt; or &lt;code&gt;runAsync&lt;/code&gt; gets called
(which is why many of the Scalaz combinators are in fact unsafe), etc.&lt;/p&gt;

&lt;p&gt;We could apply the same strategy as with &lt;code&gt;Future&lt;/code&gt;, to build the type-class
instance by taking a &lt;code&gt;implicit whatever: Context&lt;/code&gt; from the scope. But that’s
a little awkward and inefficient. It’s also telling that we can’t define
&lt;code&gt;flatMap&lt;/code&gt; only in terms of &lt;code&gt;Effect.unsafePerformIO&lt;/code&gt;, not without that
execution context. And if we can’t do it, then the type should probably
not inherit from &lt;code&gt;Monad&lt;/code&gt; because it’s not necessarily a &lt;code&gt;Monad&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So I’m personally not sure - if you have suggestions for what should be
introduced in &lt;a href=&quot;http://typelevel.org/cats&quot;&gt;Cats&lt;/a&gt;, I’d love to hear them.&lt;/p&gt;

&lt;p&gt;I do hope you enjoyed this thought experiment, designing things is fun 😎&lt;/p&gt;

&lt;h2 id=&quot;7-picking-the-right-tool&quot;&gt;7. Picking the Right Tool&lt;/h2&gt;

&lt;p&gt;Some abstractions are more general purpose than others and personally
I think the mantra of “&lt;em&gt;picking the right tool for the job&lt;/em&gt;” is
overused to defend poor choices.&lt;/p&gt;

&lt;p&gt;That said, there’s this wonderful presentation by Rúnar Bjarnason called
&lt;a href=&quot;https://www.youtube.com/watch?v=GqmsQeSzMdw&quot;&gt;Constraints Liberate, Liberties Constrain&lt;/a&gt;
that really drives the point home with concurrency abstractions at least.&lt;/p&gt;

&lt;p&gt;As said, there is no silver bullet that can be generally applied for dealing with concurrency.
The more high-level the abstraction, the less scope it has in solving issues. But the less scope
and power it has, the simpler and more composable the model is.
For example many developers in the Scala community are overusing Akka Actors -
which is a great library, but not when misapplied. Like don’t use an
Akka &lt;code&gt;Actor&lt;/code&gt; when a &lt;code&gt;Future&lt;/code&gt; or a &lt;code&gt;Task&lt;/code&gt; would do. Ditto for other abstractions,
like the &lt;code&gt;Observable&lt;/code&gt; pattern in Monix and ReactiveX.&lt;/p&gt;

&lt;p&gt;Also learn by heart these 2 very simple rules:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;avoid dealing with callbacks, threads and locks, because they are very error
prone and not composable at all&lt;/li&gt;
  &lt;li&gt;avoid concurrency like the plague it is&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And let me tell you, concurrency experts are first of all experts in
avoiding concurrency 💀&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2017/01/30/asynchronous-programming-scala/?pk_campaign=rss&quot;&gt;Asynchronous Programming and Scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 30 Jan 2017 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2017/01/30/asynchronous-programming-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2017/01/30/asynchronous-programming-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Asynchrony</category>
  <category>Best Of</category>
  <category>Concurrency</category>
  <category>Multithreading</category>
  <category>Scala</category>
  </item>


<item>
  <title>Fixing scala.collection.Iterator</title>
  <description>The venerable Iterator interface we all love and hate could use some improvements. This is a follow-up to my previous article, in which I talked about getting rid of Traversable because the Iterable and Iterator duo is enough for Scala’s standard library.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2017/01/16/iterator/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;The venerable &lt;code&gt;Iterator&lt;/code&gt; interface we all love and hate could use some improvements. This is a follow-up to my previous article, in which I talked about &lt;a href=&quot;https://alexn.org/blog/2017/01/13/traversable/&quot;&gt;getting rid of Traversable&lt;/a&gt; because the &lt;code&gt;Iterable&lt;/code&gt; and &lt;code&gt;Iterator&lt;/code&gt; duo is enough for Scala’s standard library.&lt;/p&gt;

&lt;p&gt;As a reminder, the &lt;code&gt;Iterator&lt;/code&gt; interface is something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Iterator[+A] {
  def hasNext: Boolean
  def next(): A
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’s a destructive interface that is consumed for as long as you call &lt;code&gt;next()&lt;/code&gt;,
it obviously has “identity” and you’re supposed to use it like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val cursor: Iterator[Int] = ???
var sum = 0

while (cursor.hasNext) {
  sum += cursor.next()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;problem-1-both-methods-hasnext-next-are-side-effecting&quot;&gt;Problem 1: Both methods (hasNext, next) are side-effecting&lt;/h2&gt;

&lt;p&gt;You could say that &lt;code&gt;hasNext&lt;/code&gt; is not supposed to move the internal
cursor / pointer / index and thus it shouldn’t be side-effecting, but
that’s not true, because in many cases the only way to know if there
is a next element to be served is to trigger a side-effecting read.&lt;/p&gt;

&lt;p&gt;And so the problem is that both &lt;code&gt;hasNext&lt;/code&gt; and &lt;code&gt;next()&lt;/code&gt; are side-effecting and
in my opinion the result of the wrong method is getting cached. When you work with
Functional Programming for a while, you start noticing when APIs have their
side-effects screwed ;-)&lt;/p&gt;

&lt;p&gt;We can’t really blame Scala though. This interface has been imported from
Java and kept similar probably for remaining familiar.&lt;/p&gt;

&lt;p&gt;But let me illustrate by building an iterator for reading an &lt;code&gt;InputStream&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class IteratorFromStream(in: InputStream, chunkSize: Int)
  extends Iterator[Array[Byte]] {

  private val buffer = new Array[Byte](chunkSize)
  private var chunk: Array[Byte] = _
  private var hasChunk = false

  def hasNext: Boolean = {
    if (!hasChunk) {
      val len = in.read(buffer)
      if (len &gt;= 0) {
        chunk = util.Arrays.copyOf(buffer, len)
        hasChunk = true
      } else {
        in.close()
      }
    }

    hasChunk
  }

  def next(): Array[Byte] = {
    if (hasNext) {
      val ref = chunk
      chunk = null // GC purposes
      hasChunk = false
      ref
    } else {
      throw new NoSuchElementException(&quot;InputStream is empty&quot;)
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not that particularly exciting and you can see how &lt;code&gt;next()&lt;/code&gt; has to duplicate
the work of &lt;code&gt;hasNext&lt;/code&gt; and that &lt;code&gt;hasNext&lt;/code&gt; itself is side-effecting, because
we have to read from the &lt;code&gt;InputStream&lt;/code&gt; before being able to answer that question.&lt;/p&gt;

&lt;p&gt;We can do better and we don’t have to be original about it.
Behold the alternative inspired by
&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/system.collections.ienumerator(v=vs.110).aspx&quot;&gt;IEnumerator from C#&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Iterator[+A] {
  // Side-effecting, moves the cursor
  def moveNext(): Boolean

  // Not side-effecting, can be called multiple times
  def current: A
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Usage is straightforward:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val cursor: Iterator[Int] = ???
var sum = 0

while (cursor.moveNext()) {
  sum += cursor.current
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This interface feels more natural to developers because “moving” the
cursor is the side-effect, not reading the current value.
And here’s how the above implementation changes:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class IteratorFromStream(in: InputStream, chunkSize: Int)
  extends Iterator[Array[Byte]] {

  private val buffer = new Array[Byte](chunkSize)
  private var chunk: Array[Byte] = _

  def moveNext(): Boolean = {
    val len = in.read(buffer)
    if (len &gt;= 0) {
      chunk = util.Arrays.copyOf(buffer, len)
      true
    }
    else {
      chunk = null
      in.close()
      false
    }
  }

  def current: Array[Byte] = {
    if (chunk == null) throw NoSuchElementException(&quot;current&quot;)
    chunk
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice how this &lt;em&gt;simplifies&lt;/em&gt; things on the implementation side as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; M.Odersky points out in the comments that the standard library has a
&lt;a href=&quot;http://www.scala-lang.org/api/current/scala/collection/BufferedIterator.html&quot;&gt;BufferedIterator&lt;/a&gt;
implementation that caches the current &lt;code&gt;head&lt;/code&gt; and can be used for convenience.&lt;/p&gt;

&lt;h2 id=&quot;problem-2-iterator-comes-with-operations-attached&quot;&gt;Problem 2: Iterator comes with operations attached&lt;/h2&gt;

&lt;p&gt;At the beginning I gave you a simplified &lt;code&gt;Iterator&lt;/code&gt; definition, however I lied.
The true &lt;code&gt;scala.collection.Iterator&lt;/code&gt; is closer to this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;package scala.collection

trait Iterator[+A] extends TraversableOnce[A] {
  def hasNext: Boolean
  def next(): A

  def isTraversableAgain = false
  def isEmpty: Boolean = !hasNext
  def hasDefiniteSize = isEmpty

  def map[B](f: A =&gt; B): Iterator[B] = ???
  def take(n: Int): Iterator[A] = slice(0, n)
  def drop(n: Int): Iterator[A] = ???
  def slice(from: Int, until: Int): Iterator[A] = ???
  def map[B](f: A =&gt; B): Iterator[B] = ???
  def ++[B &gt;: A](that: =&gt; GenTraversableOnce[B]): Iterator[B] = ???
  def flatMap[B](f: A =&gt; GenTraversableOnce[B]): Iterator[B] = ???
  def filter(p: A =&gt; Boolean): Iterator[A] = ???
  def corresponds[B](that: GenTraversableOnce[B])(p: (A, B) =&gt; Boolean): Boolean = ???
  def withFilter(p: A =&gt; Boolean): Iterator[A] = ???
  def filterNot(p: A =&gt; Boolean): Iterator[A] = ???
  def collect[B](pf: PartialFunction[A, B]): Iterator[B] = ???
  def scanLeft[B](z: B)(op: (B, A) =&gt; B): Iterator[B] = ???
  def scanRight[B](z: B)(op: (A, B) =&gt; B): Iterator[B] = ???
  def takeWhile(p: A =&gt; Boolean): Iterator[A] = ???
  def partition(p: A =&gt; Boolean): (Iterator[A], Iterator[A]) = ???
  def span(p: A =&gt; Boolean): (Iterator[A], Iterator[A]) = ???
  def dropWhile(p: A =&gt; Boolean): Iterator[A] = ???
  def zip[B](that: Iterator[B]): Iterator[(A, B)] = ???
  def padTo[A1 &gt;: A](len: Int, elem: A1): Iterator[A1] = ???
  def zipWithIndex: Iterator[(A, Int)] = ???
  def foreach[U](f: A =&gt; U) = ???
  def forall(p: A =&gt; Boolean): Boolean = ???
  def exists(p: A =&gt; Boolean): Boolean = ???
  def contains(elem: Any): Boolean = ???
  def find(p: A =&gt; Boolean): Option[A] = ???
  def indexWhere(p: A =&gt; Boolean): Int = ???
  def indexOf[B &gt;: A](elem: B): Int = ???
  def buffered: BufferedIterator[A] = ???
  def grouped[B &gt;: A](size: Int): GroupedIterator[B] = ???
  def copyToArray[B &gt;: A](xs: Array[B], start: Int, len: Int): Unit = ???
  def sameElements(that: Iterator[_]): Boolean = ???
  def toTraversable: Traversable[A] = ???
  def toIterator: Iterator[A] = ???
  def toStream: Stream[A] = ???
  // ....
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, at this point you should be thinking that this violates the principles of
OOP design. When &lt;code&gt;Iterator&lt;/code&gt; comes with operations like &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;filter&lt;/code&gt;,
that are polymorphic and can be overridden, it is no longer just a minimal
protocol for “&lt;em&gt;iterating over things&lt;/em&gt;”, but a &lt;em&gt;big, fat interface&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You see, there isn’t a single possible implementation for &lt;code&gt;map&lt;/code&gt; or for &lt;code&gt;take&lt;/code&gt;
and by providing such operations with a default implementation the
&lt;code&gt;Iterator&lt;/code&gt; is imposing to users how those operations should behave.
Or more specifically:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;these operations have lazy behavior, until overridden in subclasses&lt;/li&gt;
  &lt;li&gt;assume that the protocol is set in stone&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But &lt;code&gt;Iterator&lt;/code&gt; is a fine example of an OOP interface because you can add
restrictions to it. Lo and behold how OOP inheritance is supposed to work:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait CloseableIterable[+A] extends Iterable[A] {
  def iterator: CloseableIterator[A]
}

trait CloseableIterator[+A] extends Iterator[A] with AutoCloseable {
  /** Closes this resource, relinquishing any underlying resources. */
  def close(): Unit
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;BAM, we just invalidated more than 80 operations provided by Scala’s &lt;code&gt;Iterator&lt;/code&gt;
and &lt;code&gt;Iterable&lt;/code&gt;. Are you going to override them all?&lt;/p&gt;

&lt;p&gt;If you say yes, then you don’t know what you’re getting yourself into,
plus what are you going to do when Scala 2.13 (or whatever the next version is)
comes with new operators that need to be overridden? Are you going to remember
to do it? It’s a hard problem.&lt;/p&gt;

&lt;p&gt;I don’t mind having implementations of &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;filter&lt;/code&gt; for &lt;code&gt;Iterator&lt;/code&gt;, but
Scala lacks a minimal interface that provides just the raw protocol.
There is value in simplicity. Notice Java’s &lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html&quot;&gt;Iterator&lt;/a&gt;,
notice C#’s &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/system.collections.ienumerator(v=vs.110).aspx&quot;&gt;IEnumerator&lt;/a&gt;, notice how they don’t come with operators attached.
Instead, for C# at least, you can import
&lt;a href=&quot;https://github.com/Reactive-Extensions/Rx.NET&quot;&gt;Ix.NET&lt;/a&gt; in your project,
which gives you a bunch of extension methods you can work with, no strings attached.
Scala could also use &lt;a href=&quot;http://typelevel.org/cats/&quot;&gt;type-classes&lt;/a&gt; which are
much better than extension methods. But instead what currently happens in
Scala’s collection library can be seen as &lt;em&gt;inheritance hell&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Not everything needs &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;flatMap&lt;/code&gt; on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; there is now an issue for discussing this at
&lt;a href=&quot;https://github.com/scala/collection-strawman/issues/17&quot;&gt;collection-strawman/issues/#17&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;non-problem-early-termination--resource-handling&quot;&gt;Non-problem: early termination &amp; resource handling&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Iterator&lt;/code&gt; interface alone is not enough to expose streams linked
to file handles, network sockets or other resources that need to be disposed
when terminated early.&lt;/p&gt;

&lt;p&gt;So rookies (also because of problem 2 above) can end up with unconsumed iterators,
creating possible connection leaks, because it’s easy:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;iterator.take(100)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However I don’t view this as being a problem because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;we don’t need to do resource handling everywhere&lt;/li&gt;
  &lt;li&gt;as demonstrated in the sample with &lt;code&gt;CloseableIterator&lt;/code&gt; above, you can build
proper resource handling on top of &lt;code&gt;Iterator&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;doing I/O by means of an &lt;code&gt;Iterator&lt;/code&gt; is often a bad idea, given
that &lt;code&gt;Iterator&lt;/code&gt; is not capable of asynchronous boundaries, with
I/O operations often being asynchronous&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Having a &lt;code&gt;CloseableIterator&lt;/code&gt; in the standard library wouldn’t be bad though,
however given the very complex inheritance hierarchy and the traversable
grandparents, I’m afraid to wish for it.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2017/01/16/iterator/?pk_campaign=rss&quot;&gt;Fixing scala.collection.Iterator&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 16 Jan 2017 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2017/01/16/iterator/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2017/01/16/iterator/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  </item>


<item>
  <title>Why Scala&#39;s Traversable Is Bad Design</title>
  <description>Traversable was a design mistake, is redundant and we should remove it.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2017/01/13/traversable/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;Given there’s a
&lt;a href=&quot;https://contributors.scala-lang.org/t/ongoing-work-on-standard-collections-redesign/293&quot;&gt;Scala collection redesign&lt;/a&gt;
discussion going on, it’s a good time to talk about one of my personal pet peeves:
the existence of &lt;a href=&quot;http://www.scala-lang.org/api/2.12.1/scala/collection/Traversable.html&quot;&gt;Traversable&lt;/a&gt;
in the standard library, along with its variants like &lt;code&gt;TraversableLike&lt;/code&gt; and &lt;code&gt;TraversableOnce&lt;/code&gt;.
Apparently this interface is missing in the new design and that’s awesome.&lt;/p&gt;

&lt;p&gt;It’s easy to make API mistakes, we all do it and it’s important to
learn from past mistakes, this document serving as a lesson for why
&lt;code&gt;Traversable&lt;/code&gt; is a bad idea.&lt;/p&gt;

&lt;p&gt;Claims:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;code&gt;Traversable&lt;/code&gt; has implicit behavior assumptions that are not visible
in its exposed signature, the API being error prone&lt;/li&gt;
  &lt;li&gt;Iterating over a &lt;code&gt;Traversable&lt;/code&gt; has worse performance than &lt;code&gt;Iterator&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;There exists no &lt;code&gt;Traversable&lt;/code&gt; data type that doesn’t admit an efficient
&lt;code&gt;Iterator&lt;/code&gt; implementation, thus &lt;code&gt;Traversable&lt;/code&gt; being completely redundant&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As a reminder and you can also
&lt;a href=&quot;http://docs.scala-lang.org/overviews/collections/trait-traversable.html&quot;&gt;read the docs&lt;/a&gt;,
the &lt;code&gt;Traversable&lt;/code&gt; is a trait like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Traversable[+A] {
  def foreach(f: A =&gt; Unit): Unit
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The standard library also has the venerable &lt;code&gt;Iterable&lt;/code&gt; / &lt;code&gt;Iterator&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Iterable[+A] {
  def iterator(): Iterator[A]
}

trait Iterator[+A] {
  def hasNext: Boolean
  def next(): A
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Can you spot the similarities?&lt;/p&gt;

&lt;p&gt;You should, because these 2 interfaces are supposed to be
&lt;a href=&quot;https://en.wikipedia.org/wiki/Duality_(mathematics)&quot;&gt;duals&lt;/a&gt;.
So if you think of &lt;code&gt;Traversable&lt;/code&gt; as being defined by that
&lt;code&gt;foreach&lt;/code&gt; function, then &lt;code&gt;Iterable&lt;/code&gt; is that function with
its arrows reversed:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Traversable[A] = (A =&gt; ()) =&gt; ()

type Iterable[A] = () =&gt; (() =&gt; A)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this is interesting. For one &lt;code&gt;Traversable&lt;/code&gt; is a sort of
inversion of control technique, so instead of having a cursor
that you have to manually advance, you now register a callback to
a function and that callback gets called for you on each element.
This actually frees us from certain &lt;code&gt;Iterator&lt;/code&gt; constraints.
For example with a push-based API we should no longer care when
those function calls happen.&lt;/p&gt;

&lt;p&gt;But you should already spot problems with the above
definition. Our &lt;code&gt;Iterable&lt;/code&gt; function signature isn’t complete,
this one is:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Iterable[+A] = () =&gt; Iterator[A]

type Iterator[+A] = () =&gt; Try[Option[A]]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or in other words any &lt;code&gt;Iterator&lt;/code&gt; can:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;give us the next element,&lt;/li&gt;
  &lt;li&gt;or signal completion or failure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means that the actual dual of &lt;code&gt;Iterator&lt;/code&gt; is:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Observer[A] = Try[Option[A]] =&gt; Unit
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or for those OOP-oriented among us, I give you the &lt;code&gt;Observer&lt;/code&gt;
as championed by &lt;a href=&quot;https://github.com/Reactive-Extensions/Rx.NET&quot;&gt;Rx.NET&lt;/a&gt;,
as the true dual of &lt;code&gt;Iterator&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Observer[-A] {
  def onNext(a: A): Unit
  def onComplete(): Unit
  def onError(ex: Throwable): Unit
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Hello &lt;strong&gt;&lt;a href=&quot;https://monix.io/&quot;&gt;Monix&lt;/a&gt;&lt;/strong&gt; :-))&lt;/p&gt;

&lt;p&gt;This matters because &lt;code&gt;Traversable&lt;/code&gt; has &lt;strong&gt;no way to signal completion or failure&lt;/strong&gt;,
unless you get a guarantee that all the processing happens synchronously, everything
being over after the invocation of its &lt;code&gt;foreach&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As an abstraction, this makes it useless when compared with &lt;code&gt;Iterable&lt;/code&gt;
and &lt;code&gt;Iterator&lt;/code&gt;. If you introduce the synchronous execution constraint,
there exists no data type that can implement &lt;code&gt;Traversable&lt;/code&gt; and that doesn’t
admit an &lt;code&gt;Iterator&lt;/code&gt; implementation. None.&lt;/p&gt;

&lt;p&gt;Even more problematic in my opinion is that this restriction isn’t
visible in its API, unless your eyes are trained for it. With
&lt;code&gt;Iterator.next()&lt;/code&gt; whether you want it or not, you have to process things
synchronously, because &lt;em&gt;the signature says so&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Also problematic is &lt;code&gt;TraversableOnce&lt;/code&gt;, which is supposed to be a
traversable that can only be traversed once, like its name says.
We’ve got this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait TraversableOnce[+A] {
  def foreach(f: A =&gt; Unit): Unit
}

trait Traversable[+A] extends TraversableOnce[A]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Besides the name and the inheritance relationship, there is no difference.
This is another problem. Even if the API is effectful/impure, we should still
be able to use types serving as documentation. Contrast with the
&lt;code&gt;Iterable&lt;/code&gt; / &lt;code&gt;Iterator&lt;/code&gt; separation. Iterating over an &lt;code&gt;Iterator&lt;/code&gt; is known to
consume it and you can see this in its API. And the generator/factory part is in
&lt;code&gt;Iterable&lt;/code&gt;, which is good separation of concerns.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Traversable&lt;/code&gt; also has worse performance than &lt;code&gt;Iterator&lt;/code&gt;.
The ugly truth is that the JVM hasn’t been doing a good job at
inlining that function reference you pass to &lt;code&gt;foreach&lt;/code&gt;. This is called
&lt;a href=&quot;http://www.azulsystems.com/blog/cliff/2011-04-04-fixing-the-inlining-problem&quot;&gt;the inlining problem&lt;/a&gt;,
which happens for megamorphic function calls in hot inner loops.&lt;/p&gt;

&lt;p&gt;So there you have it and I hope that along with the redesign we’ll get rid
of &lt;code&gt;Traversable&lt;/code&gt;.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
My opinions have been highly influenced by the work of Erik Meijer,
if you want to learn more checkout this presentation:

&lt;a href=&quot;https://vimeo.com/98922027&quot;&gt;Contravariance is the Dual of Covariance Implies Iterable is the Dual of Observable&lt;/a&gt;.
&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2017/01/13/traversable/?pk_campaign=rss&quot;&gt;Why Scala&apos;s Traversable Is Bad Design&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 13 Jan 2017 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2017/01/13/traversable/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2017/01/13/traversable/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Scala</category>
  </item>


<item>
  <title>Add to NewsBlur Bookmarklet</title>
  <description>An Add to NewsBlur bookmarklet that you can copy-paste for iPhone/iPad/Android usage</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2016/11/11/newsblur-bookmarklet/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/newsblur.png?202603060940&quot; alt=&quot;&quot; width=&quot;512&quot; height=&quot;512&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;I’m using &lt;a href=&quot;https://www.newsblur.com/&quot;&gt;NewsBlur.com&lt;/a&gt; for consuming RSS feeds. It’s a pretty cool service, however adding a new RSS feed from iOS proves to be a challenge and the “goodies” section provides no way for easily adding a bookmarklet for adding a feed.&lt;/p&gt;

&lt;p&gt;The iPad itself makes it difficult to add bookmarklets, so here’s a
tutorial:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Go to &lt;a href=&quot;https://newsblur.com&quot;&gt;NewsBlur.com&lt;/a&gt; and add it as a bookmark
(click on the box with the arrow in it next to the Safari address bar)&lt;/li&gt;
  &lt;li&gt;We need to edit the new bookmark: tap the address bar in Safari
and you should see all bookmarks, press and hold on the new
“NewsBlur.com” bookmark that you created and then tap “&lt;em&gt;Edit&lt;/em&gt;”&lt;/li&gt;
  &lt;li&gt;Change the title to something like: “&lt;em&gt;Add to NewsBlur&lt;/em&gt;”&lt;/li&gt;
  &lt;li&gt;Copy/paste the following text for the URL:&lt;/li&gt;
&lt;/ol&gt;

&lt;textarea readonly style=&quot;width:100%;height:100px;max-width:100%;background-color:#f0f0f0;&quot;&gt;javascript:(function%20()%20%7Bvar%20l%3Ddocument.location%2B%27%27%3Bif%20(l.match(%2F%5E(%3F%3Ahttps%3F%3A%5B%2F%5D%7B2%7D(%3F%3Awww.)%3F)%3Fnewsblur.com%2Fi))%20alert(%22Cannot%20add%20NewsBlur.com%20itself!%22)%3B%20else%20window.location%20%3D%20%27https%3A%2F%2Fwww.newsblur.com%2F%3Furl%3D%27%2BencodeURIComponent(l)%3B%7D)()%3Bvoid(0)&lt;/textarea&gt;

&lt;p&gt;For the desktop you can also drag this link:&lt;/p&gt;

&lt;p&gt;&lt;a style=&quot;display:block;width:200px;padding:10px;background-color:#436592;color:#fff;text-decoration:none;font-weight:bold;&quot; href=&quot;javascript:(function%20()%20%7Bvar%20l%3Ddocument.location%2B%27%27%3Bif%20(l.match(%2F%5E(%3F%3Ahttps%3F%3A%5B%2F%5D%7B2%7D(%3F%3Awww.)%3F)%3Fnewsblur.com%2Fi))%20alert(%22Cannot%20add%20NewsBlur.com%20itself!%22)%3B%20else%20window.location%20%3D%20%27https%3A%2F%2Fwww.newsblur.com%2F%3Furl%3D%27%2BencodeURIComponent(l)%3B%7D)()%3Bvoid(0)&quot;&gt;
  Add to NewsBlur&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the unencoded Javascript for your inspection:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;(function () {
  var l = document.location+&apos;&apos;;
  if (l.match(/^(?:https?:[/]{2}(?:www.)?)?newsblur.com/i))
    alert(&quot;Cannot add NewsBlur.com itself!&quot;);
  else
    window.location = &apos;https://www.newsblur.com/?url=&apos; + encodeURIComponent(l);
})();void(0)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2016/11/11/newsblur-bookmarklet/?pk_campaign=rss&quot;&gt;Add to NewsBlur Bookmarklet&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 11 Nov 2016 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2016/11/11/newsblur-bookmarklet/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2016/11/11/newsblur-bookmarklet/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Web</category>
  </item>


<item>
  <title>Monix Task vs Scalaz vs Future, The Benchmark</title>
  <description>The Task in Monix has really good performance. See the benchmark.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2016/08/25/monix-task-performance/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/monix-1024.png?202603060940&quot; alt=&quot;&quot; width=&quot;1024&quot; height=&quot;1024&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;The Monix &lt;a href=&quot;https://monix.io/docs/2x/eval/task.html&quot;&gt;Task&lt;/a&gt; was heavily inspired by &lt;code&gt;scalaz.concurrent.Task&lt;/code&gt; and by &lt;code&gt;scala.concurrent.Future&lt;/code&gt;. That’s not a secret and I’ll be forever grateful to their authors. I’ve ran a benchmark and I’m glad to report that the Monix &lt;a href=&quot;https://monix.io/docs/2x/eval/task.html&quot;&gt;Task&lt;/a&gt; beats in performance both.&lt;/p&gt;

&lt;p&gt;Such results are actually unexpected, because the Monix &lt;code&gt;Task&lt;/code&gt; has to
do tricks in order to be “&lt;em&gt;cancelable&lt;/em&gt;”, a trait that allows it to
close opened resources when race conditions happen, which really means
extra footwork. But no, right now, it beats both in performance and by
quite the margin.&lt;/p&gt;

&lt;p&gt;Details:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Benchmark used is
&lt;a href=&quot;https://github.com/monixio/monix/blob/v2.0-RC13/benchmarks/src/main/scala/monix/TaskGatherBenchmark.scala&quot;&gt;TaskGatherBenchmark&lt;/a&gt;
in the repository&lt;/li&gt;
  &lt;li&gt;Monix version: &lt;code&gt;2.0-RC13&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;Scalaz version: &lt;code&gt;7.2.4&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;Scala version: &lt;code&gt;2.11.8&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;Java version: &lt;code&gt;1.8.0_60&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;OS: OS X El Captain, version &lt;code&gt;10.11.6&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;sequence&quot;&gt;Sequence&lt;/h3&gt;

&lt;p&gt;The purpose of this test is the performance of &lt;code&gt;flatMap&lt;/code&gt;, or in other
words the performance of the run-loop, on both normal/synchronous
tasks and tasks that are forked in separate (logical) threads. So in
other words:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;Task.sequence(tasks)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which is translated more or less into this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;tasks.foldLeft(init)((acc,et) =&gt; acc.flatMap(b =&gt; et.map(e =&gt; b += e)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So for synchronous tasks (that evaluate immediately), and note here
that Scala’s &lt;code&gt;Future&lt;/code&gt; is not applicable since &lt;code&gt;Future&lt;/code&gt; is not
trampolined:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Operation&lt;/th&gt;
      &lt;th&gt;Score&lt;/th&gt;
      &lt;th&gt;Error&lt;/th&gt;
      &lt;th&gt;Units&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Monix&lt;/td&gt;
      &lt;td&gt;Sync&lt;/td&gt;
      &lt;td&gt;Sequence&lt;/td&gt;
      &lt;td&gt;6716.906&lt;/td&gt;
      &lt;td&gt;157.947&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scalaz&lt;/td&gt;
      &lt;td&gt;Sync&lt;/td&gt;
      &lt;td&gt;Sequence&lt;/td&gt;
      &lt;td&gt;3518.888&lt;/td&gt;
      &lt;td&gt;167.148&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;And for tasks that fork threads on execution:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Operation&lt;/th&gt;
      &lt;th&gt;Score&lt;/th&gt;
      &lt;th&gt;Error&lt;/th&gt;
      &lt;th&gt;Units&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Monix&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Sequence&lt;/td&gt;
      &lt;td&gt;2044.624&lt;/td&gt;
      &lt;td&gt;24.852&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scalaz&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Sequence&lt;/td&gt;
      &lt;td&gt;1090.355&lt;/td&gt;
      &lt;td&gt;15.851&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;S.Future&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Sequence&lt;/td&gt;
      &lt;td&gt;1753.614&lt;/td&gt;
      &lt;td&gt;20.871&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;As you can see, the Monix &lt;code&gt;Task&lt;/code&gt; has twice the throughput of Scalaz
and fares quite better compared with Scala’s standard &lt;code&gt;Future&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;gather&quot;&gt;Gather&lt;/h3&gt;

&lt;p&gt;The gather operation would be:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;Task.gather(tasks)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This works like &lt;code&gt;sequence&lt;/code&gt;, except that the evaluation has non-ordered
effects. What this means is that, if the tasks are forking threads,
then they get executed in parallel.&lt;/p&gt;

&lt;p&gt;For synchronous/immediate tasks the numbers are:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Operation&lt;/th&gt;
      &lt;th&gt;Score&lt;/th&gt;
      &lt;th&gt;Error&lt;/th&gt;
      &lt;th&gt;Units&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Monix&lt;/td&gt;
      &lt;td&gt;Sync&lt;/td&gt;
      &lt;td&gt;Gather&lt;/td&gt;
      &lt;td&gt;3800.559&lt;/td&gt;
      &lt;td&gt;341.509&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scalaz&lt;/td&gt;
      &lt;td&gt;Sync&lt;/td&gt;
      &lt;td&gt;Gather&lt;/td&gt;
      &lt;td&gt;2152.441&lt;/td&gt;
      &lt;td&gt;13.569&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;S.Future&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Sequence&lt;/td&gt;
      &lt;td&gt;1753.614&lt;/td&gt;
      &lt;td&gt;20.871&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;And for forked tasks:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Operation&lt;/th&gt;
      &lt;th&gt;Score&lt;/th&gt;
      &lt;th&gt;Error&lt;/th&gt;
      &lt;th&gt;Units&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Monix&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Gather&lt;/td&gt;
      &lt;td&gt;1396.797&lt;/td&gt;
      &lt;td&gt;17.098&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scalaz&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Gather&lt;/td&gt;
      &lt;td&gt;1014.452&lt;/td&gt;
      &lt;td&gt;13.569&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;S.Future&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Sequence&lt;/td&gt;
      &lt;td&gt;1753.614&lt;/td&gt;
      &lt;td&gt;20.871&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Including the results of &lt;code&gt;Future.sequence&lt;/code&gt; as well, because &lt;code&gt;Future&lt;/code&gt;
has strict evaluation and it can be used to execute futures in
parallel. The performance of &lt;code&gt;gather&lt;/code&gt; can be worse than
&lt;code&gt;Future.sequence&lt;/code&gt;, because of the execution model. But if it executes
tasks that have immediate execution, or a mixed batch, then it is much
better.&lt;/p&gt;

&lt;h3 id=&quot;gather-unordered&quot;&gt;Gather Unordered&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;gatherUnordered&lt;/code&gt; operation would be:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;Task.gatherUnordered(tasks)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This behaves like &lt;code&gt;gather&lt;/code&gt;, except that it does not care for the order
in which the results are served. Can have much better performance if
you don’t care about order.&lt;/p&gt;

&lt;p&gt;For synchronous/immediate tasks:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Operation&lt;/th&gt;
      &lt;th&gt;Score&lt;/th&gt;
      &lt;th&gt;Error&lt;/th&gt;
      &lt;th&gt;Units&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Monix&lt;/td&gt;
      &lt;td&gt;Sync&lt;/td&gt;
      &lt;td&gt;Unordered&lt;/td&gt;
      &lt;td&gt;5654.462&lt;/td&gt;
      &lt;td&gt;150.792&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scalaz&lt;/td&gt;
      &lt;td&gt;Sync&lt;/td&gt;
      &lt;td&gt;Unordered&lt;/td&gt;
      &lt;td&gt;3340.645&lt;/td&gt;
      &lt;td&gt;244.145&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;S.Future&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Sequence&lt;/td&gt;
      &lt;td&gt;1753.614&lt;/td&gt;
      &lt;td&gt;20.871&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;For forked tasks:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Operation&lt;/th&gt;
      &lt;th&gt;Score&lt;/th&gt;
      &lt;th&gt;Error&lt;/th&gt;
      &lt;th&gt;Units&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Monix&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Unordered&lt;/td&gt;
      &lt;td&gt;1658.055&lt;/td&gt;
      &lt;td&gt;12.114&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Scalaz&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Unordered&lt;/td&gt;
      &lt;td&gt;1657.454&lt;/td&gt;
      &lt;td&gt;35.218&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;S.Future&lt;/td&gt;
      &lt;td&gt;Forked&lt;/td&gt;
      &lt;td&gt;Sequence&lt;/td&gt;
      &lt;td&gt;1753.614&lt;/td&gt;
      &lt;td&gt;20.871&lt;/td&gt;
      &lt;td&gt;ops/s&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Again, performance is really good for synchronous tasks, whereas for
forked tasks it evens out with the performance of &lt;code&gt;Future.sequence&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;raw-output&quot;&gt;Raw output&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;[info] # Run complete. Total time: 00:04:28
[info]
[info] Benchmark                              Mode  Cnt     Score     Error  Units
[info] TaskGatherBenchmark.gatherMonixA      thrpt   10  1396.797 ±  17.098  ops/s
[info] TaskGatherBenchmark.gatherMonixS      thrpt   10  3800.559 ± 341.509  ops/s
[info] TaskGatherBenchmark.gatherScalazA     thrpt   10  1014.452 ±  13.569  ops/s
[info] TaskGatherBenchmark.gatherScalazS     thrpt   10  2152.441 ±  24.811  ops/s
[info] TaskGatherBenchmark.sequenceFutureA   thrpt   10  1753.614 ±  20.871  ops/s
[info] TaskGatherBenchmark.sequenceMonixA    thrpt   10  2044.624 ±  24.852  ops/s
[info] TaskGatherBenchmark.sequenceMonixS    thrpt   10  6716.906 ± 157.947  ops/s
[info] TaskGatherBenchmark.sequenceScalazA   thrpt   10  1090.355 ±  15.851  ops/s
[info] TaskGatherBenchmark.sequenceScalazS   thrpt   10  3518.888 ± 167.148  ops/s
[info] TaskGatherBenchmark.unorderedMonixA   thrpt   10  1658.055 ±  12.114  ops/s
[info] TaskGatherBenchmark.unorderedMonixS   thrpt   10  5654.462 ± 150.792  ops/s
[info] TaskGatherBenchmark.unorderedScalazA  thrpt   10  1657.454 ±  35.218  ops/s
[info] TaskGatherBenchmark.unorderedScalazS  thrpt   10  3340.645 ± 244.145  ops/s
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2016/08/25/monix-task-performance/?pk_campaign=rss&quot;&gt;Monix Task vs Scalaz vs Future, The Benchmark&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 25 Aug 2016 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2016/08/25/monix-task-performance/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2016/08/25/monix-task-performance/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Monix</category>
  <category>Typelevel</category>
  </item>


<item>
  <title>Akka &amp; Monix - Typelevel Summit, Oslo 2016</title>
  <description>Presentation from Typelevel Summit, Oslo, 2016, about my experience in dealing with modeling behavior by processing asynchronous soft-real time signals using Akka &amp;amp; Monix.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      
&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=CQxviYlAKaY&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/CQxviYlAKaY/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=CQxviYlAKaY&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

    &lt;/div&gt;
  
      
&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=CQxviYlAKaY&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/CQxviYlAKaY/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=CQxviYlAKaY&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Akka &amp; Monix: Controlling Power Plants&lt;/strong&gt; -
my presentation from the
&lt;a href=&quot;http://typelevel.org/event/2016-05-summit-oslo/&quot;&gt;Typelevel Summit, Oslo, 2016&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://alexn.org/assets/pdfs/Akka-Monix.pdf&quot;&gt;Slides (PDF file)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=CQxviYlAKaY&quot;&gt;Video (YouTube)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also see:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://alexn.org/blog/2016/05/10/monix-task/&quot;&gt;Monix Task&lt;/a&gt;, flatMap(Oslo), 2016&lt;/li&gt;
  &lt;li&gt;the &lt;a href=&quot;https://github.com/monixio/monix&quot;&gt;Monix&lt;/a&gt; project&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This talk is about my experience in dealing with modeling behavior
by processing asynchronous soft realtime signals from different
sources using Akka, along with Monix, the library for building
asynchronous and event-based logic.&lt;/p&gt;

&lt;p&gt;It’s an experience report from my work in monitoring and controlling
power plants. We do this by gathering signals in real time and
modeling state machines that give us the state in which an asset is in.
The component I worked on is the one component in the project that
definitely adheres to FP principles, the business logic being
described with pure functions and data-structures and the communication
being handled by actors and by Observable streams. I want to show
how I pushed side effects at the edges, in a very pragmatic setup.&lt;/p&gt;

&lt;p&gt;This presentation will focus on Akka best practices, the wiring
needed for describing purely functional state, along with a
presentation of Monix Observable and how that helps.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2016/05/15/monix-observable/?pk_campaign=rss&quot;&gt;Akka &amp; Monix - Typelevel Summit, Oslo 2016&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 15 May 2016 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2016/05/15/monix-observable/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2016/05/15/monix-observable/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Monix</category>
  <category>Video</category>
  </item>


<item>
  <title>Monix Task - flatMap(Oslo) 2016</title>
  <description>My presentation from flatMap(Oslo) 2016. It’s about the Monix Task, a new type for dealing with asynchronous processing on top of Scala and Scala.js.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      
&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=rftcbxj7et0&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/rftcbxj7et0/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=rftcbxj7et0&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

    &lt;/div&gt;
  
      
&lt;figure class=&quot;video&quot;&gt;
  
  &lt;a href=&quot;https://www.youtube.com/watch?v=rftcbxj7et0&amp;autoplay=1&quot; target=&quot;_blank&quot; class=&quot;youtube-play-link&quot; title=&quot;Go to YouTube video&quot;&gt;
    &lt;img src=&quot;https://img.youtube.com/vi/rftcbxj7et0/maxresdefault.jpg?202603060940&quot; alt=&quot;&quot; class=&quot;play-thumb&quot; width=&quot;1280&quot; height=&quot;720&quot;&gt;
  &lt;/a&gt;
  &lt;figcaption&gt;&lt;p&gt;&lt;em&gt;
    &lt;a href=&quot;https://www.youtube.com/watch?v=rftcbxj7et0&amp;autoplay=1&quot; target=&quot;_blank&quot;&gt;
      Video link
      (open on YouTube.com)
    &lt;/a&gt;
  &lt;/em&gt;&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Monix Task: Lazy, Async &amp; Awesome&lt;/strong&gt; -
my presentation from
&lt;a href=&quot;http://2016.flatmap.no/nedelcu.html#session&quot;&gt;flatMap(Oslo) 2016&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://alexn.org/assets/pdfs/Monix-Task.pdf&quot;&gt;Slides (PDF file)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=rftcbxj7et0&quot;&gt;Video (YouTube)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also see:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://alexn.org/blog/2016/05/15/monix-observable/&quot;&gt;Akka &amp; Monix&lt;/a&gt;,
Typelevel Summit, Oslo, 2016&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;https://monix.io&quot;&gt;Monix&lt;/a&gt; project&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;Scala’s Future from the standard library is great, but sometimes we need more.&lt;/p&gt;

&lt;p&gt;A Future strives to be a value, one detached from time and for
this reason its capabilities are restricted and for some use-cases
its behavior ends up being unintuitive. Hence, while the Future/Promise
pattern is great for representing asynchronous results of processes that
may or may not be started yet, it cannot be used as a specification
for an asynchronous computation.&lt;/p&gt;

&lt;p&gt;The Monix Task is in essence about dealing with asynchronous
computations and non-determinism, being inspired by the Scalaz Task
and designed from the ground up for performance and to be compatible with
Scala.js/Javascript runtimes and with the Cats library. It also makes use of
Scala’s Future to represent results, the two being complementary.&lt;/p&gt;

&lt;p&gt;In this talk I’ll show you its design, when you should use it and
why in dealing with asynchronicity it’s better to work with Task
instead of blocking threads.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2016/05/10/monix-task/?pk_campaign=rss&quot;&gt;Monix Task - flatMap(Oslo) 2016&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 10 May 2016 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2016/05/10/monix-task/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2016/05/10/monix-task/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Monix</category>
  <category>Scala</category>
  <category>Video</category>
  </item>


<item>
  <title>Avoid Javaisms: Mocks, Stubs, DI is Code Smell</title>
  <description>Such practices represent clear signals for code smell, meaning code that sucks as a symptom of a bigger problem, one of design. The lumping together of these practices is not an accident, as they are related.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2015/12/15/avoid-javaisms-code-smell/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/skunk.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;630&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I’m a man of strong opinions and I truly believe that when we are
  doing
  &lt;a href=&quot;http://www.martinfowler.com/articles/mocksArentStubs.html&quot;&gt;mocking, stubbing&lt;/a&gt;,
  &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_injection&quot;&gt;dependency injection&lt;/a&gt;
  and integration testing, such practices represent clear signals for
  code smell, meaning code that sucks as a symptom of a bigger problem,
  one of design. The lumping together of these practices is not an
  accident, as they are related.
&lt;/p&gt;

&lt;p&gt;Let’s take an example. Often in our components we’ve got dependencies,
other components only slightly related and on which we depend for
producing the desired effects. Things like database access, for both
reads and writes. In true Java spirit, lets build our noun:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait DBService {
  def readItemConfig(uuid: UUID): Option[ItemConfig]
  def saveItemConfig(uuid: UUID, config: ItemConfig): Unit

  def readDatapoints(item: UUID, offset: Int, count: Int): Seq[Datapoint]
  def persistDatapoint(item: UUID, dp: Datapoint): Unit
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This interface is reasonably abstract, meaning we aren’t leaking too
many underlying storage details. Well, we are assuming synchronous
responses and the datapoints are read in batches instead of a nice
stream, but those are details that can be corrected and the interface
works for a text file, PostgreSQL, MongoDB or what have you. So now we
can depend on it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class ItemActor(db: DBService) extends Actor {
  def receive = {
    case Init(uuid) =&gt;
      for (cfg &lt;- db.readItemConfig(uuid))
        context.become(active(cfg))
  }

  def active(cfg: ItemConfig): Receive = ???
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course, if you’ve got masochistic tendencies, you might prefer
&lt;a href=&quot;https://github.com/alexandru/scala-best-practices/blob/master/sections/3-architecture.md#31-should-not-use-the-cake-pattern&quot;&gt;the Cake pattern&lt;/a&gt;,
being the same thing, only much worse, because now you’ve got garbage
enhanced by global state and polymorphic superpowers, sucking as much
as Guice, only at compile-time:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait ItemActorComponentImpl {
  self: DBServiceComponent =&gt;

  class ItemActor extends Actor {
    def receive = {
      case Init(uuid) =&gt;
        for (cfg &lt;- dbService.readItemConfig(uuid))
          context.become(active(cfg))
    }

    def active(cfg: ItemConfig): Receive = ???
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I personally can’t stand that, being the epitome of good intentions
gone wrong. But back to our point, if we want to test this actor, we’d
have to mock or stub our &lt;code&gt;DBService&lt;/code&gt;, right?&lt;/p&gt;

&lt;p&gt;Well, here’s &lt;em&gt;the problem&lt;/em&gt; mate: until now this actor only depends on
&lt;code&gt;DBService.readItemConfig&lt;/code&gt;, yet we have to mock or stub the entire
interface of &lt;code&gt;DBService&lt;/code&gt;. And having to mock or stub things unrelated
to testing this functionality should indicate that this code is too
&lt;em&gt;tightly coupled&lt;/em&gt;. Right there your nose should reject the air
emanated from this code and it’s common sense that often save us,
even though we often can’t place our finger on the problem.&lt;/p&gt;

&lt;p&gt;OK, OK, lets fix this somewhat using a common Java “best practice”, by
splitting this interface into smaller modules. Our &lt;code&gt;DBService&lt;/code&gt;
interface does too much, or so the popular wisdom would say.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait ItemConfigsRepository {
  def read(uuid: UUID): Option[ItemConfig]
  def save(uuid: UUID, config: ItemConfig): Unit
}

trait DatapointsRepository {
  def readList(item: UUID, offset: Int, count: Int): Seq[Datapoint]
  def persist(item: UUID, dp: Datapoint): Unit
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That feels better, right? By splitting functionality in smaller units
of finer-grained stuff, this should ameliorate our dependency
woes. Wrong! Now we’ve got two problems:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class ItemActor
  (icsRepo: ItemConfigsRepository, dpsRepo: DatapointsRepository)
  extends Actor {

  def receive = {
    case Init(uuid) =&gt;
      for (cfg &lt;- icsRepo.read(uuid))
        context.become(active(cfg, State.empty))
  }

  def active(cfg: ItemConfig, state: State): Receive = {
    case Signal(value) =&gt;
      val newState = state.evolve(value)
      dpsRepo.persist(cfg.uuid, state.powerOutput)
      context.become(active(cfg, newState))
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;BAM, more dependencies, more garbage, more mocks and stubs. Does this
ring a bell? Cake makes it worse btw. But anyway, now we can see that
our solution with &lt;code&gt;ItemConfigsRepository&lt;/code&gt; doesn’t work, as &lt;code&gt;readItem&lt;/code&gt;
is often not used in the same place as &lt;code&gt;writeItem&lt;/code&gt;, so our action had
an opposite effect of what we wanted.&lt;/p&gt;

&lt;p&gt;How can this be, our interfaces are abstract and split in small units
according to best practices, yet what are we doing wrong?&lt;/p&gt;

&lt;p&gt;Maybe this isn’t so bad, right? I mean surely we can stub the
dependencies that aren’t actually used and be done with it, everybody
else is doing it. And look, we’ve got dependency injection to deal
with all the constructor annoyances. Oh, except when you’ve got more
to add, things unrelated to the actual business logic, like persisting
more stuff:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;  def active(cfg: ItemConfig, state: State): Receive = {
    case Signal(value) =&gt;
      val newState = state.evolve(value)
      dpsRepo.persist(cfg.uuid, state.powerOutput)
      dpsRepo.persist(cfg.uuid, state.basepoint) // &lt;-- here
      context.become(active(cfg, newState))
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now with mocks, your tests are broken even though the business
logic hasn’t changed, whereas with stubs that ignore those calls, both
of those calls might as well not exist. Both outcomes are wrong.&lt;/p&gt;

&lt;p&gt;Here we are having a side-effect, which is persisting values in the
database in response to that &lt;code&gt;State&lt;/code&gt; being evolved when receiving
&lt;code&gt;Signal&lt;/code&gt; values.&lt;/p&gt;

&lt;p&gt;Yet we have a non-obvious &lt;em&gt;implementation leak&lt;/em&gt;. From the point of
view of this actor, those persistence calls are just signals that a
state change happened and that we could do (but not necessarily)
something &lt;em&gt;in response&lt;/em&gt;, but the actor should not care at all that
what we are doing is actual persistence in a database repository, or
sending values over an akka remoting connection, or over web-socket,
or dumping some logs on disk. These concerns should be totally outside
of our component and all we should be testing is if our component is
signaling stuff to the outside world. We tried fixing &lt;code&gt;DBService&lt;/code&gt; but
in fact our Actor is broken.&lt;/p&gt;

&lt;p&gt;Meet the famous and underused
&lt;a href=&quot;https://en.wikipedia.org/wiki/Observer_pattern&quot;&gt;Observer pattern&lt;/a&gt;. And
its sibling on steroids &lt;a href=&quot;http://reactivex.io/&quot;&gt;ReactiveX&lt;/a&gt;. Here’s the
sample above using &lt;a href=&quot;https://github.com/monifu/monifu&quot;&gt;Monifu&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class ItemActor(output: Channel[Signal])
  extends Actor {

  def receive = {
    case cfg: ItemConfig =&gt;
      context.become(active(cfg, State.empty))
  }

  def active(cfg: ItemConfig, state: State): Receive = {
    case Signal(value) =&gt;
      val newState = state.evolve(value)
      output.pushNext(newState)
      context.become(active(cfg, newState))

    case cfg: ItemConfig =&gt;
      context.become(active(cfg, state))
  }
}

// ...
// in a galaxy far, far away

dbConfigSource.subscribe { config =&gt;
  actor ! itemConfig
}

output.subscribe { signal =&gt;
  dbService.persist(signal.uuid, signal.powerOutput)
  dbService.persist(signal.uuid, signal.basepoint)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, I know that Akka actors are cool and all, this is not about you
using or not Akka actors. So lets implement the Observer pattern on
top of Akka actors to see how that looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class MyActor extends Actor {
  def receive = active(State.empty, Set.empty)

  def active(state: State, subscribers: Set[ActorRef]): Receive = {
    case &quot;register&quot; =&gt;
      val ref = sender()
      if (!subscribers.contains(ref)) {
        context.watch(ref)
        context.become(active(state, subscribers + ref))
      }

    case Terminated(ref) =&gt;
      context.unwatch(ref)
      context.become(active(state, subscribers - sender))

    case Signal(value) =&gt;
      val newState = state.evolve(value)
      for (subscriber &lt;- subscribers) {
        for (event &lt;- newState.events)
          subscriber ! event
      }

      context.become(active(newState, subscribers))
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It has been my general opinion that actors should
&lt;a href=&quot;https://github.com/alexandru/scala-best-practices/blob/master/sections/5-actors.md#52-should-mutate-state-in-actors-only-with-contextbecome&quot;&gt;mutate their state with context.become&lt;/a&gt;
and one reason is because that enables us to separate the business
logic from the actor and leave the actor to handle just the
communication side. Should the above actor be tested? Maybe, if you’ve
got time, but it really isn’t a priority, because it doesn’t contain
business logic. Let’s go deeper. The business logic, exposed by
&lt;code&gt;newState = state.evolve&lt;/code&gt; would be something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class Event(value: Int)

case class State
  (value: Int, lastEvent: Int, events: Seq[Event]) {

  def evolve(newValue: Int): State = {
    if (math.abs(newValue - lastEvent) &gt; 100)
      State(newValue, newValue, Seq(Event(newValue)))
    else
      copy(value = newValue)
  }

  def popEvents: (Seq[Event], State) =
    (events, copy(events = Seq.empty))
}

object State {
  val empty = State(0, 0, Seq.empty)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;M’kay, so this does have business logic that would be valuable for
testing. AND we are modeling the side-effects in a pure way, by saying
on each &lt;code&gt;evolve&lt;/code&gt; “&lt;em&gt;here’s a bunch of signals to emit Bob, I don’t care
how you do it or who reads them&lt;/em&gt;”.&lt;/p&gt;

&lt;p&gt;Does this code have any dependencies whatsoever? No, it’s pure and can
be tested in total isolation and for things that actually matter, you
know, unit testing. This is the essence of functional programming and
(I hope) of Scala. Because whenever you’re using
&lt;a href=&quot;http://mockito.org/&quot;&gt;Mockito&lt;/a&gt; it means that you’re not doing the
above.&lt;/p&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;dependency injection, mocking and stubbing is meant for hiding
garbage under the rug&lt;/li&gt;
  &lt;li&gt;for writes, you don’t have to sprinkle your side-effecting calls all
over the place, when you can decouple those concerns by implementing
signaling by means of the Observer pattern&lt;/li&gt;
  &lt;li&gt;for reads you can have components that &lt;em&gt;push&lt;/em&gt; those configurations
into your component and the actual wiring is very often not worth
testing, because …&lt;/li&gt;
  &lt;li&gt;testing has diminishing returns: math formulas, the whiles and the
ifs and the decision making are very important, but the interaction
with external components or systems? Not so much, especially because
you end up testing other people’s libraries and frameworks,
essentially duplicating functionality and generally not worth the
trouble&lt;/li&gt;
  &lt;li&gt;integration testing is like meat eating - it’s not that meat eating
is bad for you per se, but rather the fact that by eating meat
you’re not eating enough vegetables. You see, we have a finite
budget and by doing integration testing it means that you’re not
doing something else. And people that do integration testing in
their code are often the people that gave up on refactoring and unit
testing their convoluted and tightly coupled code&lt;/li&gt;
  &lt;li&gt;mocks and stubs are a definite sign that your components are too
tightly coupled and that your business logic is mixed with
side-effects of short term value involving third-party components
and systems. It’s usually a sign that you need to clean up your mess&lt;/li&gt;
  &lt;li&gt;testing Akka actors is horrible because of their asynchronous nature
and that’s a good thing, because it makes you realize that actors
are about communication and that you don’t care about communication
in your unit tests, so you’d better not have business logic in them ;-)&lt;/li&gt;
  &lt;li&gt;your DBService can always fail for reasons outside of your control,
so instead of testing DBService, your effort is much better spent in
making your own component more resilient to failure and in improving
logging, because when it comes to external systems, testing the
happy path is worthless, being the edge cases that get you&lt;/li&gt;
  &lt;li&gt;personally I dislike very much tests that pretend to test things,
but have zero value - writing unit tests is just a means to an end,
take time and have to be maintained, so don’t burden your team with
fragile tests that don’t test anything of value, because that’s not
why you’ve been hired&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pain is good. Mocks, stubs, DI, integration tests are about avoiding
pain by fixing the symptoms rather than the disease. Don’t treat the
symptoms, treat the disease.&lt;/p&gt;

&lt;p&gt;Also see the list of
&lt;a href=&quot;https://github.com/alexandru/scala-best-practices&quot;&gt;best practices&lt;/a&gt; I
initiated that’s free of Javaisms.&lt;/p&gt;

&lt;p&gt;Cheers,&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2015/12/15/avoid-javaisms-code-smell/?pk_campaign=rss&quot;&gt;Avoid Javaisms: Mocks, Stubs, DI is Code Smell&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 15 Dec 2015 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2015/12/15/avoid-javaisms-code-smell/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2015/12/15/avoid-javaisms-code-smell/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  </item>


<item>
  <title>Monifu vs Akka Streams</title>
  <description>Back in June I attended
Scala Days in
Amsterdam and participated at a talk by Mathias Doenitz on
The Reactive Streams Implementation Landscape.
It was a good talk, yet I felt a little bias towards Akka Streams,
which is natural coming from somebody that is contributing to Akka,
but let me give you the perspective from the other side.</description>
  <content:encoded>&lt;p&gt;Back in June I attended
&lt;a href=&quot;http://event.scaladays.org/scaladays-amsterdam-2015&quot;&gt;Scala Days&lt;/a&gt; in
Amsterdam and participated at a talk by Mathias Doenitz on
&lt;a href=&quot;https://www.parleys.com/tutorial/the-reactive-streams-implementation-landscape&quot;&gt;The Reactive Streams Implementation Landscape&lt;/a&gt;.
It was a good talk, yet I felt a little bias towards Akka Streams,
which is natural coming from somebody that is contributing to Akka,
but let me give you the perspective from &lt;em&gt;the other side&lt;/em&gt;.&lt;/p&gt;

&lt;figure class=&quot;page-width&quot;&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/monifu.png&quot; width=&quot;1200&quot; height=&quot;756&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;For a short introduction, we are talking about libraries that are
meant for stream processing. Several libraries exist for stream
processing, a craze that started with
&lt;a href=&quot;https://msdn.microsoft.com/en-us/data/gg577609.aspx&quot;&gt;Rx.NET&lt;/a&gt;, or with
&lt;a href=&quot;https://en.wikipedia.org/wiki/Iteratee&quot;&gt;Iteratees&lt;/a&gt; on the Haskell
side and since then we ended up with ports and enhancements, like
&lt;a href=&quot;https://github.com/ReactiveX/RxJava&quot;&gt;RxJava&lt;/a&gt;,
&lt;a href=&quot;https://github.com/Reactive-Extensions/RxJS&quot;&gt;Rx.js&lt;/a&gt;,
&lt;a href=&quot;https://baconjs.github.io/&quot;&gt;Bacon.js&lt;/a&gt;,
&lt;a href=&quot;https://www.playframework.com/documentation/2.4.x/Iteratees&quot;&gt;Play’s Iteratees&lt;/a&gt;,
&lt;a href=&quot;https://github.com/scalaz/scalaz-stream&quot;&gt;Scalaz Streams&lt;/a&gt; and more
recently
&lt;a href=&quot;http://doc.akka.io/docs/akka-stream-and-http-experimental/current/&quot;&gt;Akka Streams&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The library I’ve been working on is named
&lt;strong&gt;&lt;a href=&quot;https://github.com/monifu/monifu&quot;&gt;Monifu&lt;/a&gt;&lt;/strong&gt;. It has just
reached 1.0-RC1, it is built on idiomatic Scala principles, is
cross-compiled to &lt;a href=&quot;http://www.scala-js.org/&quot;&gt;Scala.js&lt;/a&gt;, is freaking
awesome and even though it is inspired by Rx, compared to other Rx
implementations, it was designed from scratch to deal with
back-pressure. It’s also implementing the 1.0 version of the
&lt;a href=&quot;http://www.reactive-streams.org/&quot;&gt;Reactive Streams&lt;/a&gt; protocol for
interoperability. Checkout this cool sample of client/server
communications, where both the server-side and the browser-side is handled
by Monifu: &lt;a href=&quot;https://github.com/monifu/monifu-sample&quot;&gt;code&lt;/a&gt; /
&lt;a href=&quot;http://monifu-sample.herokuapp.com/&quot;&gt;demo&lt;/a&gt;
(that’s a free Heroku node, go easy on it :-)).&lt;/p&gt;

&lt;h2 id=&quot;code&quot;&gt;Code&lt;/h2&gt;

&lt;p&gt;I am biased, I admit. But personally I find the design of Akka Streams
to be &lt;em&gt;conceptually ugly&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Mathias was kind to release his comparison
&lt;a href=&quot;https://github.com/sirthias/rs-comparison&quot;&gt;on GitHub&lt;/a&gt;, containing the
same problem solved with Akka Streams, RxJava and Reactor and I think
this provides a good starting point for a comparison.  So lets take
Mathias’s own
&lt;a href=&quot;https://github.com/alexandru/rs-comparison/blob/master/src/main/scala/swave/rsc/AkkaPi.scala&quot;&gt;sample for Akka Streams&lt;/a&gt;
and compare it with my
&lt;a href=&quot;https://github.com/alexandru/rs-comparison/blob/master/src/main/scala/swave/rsc/MonifuPi.scala&quot;&gt;own sample for Monifu&lt;/a&gt;. Akka
Streams is missing some useful operators, like operators for
throttling, therefore the code needs to implement it.&lt;/p&gt;

&lt;p&gt;To throttle once per second, here’s what the Akka Streams sample is doing:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Akka Streams sample
def onePerSecValve: Flow[State, State, Unit] =
  Flow() { implicit b ⇒
    import FlowGraph.Implicits._

    val zip = b.add(ZipWith[State, Tick.type, State](Keep.left)
      .withAttributes(OperationAttributes.inputBuffer(1, 1)))
    val dropOne = b.add(Flow[State].drop(1))

    Source(Duration.Zero, 1.second, Tick) ~&gt; zip.in1
    zip.out ~&gt; dropOne.inlet

    (zip.in0, dropOne.outlet)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Monifu has
&lt;a href=&quot;https://monifu.org/api/1.0-RC1/index.html#monifu.reactive.Observable@throttleFirst(interval:scala.concurrent.duration.FiniteDuration):monifu.reactive.Observable[T]&quot;&gt;throttling operators&lt;/a&gt;
built-in, but if that weren’t the case, here’s how you could implement
sampling per second:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Monifu sample
def throttleOnePerSec[T](source: Observable[T]): Observable[T] = {
  val tick = Observable.intervalAtFixedRate(1.second, 1.second)
  source.whileBusyDropEvents.zip(tick)
    .map { case (elem, _) =&gt; elem }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Both pieces of code are doing roughly the same thing. A different
data-source is being started that generates a tick over every second
and that data-source is being &lt;code&gt;zipped&lt;/code&gt; with our source. Events emitted
by our source are dropped as long as the tick is silent and then when
the tick event happens we emit whatever we’ve got. Using &lt;code&gt;zip&lt;/code&gt; for
sampling is actually very inefficient, as &lt;code&gt;zip&lt;/code&gt; is a fundamentally
concurrent operator, but this is just for comparing apples with apples
;-)&lt;/p&gt;

&lt;p&gt;So why is the code for Akka Streams looking so complicated? Well
that’s because of its design, but lets come back to that later.
In the Akka Streams sample, here’s how the original data-source is
being split in two streams (&lt;code&gt;filterInner&lt;/code&gt; and &lt;code&gt;filterOuter&lt;/code&gt;) and then
merged:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Akka Streams sample
Source(() ⇒ new RandomDoubleValueGenerator())
  .grouped(2)
  .map { case x +: y +: Nil ⇒ Point(x, y) }
  .via(broadcastFilterMerge)

// ...
def broadcastFilterMerge: Flow[Point, Sample, Unit] =
  Flow() { implicit b ⇒
    import FlowGraph.Implicits._

    val broadcast = b.add(Broadcast[Point](2)) // split one upstream into 2 downstreams
    val filterInner = b.add(Flow[Point].filter(_.isInner).map(InnerSample))
    val filterOuter = b.add(Flow[Point].filter(!_.isInner).map(OuterSample))
    val merge = b.add(Merge[Sample](2)) // merge 2 upstreams into one downstream

    broadcast.out(0) ~&gt; filterInner ~&gt; merge.in(0)
    broadcast.out(1) ~&gt; filterOuter ~&gt; merge.in(1)

    (broadcast.in, merge.out)
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s Monifu’s version, doing the same thing.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// Monifu sample
val source = Observable
  .fromIterator(new RandomDoubleValueGenerator())
  .buffer(2)
  .map { case Seq(x, y) ⇒ Point(x, y) }
  .share() // shares the data-source

val innerSamples = source.filter(_.isInner).map(InnerSample)
val outerSamples = source.filter(!_.isInner).map(OuterSample)

Observable.merge(innerSamples, outerSamples)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;At this point I think a pattern emerges.&lt;/p&gt;

&lt;h2 id=&quot;design&quot;&gt;Design&lt;/h2&gt;

&lt;p&gt;A stream of information is like a river. Does the river care who
observes it or who drinks from it? No, it doesn’t. And yes, sometimes
you need to share the source between multiple listeners, sometimes you
want to create new sources for each listener. But the listener
shouldn’t care what sort of producer it has on its hands or
vice-versa. And people are really not good at reasoning about graphs
and making those graphs explicit doesn’t make it better, it makes it
worse.&lt;/p&gt;

&lt;figure class=&quot;page-width&quot;&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/river.jpg&quot; width=&quot;587&quot; height=&quot;640&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;In Monifu / Rx you’ve got hot observables (hot data sources shared
between an unlimited number of subscribers) and cold observables (each
subscriber gets its very own private data source). You can also
convert any cold data source into a hot one by using the &lt;code&gt;multicast&lt;/code&gt;
operator, in combination with &lt;code&gt;Subjects&lt;/code&gt; that dictate behavior
(e.g. Publish, Behavior, Async or Replay). The
&lt;a href=&quot;https://monifu.org/api/1.0-RC1/index.html#monifu.reactive.observables.ConnectableObservable&quot;&gt;ConnectableObservable&lt;/a&gt;
is meant for hot data sources. In our sample above, we are using
&lt;code&gt;share()&lt;/code&gt;, an operator that transforms our data source into a hot one
and then applies reference counting on its subscribers to know when to
stop it. This is what &lt;em&gt;encapsulation&lt;/em&gt; is all about.&lt;/p&gt;

&lt;p&gt;In Akka Streams the sources have a “single output” port and what you
do is you build “flow graphs” and sinks. Akka Streams is thus all
about modeling how streams are split. They call it “&lt;em&gt;explicit
fan-out&lt;/em&gt;” and it’s a design choice. However I consider it an
encapsulation leak that makes things way more complicated than they
should be and defeats the purpose of using a library for streams
manipulation in the first place. In Rx (Rx.NET / RxJava / Monifu)
terms, this is like having single-subscriber Observables and then
working with Subjects (which is both a listener and a producer) and
people that have used Rx know that working with Subjects sucks and
when you do, you usually encapsulate it really, really well. This
design choice of Akka Streams has also leaked into the “Reactive
Streams” specification, as that Processor interface is irrelevant,
plus during the talks on what the &lt;code&gt;Producer&lt;/code&gt; should be, the original
design was for the &lt;code&gt;Producer&lt;/code&gt; to be single-subscriber.&lt;/p&gt;

&lt;p&gt;Another thing I don’t like is that Akka Streams depends on Akka, the
library. You need an Actor System and an &lt;code&gt;ActorFlowMaterializer&lt;/code&gt;,
whatever that is, with the tasks being executed by actors. I think
that’s a design mistake. One reason for why Scala’s &lt;code&gt;Future&lt;/code&gt; and
&lt;code&gt;ExecutionContext&lt;/code&gt; are great is precisely because they model only
asynchronous computations, but are completely oblivious to how the
required asynchronous execution happens. This
is why &lt;code&gt;Future&lt;/code&gt; works on top of Scala.js without problems.&lt;/p&gt;

&lt;p&gt;And again, I’m biased, but Monifu’s own implementation is conceptually
elegant. You’ve got the
&lt;a href=&quot;https://github.com/monifu/monifu/blob/master/core/shared/src/main/scala/monifu/concurrent/Scheduler.scala#L34&quot;&gt;Scheduler&lt;/a&gt;
that is used to execute tasks (an evolved &lt;code&gt;ExecutionContext&lt;/code&gt;), the
&lt;a href=&quot;https://github.com/monifu/monifu/blob/v1.0-RC1/monifu/shared/src/main/scala/monifu/reactive/Observable.scala#L379&quot;&gt;Observable&lt;/a&gt;
interface which is the producer, characterized solely by its
&lt;code&gt;onSubscribe&lt;/code&gt; function, then you’ve got the
&lt;a href=&quot;https://github.com/monifu/monifu/blob/v1.0-RC1/monifu/shared/src/main/scala/monifu/reactive/Observer.scala#L42&quot;&gt;Observer&lt;/a&gt;
which represents the consumer and has the back-pressure protocol baked
in its API, the
&lt;a href=&quot;https://github.com/monifu/monifu/blob/v1.0-RC1/monifu/shared/src/main/scala/monifu/reactive/Subject.scala#L34&quot;&gt;Subject&lt;/a&gt;
that is both a producer and a consumer, the
&lt;a href=&quot;https://github.com/monifu/monifu/blob/master/monifu/shared/src/main/scala/monifu/reactive/Channel.scala#L28&quot;&gt;Channel&lt;/a&gt;
which represents a way to build Observables in an imperative way
without back-pressure concerns and the
&lt;a href=&quot;https://github.com/monifu/monifu/blob/master/monifu/shared/src/main/scala/monifu/reactive/observables/ConnectableObservable.scala#L33&quot;&gt;ConnectableObservable&lt;/a&gt;,
which represents hot data-sources that are shared between multiple
subscribers. Monifu’s internals are self-explanatory and (I hope) a
joy to go through.&lt;/p&gt;

&lt;p&gt;I mean, this beauty describes Monifu’s design and represents at least
half of what you need to know (and skipping over back-pressure
concerns, you
&lt;a href=&quot;https://en.wikipedia.org/wiki/Observer_pattern&quot;&gt;already know it&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Observer[-T] {
  def onNext(elem: T): Future[Ack]

  def onError(ex: Throwable): Unit

  def onComplete(): Unit
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In contrast, I found the source-code and the concepts in Akka Streams
to be very hard to read and understand. Give it a try and compare.&lt;/p&gt;

&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;

&lt;p&gt;I’ve left the best part of Monifu for last. Here’s running the Monifu
sample:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[info] Running swave.rsc.MonifuPi

After  1,909,713 samples π is approximated as 3.14102
After  4,132,610 samples π is approximated as 3.14240
After  6,342,356 samples π is approximated as 3.14241
After  8,513,597 samples π is approximated as 3.14239
After 10,696,940 samples π is approximated as 3.14176
After 12,897,762 samples π is approximated as 3.14165
After 15,099,261 samples π is approximated as 3.14160
After 17,326,511 samples π is approximated as 3.14169
After 19,529,832 samples π is approximated as 3.14164
After 21,752,232 samples π is approximated as 3.14170

[success] Total time: 11 s, completed Sep 6, 2015 2:48:06 PM
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s Akka Streams:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[info] Running swave.rsc.AkkaPi

After     59,812 samples π is approximated as 3.12807
After    258,925 samples π is approximated as 3.13910
After    525,537 samples π is approximated as 3.14173
After    892,973 samples π is approximated as 3.14070
After  1,258,939 samples π is approximated as 3.14127
After  1,545,861 samples π is approximated as 3.14019
After  1,813,374 samples π is approximated as 3.14103
After  2,219,992 samples π is approximated as 3.14137
After  2,515,283 samples π is approximated as 3.14129
After  2,826,297 samples π is approximated as 3.14148

[success] Total time: 13 s, completed Sep 6, 2015 2:49:23 PM
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s RxJava (RxScala):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[info] Running swave.rsc.RxScalaPi

After    804,127 samples π is approximated as 3.11240
After  1,747,146 samples π is approximated as 3.12848
After  2,761,645 samples π is approximated as 3.13558
After  3,678,029 samples π is approximated as 3.13880
After  4,756,818 samples π is approximated as 3.13960
After  5,787,079 samples π is approximated as 3.14172
After  6,768,352 samples π is approximated as 3.14249
After  7,804,973 samples π is approximated as 3.14320
After  8,812,403 samples π is approximated as 3.14381
After  9,625,207 samples π is approximated as 3.14393

[success] Total time: 12 s, completed Sep 6, 2015 2:54:55 PM
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The results:&lt;/p&gt;

&lt;figure class=&quot;page-width&quot;&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/bench-monifu.png&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;So my Monifu sample is consistently beating Akka Streams by at least a
&lt;strong&gt;factor of 7&lt;/strong&gt; and RxJava/RxScala by a &lt;strong&gt;factor of 2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The difference is so large that either Akka Streams has some serious
improvements to achieve, or I’m doing something terribly wrong,
because this is Monifu’s out-of-the-box behavior, as in I haven’t even
attempted to fine tune the buffers or the scheduler for this sample.&lt;/p&gt;

&lt;p&gt;But yes, Monifu was built for both ease of use and performance.&lt;/p&gt;

&lt;h2 id=&quot;final-words&quot;&gt;Final Words&lt;/h2&gt;

&lt;p&gt;Again, I’m biased, since I’m the author of an alternative, so take
this conclusion for what it is.&lt;/p&gt;

&lt;p&gt;The precursors of Akka Streams have been
&lt;a href=&quot;https://www.playframework.com/documentation/2.4.x/Iteratees&quot;&gt;Play’s Iteratees&lt;/a&gt;
and the
&lt;a href=&quot;http://doc.akka.io/docs/akka/2.2.0/scala/io-codec.html&quot;&gt;Akka I/O Pipeline&lt;/a&gt;,
the former on its way to deprecation, the latter already
deprecated. Unfortunately I’m seeing the same mistakes: implementation
hard to read, conceptualy very complicated, while exposing custom
binary operators in the hope of forming a DSL that will somehow fix
this complexity. And I’m all for wheel reinvention when it’s done for
the right reasons, but I find this model to be inferior to an evolved
Rx (such as Monifu) and this is just one other design heading towards
deprecation.&lt;/p&gt;

&lt;p&gt;If you’re interested in Monifu, there’s still some work to be done.
It’s at release candidate for version 1.0, meaning that we’re done breaking the
API and a very functional core is ready. Monifu has been developed in
parallel to its usage in production for the past year, should be fairly
solid and has very good test coverage as testament to that, but bugs may
still happen, since a lot of work went on this past month.
Documentation is sadly a work in progress and for now only the
&lt;a href=&quot;http://monifu.org/api/current/&quot;&gt;API documentation&lt;/a&gt; is up to date. But we’re
marching towards a 1.0 release you can rely on, which should be available
in about two weeks from now (if everything goes well). Checkout the
&lt;a href=&quot;https://github.com/monifu/monifu&quot;&gt;GitHub repo&lt;/a&gt;, join
&lt;a href=&quot;https://gitter.im/monifu/monifu&quot;&gt;our chat channel&lt;/a&gt; and give us feedback.&lt;/p&gt;

&lt;h3 id=&quot;update-sep-8-800-am&quot;&gt;Update (Sep 8, 8:00 AM)&lt;/h3&gt;

&lt;p&gt;Some interesting questions happened on
&lt;a href=&quot;https://www.reddit.com/r/scala/comments/3jymvw/monifu_vs_akka_streams/&quot;&gt;the reddit thread&lt;/a&gt;.
To dispel some myths:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;currently Akka Streams does no more parallelism than Monifu does&lt;/li&gt;
  &lt;li&gt;in our sample Monifu is not single-threaded&lt;/li&gt;
  &lt;li&gt;in our sample Monifu parallelizes the portion that it can, which
is the processing of &lt;code&gt;filterInner&lt;/code&gt; and &lt;code&gt;filterOuter&lt;/code&gt;, plus execution
is jumping threads, because Monifu as a matter of policy never keeps
a single thread occupied for too long&lt;/li&gt;
  &lt;li&gt;you can’t parallelize concurrent operations, that being an oxymoron,
which is why I’m dumbfounded by claims of parallelism&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cheers,&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2015/09/06/monifu-vs-akka-streams/?pk_campaign=rss&quot;&gt;Monifu vs Akka Streams&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 06 Sep 2015 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2015/09/06/monifu-vs-akka-streams/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2015/09/06/monifu-vs-akka-streams/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Reactive Streams</category>
  </item>


<item>
  <title>Scala Best Practices</title>
  <description>This is a collection of best practices for Scala, something to get you started.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2014/10/20/scala-best-practices/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;This is a collection of best practices for Scala, something to get you started.&lt;/p&gt;

&lt;p&gt;Article has been moved to its own GitHub repo:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/alexandru/scala-best-practices/&quot;&gt;alexandru/scala-best-practices&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful as a starting point for your team, fork it.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2014/10/20/scala-best-practices/?pk_campaign=rss&quot;&gt;Scala Best Practices&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 20 Oct 2014 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2014/10/20/scala-best-practices/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2014/10/20/scala-best-practices/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Languages</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Best Practices</category>
  </item>


<item>
  <title>Resources for Learning Scala</title>
  <description>Getting started with a new programming language shouldn&apos;t be hard,
  however navigating the web for resources on getting started with Scala
  can be a doubting experience, as many such resources are either out of
  date, or wrong, or both. This post is intended to reduce the noise for
  my colleagues and other people that are interested in Scala
  development.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2013/05/13/getting-started-with-scala/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Getting started with a new programming language shouldn&apos;t be hard,
  however navigating the web for resources on getting started with Scala
  can be a doubting experience, as many such resources are either out of
  date, or wrong, or both. This post is intended to reduce the noise for
  my colleagues and other people that are interested in Scala
  development.
&lt;/p&gt;

&lt;!-- read more --&gt;

&lt;h2 id=&quot;1-tools-of-the-trade&quot;&gt;1. Tools of the Trade&lt;/h2&gt;

&lt;p&gt;All you need for getting started is the Scala interpreter and a good
text editor.&lt;/p&gt;

&lt;p&gt;First, download the archive from
&lt;strong&gt;&lt;a href=&quot;http://www.scala-lang.org/downloads&quot;&gt;scala-lang.org/downloads&lt;/a&gt;&lt;/strong&gt;,
uncompress it and place the &lt;code&gt;bin/&lt;/code&gt; subdirectory on your local
&lt;code&gt;PATH&lt;/code&gt;. Then start the “scala” interpreter and test if it works:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ scala
Welcome to Scala version 2.10.1
Type in expressions to have them evaluated.
Type :help for more information.

scala&gt; 1 + 1
res0: Int = 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You also need a good and simple text editor that can do syntax
highlighting for Scala. Your choice should be done in this order:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;your existing favorite text editor, if you have one&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;a href=&quot;https://www.sublimetext.com/&quot;&gt;Sublime Text 2&lt;/a&gt;&lt;/strong&gt; for a good
out-of-the-box experience, although for reasons I won’t go into
here, I really keep away from text-editors that aren’t open-source&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;a href=&quot;http://www.vim.org/&quot;&gt;Vim&lt;/a&gt;&lt;/strong&gt; or
&lt;strong&gt;&lt;a href=&quot;http://www.gnu.org/software/emacs/&quot;&gt;Emacs&lt;/a&gt;&lt;/strong&gt; (in combination with
&lt;a href=&quot;https://github.com/hvesalai/scala-mode2&quot;&gt;scala-mode2&lt;/a&gt; and
&lt;a href=&quot;https://github.com/capitaomorte/yasnippet&quot;&gt;yasnippet&lt;/a&gt;). These text
editors are eternal and extremely productive, however if you’re unfamiliar with neither of
them, adding the overhead of learning them on top of learning Scala
is a bit too much&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other tools you may need for &lt;em&gt;serious development&lt;/em&gt; (TM), but not
necessarily for learning:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;a href=&quot;http://www.scala-sbt.org/&quot;&gt;SBT&lt;/a&gt;&lt;/strong&gt; for building projects and
managing dependencies, being much like Maven for Java, or Leiningen
for Clojure, or Rake+Bundler for Ruby&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;a href=&quot;http://www.jetbrains.com/idea/&quot;&gt;IntelliJ IDEA&lt;/a&gt;&lt;/strong&gt;, in combination
with the &lt;a href=&quot;https://github.com/mpeltonen/sbt-idea&quot;&gt;sbt-idea&lt;/a&gt; plugin,
if you need a good IDE, but seriously, when getting your feet wet,
stay away from IDEs. The community edition is open-source and fit
for Scala development&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;a href=&quot;http://typesafe.com/platform/getstarted&quot;&gt;Typesafe Activator&lt;/a&gt;&lt;/strong&gt; is a
pretty recent development if you want to play with the TypeSafe stack
(which really means the
&lt;a href=&quot;http://www.playframework.com/&quot;&gt;Play Framework&lt;/a&gt; and
&lt;a href=&quot;http://akka.io/&quot;&gt;Akka&lt;/a&gt;). I haven’t played with it, but it looks like
a neat way to get some sample apps running quickly. It also includes SBT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But really, for playing around, start with just the Scala compiler + a
text editor that does syntax highlighting for Scala. I can’t stress
this enough.&lt;/p&gt;

&lt;h2 id=&quot;2-books&quot;&gt;2. Books&lt;/h2&gt;

&lt;p&gt;For getting started, at the moment (&lt;em&gt;May 2013&lt;/em&gt;) ignore all books
(seriously) other than these 3:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0321774094/ref=as_li_ss_il?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0321774094&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;&lt;b&gt;Scala for the Impatient&lt;/b&gt;&lt;/a&gt;
by Cay S. Horstmann, is a good pragmatic book on Scala (not so much on
functional programming), but it’s for developers experienced in other
languages, so it’s fast-paced while not scaring you away with endless
discussions on types. The PDF for the first part (out of 3) is
available from the
&lt;a href=&quot;http://typesafe.com/resources/free-books&quot;&gt;Typesafe website&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;clear&quot; style=&quot;clear: both; &quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/B004Z1FTXS/ref=as_li_ss_il?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B004Z1FTXS&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;&lt;b&gt;Programming in Scala&lt;/b&gt;&lt;/a&gt;
by Martin Odersky is a good book on programming, not just Scala - many
of the exercises in
&lt;a href=&quot;http://mitpress.mit.edu/sicp/&quot;&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;
are also present in this book, giving you the Scala-approach for
solving those problems, which is good.&lt;/p&gt;

&lt;div class=&quot;clear&quot; style=&quot;clear: both; &quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/1935182706/ref=as_li_ss_il?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1935182706&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;&lt;b&gt;Scala in Depth&lt;/b&gt;&lt;/a&gt;
by Joshua Suereth D. - this is an advanced book on Scala, with many
insights into how functional idioms work in it or advice on best practices. I’ve yet to finish it,
as it’s not really an easy lecture. But it’s a good book. Get
the eBook straight from &lt;a href=&quot;http://www.manning.com/suereth/&quot;&gt;Manning&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;clear&quot; style=&quot;clear: both; &quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;NOTE:&lt;/em&gt; these are Amazon links (with my affiliate tag) placed here for
convenience and for reading other people’s reviews, but if you want
the eBook version don’t buy from Amazon, prefer buying directly from
the publisher, as you’ll get both a DRM-free Kindle version and a PDF,
useful for desktops or iPads.&lt;/p&gt;

&lt;h2 id=&quot;3-online-resources&quot;&gt;3. Online Resources&lt;/h2&gt;

&lt;p&gt;An unspoken rule when searching for online resources about Scala is
that you should stay away from the &lt;em&gt;www.scala-lang.org&lt;/em&gt; website,
because many links are outdated and the website is not properly
maintained, as most of the effort these days is going to the
documention project (mentioned below), which will probably become the
homepage for Scala at some point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.coursera.org/course/progfun&quot;&gt;Functional Programming Principles in Scala&lt;/a&gt;&lt;/strong&gt;
is an excellent course provided by Coursera / EPFL, taught by Martin
Odersky. The course is almost over, so register right now if you want
access to the videos and assignments, or you’ll probably have to wait
for the next iteration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://docs.scala-lang.org/&quot;&gt;Scala Documentation Project&lt;/a&gt;&lt;/strong&gt; -
definitely checkout this website, as they aggregate everything good
here. If you want to learn more about Scala’s library, especially the
collections, this is the place to learn from. Checkout for instance
this &lt;strong&gt;&lt;a href=&quot;http://docs.scala-lang.org/cheatsheets/&quot;&gt;Scala cheatsheet&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://twitter.github.com/scala_school/&quot;&gt;Scala School&lt;/a&gt;&lt;/strong&gt; - a freely
available online tutorial by Twitter, which is very friendly to
newbies. I’ve read it and it’s pretty good.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://aperiodic.net/phil/scala/s-99/&quot;&gt;Ninety-Nine Scala Problems&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;a collection of 99 problems to be solved with Scala. If you get
stuck, you can view a solution which is often idiomatic. See also this
&lt;a href=&quot;https://github.com/etorreborre/s99&quot;&gt;GitHub project&lt;/a&gt; that gives you a
complete test-suite, to spare you of the
effort. &lt;a href=&quot;http://projecteuler.net/&quot;&gt;Project Euler&lt;/a&gt; is also a pretty
cool source of problems to solve.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://stackoverflow.com/tags/scala/info&quot;&gt;The Scala Overview at StackOverflow.com&lt;/a&gt;&lt;/strong&gt;
is a pretty cool aggregate of popular Scala questions. I don’t know if
they are compiling this automatically, or by hand, but it almost feels
like an online book.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://nescala.org/&quot;&gt;Online videos from nescala.org&lt;/a&gt;&lt;/strong&gt;. These
presentations are pure gold and a must see. At the moment, the
homepage features the videos from 2013, so start with the
&lt;a href=&quot;http://nescala.org/2012&quot;&gt;2012 archive&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;4-whom-to-follow&quot;&gt;4. Whom to Follow&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://typesafe.com/blog&quot;&gt;The Typesafe Blog&lt;/a&gt; usually contains news
regarding Scala adoptions in the enterprise, or release announcements
about Akka, Play, Scala-IDE, or whatever Typesafe is doing these days
and it’s useful to follow their RSS feed.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.cakesolutions.net/teamblogs/&quot;&gt;This Week in #Scala&lt;/a&gt; is a
weekly-ish article series written by Chris Cundill of Cake Solutions,
aggregating the most interesting news happening in the Scala
community. I subscribed to their newsletter.&lt;/p&gt;

&lt;p&gt;My Twitter and my RSS feed does have subscriptions to interesting
people from the Scala community, however following people tends to add
noise to your news stream. If you want to learn Scala, then following
people’s blogs and tweats is a waist of time.&lt;/p&gt;

&lt;h2 id=&quot;5-seeking-help&quot;&gt;5. Seeking Help&lt;/h2&gt;

&lt;p&gt;For seeking help for language usage:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://groups.google.com/forum/?fromgroups=#!forum/scala-user&quot;&gt;The Scala-User mailing-list&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;http://stackoverflow.com/questions/tagged/scala&quot;&gt;StackOverflow.com&lt;/a&gt;,
where I got some pretty cool answers on Scala-tagged questions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For seeking help related to usage of various Scala frameworks or
libraries, you may want to subscribe to their specific
mailing-list. For instance
&lt;a href=&quot;https://groups.google.com/forum/?fromgroups=#!forum/play-framework&quot;&gt;play-framework&lt;/a&gt;
for problems related to the Play framework.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2013/05/13/getting-started-with-scala/?pk_campaign=rss&quot;&gt;Resources for Learning Scala&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 13 May 2013 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2013/05/13/getting-started-with-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2013/05/13/getting-started-with-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Languages</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Books</category>
  </item>


<item>
  <title>Towards a Better AtomicReference</title>
  <description>The
  AtomicReference
  is like a container for a volatile reference. Usage of volatile
  references is useful for the issue of
  visibility
  in concurrent code, however AtomicReference also supports the atomic
  Compare-and-Swap
  operation (CAS for short), which is the pillar of all non-blocking
  data-structures and algorithms built on top of the JVM, including
  complex ones like the ConcurrentLinkedQueue, an implementation based
  on the
  Michael-Scott non-blocking queues.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  The
  &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/package-summary.html&quot;&gt;AtomicReference&lt;/a&gt;
  is like a container for a &lt;code&gt;volatile&lt;/code&gt; reference. Usage of &lt;code&gt;volatile&lt;/code&gt;
  references is useful for the issue of
  &lt;a href=&quot;https://alexn.org/blog/2013/03/14/jvm-multithreading-monitor-locks-visibility.html#visibility&quot;&gt;visibility&lt;/a&gt;
  in concurrent code, however &lt;code&gt;AtomicReference&lt;/code&gt; also supports the atomic
  &lt;a href=&quot;http://en.wikipedia.org/wiki/Compare-and-swap&quot;&gt;Compare-and-Swap&lt;/a&gt;
  operation (CAS for short), which is the pillar of all non-blocking
  data-structures and algorithms built on top of the JVM, including
  complex ones like the &lt;code&gt;ConcurrentLinkedQueue&lt;/code&gt;, an implementation based
  on the
  &lt;a href=&quot;http://www.cs.rochester.edu/u/michael/PODC96.html&quot;&gt;Michael-Scott non-blocking queues&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;However, the interface provided leaves something to be desired:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicReference.html#compareAndSet%28V,%20V%29&quot;&gt;compareAndSet&lt;/a&gt;
operation is too low level and for 99% of everything we do in our day to day
code it can be replaced with something much better, as we’ll see&lt;/li&gt;
  &lt;li&gt;the classes from the &lt;code&gt;java.util.concurrent.atomic&lt;/code&gt; package do not
implement a common interface, so you can’t use an
&lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html&quot;&gt;AtomicInteger&lt;/a&gt;
in place of an &lt;code&gt;AtomicReference&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;AtomicInteger&lt;/code&gt; and &lt;code&gt;AtomicLong&lt;/code&gt; provide &lt;code&gt;incrementAndGet&lt;/code&gt;, which is
really useful in practice for keeping track of things in
non-blocking counters, but why should that be available only for
Ints and Longs?  Floats, Doubles, BigInt, BigDecimal and all kinds
of numbers can be incremented too&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT UPDATE (March 31, 2014):&lt;/strong&gt; The content of this article is slightly obsolete, though
still has pedagogical value. For an up to date article on my Atomic references, checkout the wiki page maintained for project &lt;a href=&quot;https://github.com/alexandru/monifu/&quot;&gt;Monifu&lt;/a&gt;: &lt;a href=&quot;https://github.com/alexandru/monifu/blob/master/docs/atomic.md&quot;&gt;Atomic References&lt;/a&gt;&lt;/p&gt;

&lt;!-- read more --&gt;

&lt;p&gt;This is a simple and working example of how Scala can improve your
code tremendously. And I’m basically describing the implementation of
my own &lt;code&gt;shifter.concurrency.atomic.Ref&lt;/code&gt;. You can:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;see the code in &lt;a href=&quot;https://github.com/alexandru/shifter/blob/master/core/src/main/scala/shifter/concurrency/atomic/Ref.scala&quot;&gt;my GitHub repo&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;checkout the &lt;a href=&quot;http://shifter.alexn.org/api/current/core/#shifter.concurrency.atomic.package&quot;&gt;API docs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-common-interface&quot;&gt;The Common Interface&lt;/h2&gt;

&lt;p&gt;Lets start by mirroring the basics of AtomicReference:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Ref[T] {
  def get: T
  def set(update: T)
  def compareAndSet(expect: T, update: T): Boolean
}

object Ref {
  def apply[T](initial: T) = new RefAny(initial)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With a generic implementation that for now just delegates to our inner
&lt;code&gt;AtomicReference&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class RefAny[T](initial: T) extends Ref[T] {
  def get =
    instance.get()
  def set(update: T) =
    instance.set(update)
  def compareAndSet(expect: T, update: T) =
    instance.compareAndSet(expect, update)

  private[this] val instance = new AtomicReference(initial)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As I was saying, the &lt;code&gt;compareAndSet&lt;/code&gt; is too low level. Much better is
to work with transformations. How about defining a function with the
following signature:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def transformAndGet(cb: T =&gt; T): T
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that can be used like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val ref = Ref(2)

ref.transformAndGet(x =&gt; x + 2)
// =&gt; 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, incrementing numbers is not the only thing that you can do. For
instance you could store and transform immutable data-structures, like a queue:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import collection.immutable.Queue

val ref = Ref(Queue.empty[String])

ref.transformAndGet(q =&gt; q.enqueue(&quot;Alex&quot;))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;How about that? We got ourselves a non-blocking queue, without having
to implement the dreadful Michael-Scott algorithm.&lt;/p&gt;

&lt;p&gt;Implementing &lt;code&gt;Ref.transformAndGet&lt;/code&gt; is easy:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;  @tailrec
  final def transformAndGet(cb: T =&gt; T): T = {
    val oldValue = get
    val newValue = cb(oldValue)

    if (!compareAndSet(oldValue, newValue))
	  // tail-recursive call
      transformAndGet(cb)
    else
      newValue
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’m using a tail-recursive function, guarded by the &lt;code&gt;tailrec&lt;/code&gt;
annotation, because that’s how I roll. I also find it much more
readable and less error-prone. It creates a loop … as long as the
&lt;code&gt;compareAndSet&lt;/code&gt; operation is unsuccessful, then it keeps trying.&lt;/p&gt;

&lt;p&gt;We can also implement &lt;code&gt;Ref.getAndTransform&lt;/code&gt;, which returns the old
value before the transformation occurred, instead of the update:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;  @tailrec
  final def getAndTransform(cb: T =&gt; T): T = {
    val oldValue = get
    val update = cb(oldValue)

    if (!compareAndSet(oldValue, update))
	  // tail-recursive call
      getAndTransform(cb)
    else
      oldValue
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can have other utilities too, like
&lt;a href=&quot;http://shifter.alexn.org/api/current/core/index.html#shifter.concurrency.atomic.Ref@transformAndExtract[U]%28cb:T=%3E%28T,U%29%29:U&quot;&gt;transformAndExtract&lt;/a&gt;,
but lets move on to our next issue … incrementing numbers.&lt;/p&gt;

&lt;p&gt;Of course, with our transformation functions, the presence of a
shortcut for incrementing numbers is not that required anymore,
however it’s still a nice shortcut that can also provide readability
and performance advantages. The problem with a generic
&lt;code&gt;AtomicReference&lt;/code&gt; is that not all reference types are numbers that can
be incremented. Fortunately for us, Scala gives us
&lt;a href=&quot;http://en.wikipedia.org/wiki/Type_class&quot;&gt;Type Classes&lt;/a&gt; and there is
already a type class defined in Scala’s standard library for numbers:
&lt;a href=&quot;http://www.scala-lang.org/api/current/index.html#scala.math.Numeric&quot;&gt;Numeric[T]&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What &lt;code&gt;Numeric[T]&lt;/code&gt; does is to define, amongst others, the &lt;code&gt;sum&lt;/code&gt;
operation for type &lt;code&gt;T&lt;/code&gt; and of course the value for &lt;code&gt;one&lt;/code&gt;. And we don’t
need more than that.&lt;/p&gt;

&lt;p&gt;So we can define our &lt;code&gt;Ref.incrementAndGet&lt;/code&gt; function, in a generic way,
like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;  def incrementAndGet(implicit num : Numeric[T]) =
    transformAndGet(x =&gt; num.plus(x, num.one))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And lo and behold, this stuff works for any kind of number, not just
Ints and Longs:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&gt; val ref = Ref(BigInt(1))
ref: Ref[scala.math.BigInt] = Ref(1)

scala&gt; ref.incrementAndGet
res0: scala.math.BigInt = 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Best of all, if we try doing this on things that aren’t numbers, then
it fails with a compile-time error:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;scala&gt; val ref = Ref(&quot;hello&quot;)
ref: Ref[String] = Ref(hello)

scala&gt; ref.incrementAndGet
&lt;console&gt;:9: error: could not find implicit value for parameter num: Numeric[String]
              ref.incrementAndGet
                  ^
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;AtomicInteger&lt;/code&gt; from Java’s standard library already has an
&lt;code&gt;incrementAndGet&lt;/code&gt; and who knows, it might be more efficient than our
implementation. Maybe at some point it will get translated into a
single processor instruction. So we can take advantage of that by
specializing our &lt;code&gt;Ref&lt;/code&gt; for &lt;code&gt;Int&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;final class RefInt(initialValue: Int) extends Ref[Int] {
  // ....

  override def incrementAndGet(implicit num: Numeric[Int]): Int =
    instance.incrementAndGet()

  private[this] val instance = new AtomicInteger(initialValue)
}

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

&lt;p&gt;And then we can make our primary constructor return a &lt;code&gt;RefInt&lt;/code&gt;, in
case the initial value is an &lt;code&gt;Int&lt;/code&gt;. Well, here’s how the code in
&lt;code&gt;shifter.concurrency.atomic.Ref&lt;/code&gt; looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object Ref {
  def apply(initialValue: Int): RefInt =
    new RefInt(initialValue)

  def apply(initialValue: Long): RefLong =
    new RefLong(initialValue)

  def apply(initialValue: Boolean): RefBoolean =
    new RefBoolean(initialValue)

  def apply[T](initialValue: T): Ref[T] =
    new RefAny[T](initialValue)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There is still one difference between a &lt;code&gt;Ref[Int]&lt;/code&gt; and
&lt;code&gt;AtomicInteger&lt;/code&gt;. Our interface will be guilty of
&lt;a href=&quot;http://en.wikipedia.org/wiki/Object_type_%28object-oriented_programming%29#Boxing&quot;&gt;boxing and unboxing&lt;/a&gt;
the integers passed to those functions. And in the wild, using
&lt;code&gt;AtomicInteger&lt;/code&gt; for cheap and non-blocking counters is really common,
so it’s a pitty if we’ll have performance degradation here.&lt;/p&gt;

&lt;p&gt;The fix is easy though. The Scala compiler can specialize our type T
for primitive types, if we annotate our type like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait Ref[@specialized(scala.Int, scala.Long, scala.Boolean) T] {
  // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the example, the compiler will specialize the &lt;code&gt;Ref[T]&lt;/code&gt; interface
for Ints, Longs and Booleans, to avoid the boxing and unboxing
overhead.&lt;/p&gt;

&lt;p&gt;What this will do is to generate specialized methods for these
primitive types. You can inspect the generated interface easily with
the &lt;code&gt;javap&lt;/code&gt; utility. For instance, let’s see what it generates for
&lt;code&gt;compareAndSet&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;$ javap shifter.concurrency.atomic.Ref | grep compareAndSet
  public abstract boolean compareAndSet(T, T);
  public abstract boolean compareAndSet$mcZ$sp(boolean, boolean);
  public abstract boolean compareAndSet$mcI$sp(int, int);
  public abstract boolean compareAndSet$mcJ$sp(long, long);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or for &lt;code&gt;incrementAndGet&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;$ javap shifter.concurrency.atomic.Ref | grep incrementAndGet
  public abstract T incrementAndGet(scala.math.Numeric&lt;T&gt;);
  public abstract boolean incrementAndGet$mcZ$sp(scala.math.Numeric&lt;java.lang.Object&gt;);
  public abstract int incrementAndGet$mcI$sp(scala.math.Numeric&lt;java.lang.Object&gt;);
  public abstract long incrementAndGet$mcJ$sp(scala.math.Numeric&lt;java.lang.Object&gt;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So it’s basically method overloading done by the Scala
compiler. Clearly this adds some overhead in the generated .class
files and it might not do what you think it does, so use it only if
you really need it.&lt;/p&gt;

&lt;p&gt;As I was saying in the beginning, make sure to also (&lt;strong&gt;links update March 31, 2014&lt;/strong&gt;):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;see the code in &lt;a href=&quot;https://github.com/alexandru/monifu&quot;&gt;project Monifu&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;checkout the &lt;a href=&quot;http://www.monifu.org/monifu-core/current/api/#monifu.concurrent.atomic.package&quot;&gt;API docs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, you may be interested in using
&lt;strong&gt;&lt;a href=&quot;http://nbronson.github.io/scala-stm/&quot;&gt;scala-stm&lt;/a&gt;&lt;/strong&gt;, a library for
&lt;em&gt;shared transactional memory&lt;/em&gt;, that basically gives you the ability to
orchestrate multiple atomic references at once.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2013/05/07/towards-better-atomicreference-scala/?pk_campaign=rss&quot;&gt;Towards a Better AtomicReference&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 07 May 2013 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2013/05/07/towards-better-atomicreference-scala/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2013/05/07/towards-better-atomicreference-scala/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Languages</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Java</category>
  <category>Multithreading</category>
  <category>Concurrency</category>
  </item>


<item>
  <title>JVM Multithreading: Monitor Locks and Visibility</title>
  <description>Multithreading is a pain to deal with. While interviewing developers,
  I noticed that surprisingly many don&apos;t have knowledge about this topic
  and I can&apos;t blame them really. However, in this day and age, for some
  problem domains building highly-concurrent architectures may be
  paramount to the success of demanding projects. As you&apos;ll see, there
  are many high level solutions, but I personally prefer to learn with a
  bottom up approach, starting from the basic and unsafe primitives, as
  understanding the problem is always the first step to real solutions.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2013/03/14/jvm-multithreading-monitor-locks-visibility/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/ferrari.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;800&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Multithreading is a pain to deal with. While interviewing developers,
  I noticed that surprisingly many don&apos;t have knowledge about this topic
  and I can&apos;t blame them really. However, in this day and age, for some
  problem domains building highly-concurrent architectures may be
  paramount to the success of demanding projects. As you&apos;ll see, there
  are many high level solutions, but I personally prefer to learn with a
  bottom up approach, starting from the basic and unsafe primitives, as
  understanding the problem is always the first step to real solutions.
&lt;/p&gt;

&lt;p&gt;This is (hopefully) the start of a series of articles giving an
overview of the primitives and tools available on top of the JVM for
solving concurrency-related problems, with code given in Scala and
Java, starting from standard synchronization techniques, going through
low-level primitives and non-blocking algorithms based on
compare-and-set, up to high-level tools, such as Futures/Promises,
actors and optimistic locking with shared transactional memory.&lt;/p&gt;

&lt;!-- read more --&gt;

&lt;h2 id=&quot;the-problem-of-atomicity&quot;&gt;The Problem of Atomicity&lt;/h2&gt;

&lt;p&gt;Over 100,000 people can watch the same soccer game from the same
stadium, at the same time. Those same 100,000 people cannot all take a
dump in the same bathroom at the same time. Writing data to a central
location requires an agreed-upon protocol for establishing who’s
allowed to write and when.&lt;/p&gt;

&lt;p&gt;Most of our concurrency-related problems come from our usage of
&lt;em&gt;mutable data and data-structures&lt;/em&gt;, as both reading and writing are
problematic. When updating a mutable data-structure, the data can get
into an inconsistent state, so threads that are doing the reading can
end-up with garbage. When multiple threads are updating the same
data-structure, the result can be far worse as it can lead to
irrecoverable data corruption.&lt;/p&gt;

&lt;p&gt;To solve the problem, you want updates to seem &lt;em&gt;instantaneous&lt;/em&gt; from
other threads, with no in-between intermediary and inconsistent
state. A piece of code is considered &lt;em&gt;atomic&lt;/em&gt; if it seems
instantaneous to other threads.&lt;/p&gt;

&lt;p&gt;Consider implementing a basic stack. Below is one example in which
many things can go wrong, pointing out a few gotchas off the top of
my head.&lt;/p&gt;

&lt;p&gt;(&lt;a href=&quot;https://github.com/alexandru/multithreading-tutorial/blob/master/src/main/java/JavaSynchronize1.java&quot;&gt;See here for the Java version&lt;/a&gt;)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;/**
  * Class representing nodes in a simple linked list.
  *
  * NOTES:
  *
  * 1. considering this class is used in the context of a stack, we
  *    never need to add or remove from the middle, so there&apos;s no
  *    reason for why this shouldn&apos;t be immutable
  *
  * 2. leaving this class public exposes the internal implementation
  *    of our stack
  *
  */
class Node {
  var value: Any = null
  var next: Node = null
}

/**
  * Totally unsafe, totally screwed implementation of a stack.
  */
class Stack {
  /**
    * Gotcha: leaving our head public, means other threads can mess
    * with the internal state of our stack, even more so because our
    * Node class is mutable.
    */
  var head: Node = null

  def isEmpty = head == null

  def push(value: Any) {
    val node = new Node
    node.value = value
    node.next = this.head
    // Gotcha: by the time we assign the new head, another thread may
    // have changed it already
    this.head = node
  }

  def pop() = {
    if (!isEmpty) {
      // Gotchas:
      //
      // 1. by the time the following is executed the `head` can
      //    already be null
      //
      // 2. two or more threads may read the same `head` and thus
      // receive the same value on pop()
      val node = this.head

      // 1. again, the `head` can already be different, so the
      //    following assignment may lose data
      // 2. the new value may not be visible from other threads
      this.head = node.next
      node.value
    } else {
      null
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The standard way to fix this, as preferred by Java developers, is to
use the &lt;code&gt;synchronize&lt;/code&gt; keyword on all the Stack’s methods. You’ve seen
this before, right?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public synchronized boolean isEmpty() {
  return this.head == null;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;synchronized&lt;/code&gt; keyword creates a &lt;em&gt;monitor lock&lt;/em&gt; (also called an
&lt;em&gt;intrinsic lock&lt;/em&gt;) on the implicit &lt;code&gt;this&lt;/code&gt;. So in case of an instance,
it creates a monitor on that instance. In the case of Java’s &lt;code&gt;static&lt;/code&gt;
methods, it creates a monitor on the class object. It’s important to
keep this in mind, because &lt;code&gt;synchronized&lt;/code&gt; is not some magical tool
that solves every problem you may have and I like that Scala doesn’t
have such a keyword ;-)&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;monitor lock&lt;/em&gt; is guaranteed to be acquired by only a single thread
at the same time. Other threads that try acquiring it in the process
are blocked until the lock is free again.&lt;/p&gt;

&lt;p&gt;Lets improve the above using the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;the Monitor pattern (monitor locks on &lt;code&gt;this&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;encapsulation of internal mutable state&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;Option[T]&lt;/code&gt; instead of nulls (Guava’s &lt;code&gt;Optional&lt;T&gt;&lt;/code&gt; for the Java
version), because that’s how I roll&lt;/li&gt;
  &lt;li&gt;immutable nodes for our internal linked-list&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(&lt;a href=&quot;https://github.com/alexandru/multithreading-tutorial/blob/master/src/main/java/JavaSynchronize2.java&quot;&gt;See here for the Java version&lt;/a&gt;)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;/**
  * Better (mutable) stack implementation.
  *
  * For type-safety, changed the interface to take a type parameter.
  */
class Stack[T] {
  /**
    *
    * Changes:
    * 1. to prevent implementation leaks, nodes in our linked-list
    *    have to be private, including the Node class
    * 2. Node instances are now immutable (always prefer immutable
    *    data structures)
    * 3. never use nulls, prefer proper initialization and Option[T]
    */
  private[this] case class Node(
    value: Option[T],
    next: Option[Node]
  )

  /**
    * The head of our stack.
    *
    * Because the Node class is private, if you make this field
    * public, then the compiler will trigger a compilation error
    */
  private[this] var head: Option[Node] = None

  def isEmpty =
    this.synchronized {
      head.isEmpty
    }

  def push(value: T): Stack[T] = {
    // entering monitor lock
    this.synchronized {
      head = Some(Node(
        value = Option(value),
        next = head
      ))
      this
    }
  }

  def pop(): Option[T] = {
    // Entering monitor lock
    //
    // Note that `isEmpty` is also synchronized, but monitor locks
    // are reentrant so a lock can be acquired multiple times by the
    // same thread.
    this.synchronized {
      if (!isEmpty) {
        val node = head.get
        head = node.next
        node.value
      }
      else
        None
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s better. Not perfect though, as Stacks are the easiest immutable
data-structures to implement … so how about not using any locks at
all? (that’s for another article)&lt;/p&gt;

&lt;h3 id=&quot;the-big-problem-with-locks&quot;&gt;The Big Problem with Locks&lt;/h3&gt;

&lt;p&gt;Take these 2 stacks:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val stack1 = new Stack.push(&quot;World&quot;).push(&quot;Hello&quot;)
val stack2 = new Stack
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Question: is the following thread safe?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;while (!stack1.isEmpty)
  stack2.push( stack1.pop )
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Answer: No. Given that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;code&gt;A&lt;/code&gt; is thread safe&lt;/li&gt;
  &lt;li&gt;
&lt;code&gt;B&lt;/code&gt; is thread safe&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then using &lt;code&gt;A + B&lt;/code&gt; is NOT thread safe, unless you make it so by using
an external lock that protects both at all times.&lt;/p&gt;

&lt;p&gt;Code that’s thread-safe through synchronization based on locks is
&lt;strong&gt;not composable&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;visibility&quot;&gt;The Problem of Visibility&lt;/h2&gt;

&lt;p&gt;When speaking of multithreading, the most obvious problem is the
inconsistency of shared mutable state when being changed and read by
multiple threads at the same time. However the problem is actually
twofold and the &lt;em&gt;atomicity&lt;/em&gt; of code that changes mutable state is not
your only problem.&lt;/p&gt;

&lt;p&gt;Take this piece of code Scala code (
&lt;a href=&quot;https://github.com/alexandru/multithreading-tutorial/blob/master/src/main/java/JavaVisibility1.java&quot;&gt;see here for the Java version&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;var result = &quot;Not Initialized&quot;
var isDone = false

val producer = new Thread(new Runnable {
  def run() {
    result = &quot;Hello, World!&quot;
    isDone = true
  }
})

val consumer = new Thread(new Runnable {
  def run() {
    // loops until isDone is true
    while (!isDone) {}
    println(result)
  }
})

consumer.start()
producer.start()
consumer.join()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; What does the above print?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;Hello, World!&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Not initialized&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Nothing, goes into an infinite loop&lt;/li&gt;
  &lt;li&gt;All of the above&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The answer may surprise some of you. It’s actually number 4, all of
the above. To make matters worse, you can’t predict what happens, as
it depends on the CPU architecture you have, on the number of cores,
on who made the VM, on what other apps you have running, on whether
the laptop is plugged in or not, on planetary alignments and so on.&lt;/p&gt;

&lt;p&gt;So what can happen?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;On most desktops today, most of the time (as in &gt;50%) it will
  behave as expected, which kind of sucks really, because it’s far
  better to have a fast and loud failure than one with subtle effects
  that may or may not manifest when you’re testing the app.&lt;/li&gt;
  &lt;li&gt;The JVM doesn’t guarantee that the instructions are executed in the
  given order. Amongst others, the VM may decide that those
  instructions are independent of each other and may reverse their
  order for things like better cache locality, or because processors
  are pretty smart about executing multi-cycles instructions, being
  able for example to start subsequent instructions before the
  previous ones are finished. So it’s pretty common for the compiler
  to reorder instructions such that longer instructions are executed
  before shorter ones. The processor itself may decide to execute
  instructions out of order, even if the VM/compiler is issuing the
  instructions in the right order. From the point of view of the
  &lt;code&gt;producer&lt;/code&gt; thread, the result is the same as if the instructions
  are executed in the given order, but you can’t rely on it when
  viewing the results from outside threads.&lt;/li&gt;
  &lt;li&gt;The new value for &lt;code&gt;isDone&lt;/code&gt; could be cached somewhere (like in a
  processor register) and the &lt;code&gt;consumer&lt;/code&gt; thread may never see this
  new value. On my desktop in more than 1 out of 10 cases this little
  example goes into an infinite loop.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;happens-before-relationships-and-memory-barriers&quot;&gt;Happens-Before Relationships and Memory Barriers&lt;/h3&gt;

&lt;p&gt;As I was saying at point 2 above, in addition to cached values, you
can also have reordered instructions. Say that you’ve got the
following calls:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;statementA;
statementB;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the point of view of the thread executing these 2 statements, the
result of &lt;code&gt;statementA&lt;/code&gt; is available to &lt;code&gt;statementB&lt;/code&gt;. We call this a
&lt;em&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Happened-before&quot;&gt;happens-before&lt;/a&gt;&lt;/em&gt;
relationship between the two statements. So from the point of view of
the executing thread, the result is always the same as if these 2
statements are executing in order, even if these statements are
executed in fact out of order.&lt;/p&gt;

&lt;p&gt;Outside of the executing thread, this &lt;em&gt;happens-before&lt;/em&gt; relationship is
not guaranteed. The result of &lt;code&gt;statementB&lt;/code&gt; could be visible to other
threads, while the result of &lt;code&gt;statementA&lt;/code&gt; could be made visible later
or &lt;em&gt;never&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In our example, to ensure that &lt;code&gt;isDone&lt;/code&gt; is written after &lt;code&gt;result&lt;/code&gt; and
to ensure the visibility for outside threads for both, you need to
create what is called a
&lt;em&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Memory_barrier&quot;&gt;memory barrier&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The standard way of doing this is (again) through a &lt;em&gt;monitor lock&lt;/em&gt;
acquired on a certain object.&lt;/p&gt;

&lt;p&gt;A synchronization block guarantees two things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;all the writes that happened on other threads on variables, by using
the monitor &lt;code&gt;X&lt;/code&gt;, are visible to our current thread if it acquired
&lt;em&gt;the same monitor&lt;/em&gt; &lt;code&gt;X&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;at the end of the synchronization block, a memory barrier is created
and changes made to variables inside that block will be visible to
other threads that &lt;em&gt;use the same monitor&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To fix our problem with monitor locks, here’s the Scala version (
&lt;a href=&quot;https://github.com/alexandru/multithreading-tutorial/blob/master/src/main/java/JavaVisibility2.java&quot;&gt;see here for the Java version&lt;/a&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;var result = &quot;Not Initialized&quot;
var isDone = false
val lock = new AnyRef

val consumer = new Thread(new Runnable {
  def run() {
    var continueLooping = true

    while (continueLooping)
      lock.synchronized {
        continueLooping = !isDone
      }

    println(result)
  }
})

val producer = new Thread(new Runnable {
  def run() {
    lock.synchronized {
      result = &quot;Hello, World!&quot;
      isDone = true
    } // &lt;-- memory barrier
  }
})

consumer.start()
producer.start()
consumer.join()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There is one big gotcha here. The JVM only guarantees &lt;em&gt;visibility&lt;/em&gt; and
&lt;em&gt;happens-before relationships&lt;/em&gt; only if the threads involved in
reading/writing to our variables are synchronized with the same
monitor lock. This gotcha could happen for a bunch of reasons, for
instance the JVM does escape-analysis and it can get rid of locks
completely if it decides a lock isn’t used concurrently by multiple
threads.&lt;/p&gt;

&lt;h3 id=&quot;volatiles&quot;&gt;Volatiles&lt;/h3&gt;

&lt;p&gt;For this particular example, you actually don’t need a lock at
all. All you need is a &lt;code&gt;volatile&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;@volatile
var isDone = false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or in Java:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;volatile boolean isDone = false;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A write to a &lt;code&gt;volatile&lt;/code&gt; also creates a memory-barrier. If you need
memory barriers, then a write to a volatile on the JVM creates a
&lt;em&gt;full-fence&lt;/em&gt;. This guarantees not only the visibility of &lt;code&gt;isDone&lt;/code&gt;, but
it also guarantees the visibility of all other variables written prior
to it by the same thread, like &lt;code&gt;result&lt;/code&gt; in our example.&lt;/p&gt;

&lt;p&gt;Volatiles are useful sometimes in non-blocking algorithms. But even
with the strong guarantee of the created memory-barrier, for most
purposes where you need volatiles, you’ll end up using atomic
instances from the &lt;code&gt;java.util.concurrent.atomic&lt;/code&gt; package, like
&lt;a href=&quot;http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/atomic/AtomicReference.html&quot;&gt;AtomicReference&lt;/a&gt;
or
&lt;a href=&quot;http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/atomic/AtomicInteger.html&quot;&gt;AtomicInteger&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That’s because you need &lt;strong&gt;compare and set&lt;/strong&gt; for non-blocking
algorithms, an atomic operation that’s optimized on most CPUs today
that you can’t do with plain volatiles.&lt;/p&gt;

&lt;p&gt;But that’s a topic for another article.&lt;/p&gt;

&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;

&lt;p&gt;Checkout the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html&quot;&gt;JSR 133 (Java Memory Model) FAQ&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;
&lt;strong&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0321349601/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0321349601&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;Java Concurrency in Practice&lt;/a&gt;&lt;/strong&gt;
 (affiliate Amazon link)&lt;/li&gt;
&lt;/ul&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2013/03/14/jvm-multithreading-monitor-locks-visibility/?pk_campaign=rss&quot;&gt;JVM Multithreading: Monitor Locks and Visibility&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 14 Mar 2013 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2013/03/14/jvm-multithreading-monitor-locks-visibility/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2013/03/14/jvm-multithreading-monitor-locks-visibility/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Languages</category>
  <category>FP</category>
  <category>Scala</category>
  <category>Java</category>
  <category>Multithreading</category>
  <category>Concurrency</category>
  </item>


<item>
  <title>Notes On JavaScript Client-side Development</title>
  <description>Client-side JavaScript development can be quite overwhelming, even for senior developers. I’m describing here what I did in a recent piece of client-side functionality to keep my sanity. This interface I’m talking about is served on mobile-phones, so it must be pretty bloat-free, adding salt over injury.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2012/11/07/notes-javascript-development/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/javascript.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1280&quot; height=&quot;720&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Client-side JavaScript development can be quite overwhelming, even for
  senior developers. I&apos;m describing here what I did in a recent piece of
  client-side functionality to keep my sanity. This interface I&apos;m
  talking about is served on mobile-phones, so it must be pretty
  bloat-free, adding salt over injury.
&lt;/p&gt;

&lt;h2 id=&quot;dealing-with-modules-packaging-and-minifying&quot;&gt;Dealing with modules, packaging and minifying&lt;/h2&gt;

&lt;p&gt;This is probably my biggest gripe with JavaScript, that you can’t
simply &lt;code&gt;require(&quot;some.namespace&quot;)&lt;/code&gt; without extra glue and tricks. This
is a limitation of the browser, as such operations would have to be
executed asynchronously, requiring tedious callbacks and because of
bandwidth constraints you may want to serve everything in a single
optimized and gzipped JS.&lt;/p&gt;

&lt;!-- read more --&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://brunch.io/&quot;&gt;Brunch.io&lt;/a&gt;&lt;/strong&gt; is an awesome tool that helps you
do that. You split your project in multiple files, then Brunch can do
the assembling for you. To have modules in your project (splitting it
in several files), Brunch works with the
&lt;a href=&quot;http://wiki.commonjs.org/wiki/Modules/1.1&quot;&gt;CommonJS modules&lt;/a&gt;
interface. All that means is that your JavaScript files will end-up
looking like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// for importing another module
utils = require(&quot;path/to/utils&quot;)

function generateRandomString() {
  var userAgent = navigator.userAgent
  var rnd = Math.random() * 100000000
  return utils.md5(userAgent + rnd);
}

// exporting function for consumption from other modules
modules.export = {
  generateRandomString: generateRandomString
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Building changes and seeing them in your browser works really fast, as
Brunch can watch for changes in real-time and also exposes a built-in
server. So Brunch can take care of packaging for all your modules in a
single JS file, also minimizing for production if you want. The
workflow is pretty sweat, the configuration simple.&lt;/p&gt;

&lt;h2 id=&quot;dealing-with-javascripts-syntax-quirks&quot;&gt;Dealing with JavaScript’s Syntax Quirks&lt;/h2&gt;

&lt;p&gt;JavaScript is a capable language exposed by an awful syntax and
plagued by incompatibilities - did you know that placing extra commas
or other punctuation will cause syntax errors in older browsers? So
it’s not just about API incompatibilities, the syntax itself can lead
to surprises.&lt;/p&gt;

&lt;p&gt;Brunch can be configured to check your code with
&lt;a href=&quot;http://www.jshint.com/&quot;&gt;JSHint&lt;/a&gt;, which is a Linter that can check for
syntax errors and you can use it to force upon yourself and your team
certain best practices. It has a lot of
&lt;a href=&quot;http://www.jshint.com/docs/&quot;&gt;configuration options&lt;/a&gt; and for instance
it can trigger errors on uninitialized variables and other
tremendously useful stuff.&lt;/p&gt;

&lt;p&gt;I’ve used &lt;a href=&quot;http://coffeescript.org/&quot;&gt;CoffeeScript&lt;/a&gt; as Brunch can work
with any language, with the proper plugin. I preferred CoffeeScript
because I develop in a more functional style and CoffeeScript has a
lighter syntax for anonymous functions, plus some other fixes to
JavaScript, like “class” or the fat-arrow that binds the defined
function to the current &lt;code&gt;this&lt;/code&gt; (tremendously useful). I coupled
CoffeeScript with &lt;a href=&quot;http://www.coffeelint.org/&quot;&gt;CoffeeLint&lt;/a&gt; and for
instance I disabled the implicit braces when declaring object
literals, as I hate that syntax and don’t want to get sucked into
it. What I really wanted however was
&lt;a href=&quot;http://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;, which is like
JavaScript, but with nice add-ons. Unfortunately it’s too immature and
so
&lt;a href=&quot;https://x.com/brunch/status/253571565923467264&quot;&gt;it isn’t included by Brunch’s authors yet&lt;/a&gt;,
but it probably will be at some point.&lt;/p&gt;

&lt;h2 id=&quot;dealing-with-async-events&quot;&gt;Dealing with Async Events&lt;/h2&gt;

&lt;p&gt;Many people use &lt;a href=&quot;http://backbonejs.org/&quot;&gt;Backbone.js&lt;/a&gt; or things based
on it. What Backbone gives you, besides a structure for your app with
controllers and models, it also gives you a foundation for using the
&lt;a href=&quot;http://en.wikipedia.org/wiki/Observer_pattern&quot;&gt;Observer pattern&lt;/a&gt;. So
your app initiates events that produce data and in response to user
actions or new data, you have to update stuff.&lt;/p&gt;

&lt;p&gt;However my use-case was simple (the interface can be described by a
state-machine, without many things going on as far as the UI is
concerned). And &lt;em&gt;I absolutely hate&lt;/em&gt; this consumer/producer model with
listeners, because I can’t really wrap my head around it even for the
simplest of examples, as this model was really designed for usage
inside an IDE, where you can right-click on components and see all the
registered listeners for certain events.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/kriskowal/q&quot;&gt;The Q library&lt;/a&gt;&lt;/strong&gt; - is one library
I’m using for dealing with &lt;em&gt;future&lt;/em&gt; responses (a promise for a
response that may be available at a later time) and for avoiding the
&lt;a href=&quot;http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/&quot;&gt;Pyramid of Doom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You see, many people choose something like Backbone because it makes
asynchronicity easier to deal with. I chose against it by building
small functions that compose, binding them together with Q. Works
great for small projects, even if the asynchronous calls are difficult
to compose, because working with promises makes that easy - note that
&lt;a href=&quot;https://gist.github.com/3889970&quot;&gt;jQuery’s implementation is broken&lt;/a&gt;,
so don’t use it, just wrap jQuery’s ajax calls in a Q promise.&lt;/p&gt;

&lt;p&gt;Also, the great thing about preferring small functions with
referential transparency that compose is that testing becomes so much
easier. Brunch can also run your tests and you can use something like
&lt;a href=&quot;http://chaijs.com/&quot;&gt;Chai&lt;/a&gt; or other helpers for testing nirvana.&lt;/p&gt;

&lt;p&gt;This doesn’t mean that Backbone and data flows with something like Q
can’t be used together. I can certainly see myself working with
Backbone for larger projects.&lt;/p&gt;

&lt;h2 id=&quot;going-mobile&quot;&gt;Going Mobile&lt;/h2&gt;

&lt;p&gt;Other libraries I’m using are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;http://underscorejs.org/&quot;&gt;Underscore.js&lt;/a&gt;, which provides much
needed API additions, some of which are available in latest versions
of JS, but not on older browsers. You definitely need this if you
like to program in a more functional style&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;http://zeptojs.com/&quot;&gt;Zepto&lt;/a&gt; instead of jQuery, because this
interface is served on mobile phones and jQuery is pretty
bloated. I’ll also probably switch to
&lt;a href=&quot;http://www.jqmobi.com/&quot;&gt;jqMobi&lt;/a&gt; because it’s even lighter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In regards to jQuery alternatives, well jQuery adds like 33KB of
gzipped JavaScript to my download. This may not be an issue in a
browser that has jQuery already cached, but in a fresh
&lt;a href=&quot;http://developer.android.com/reference/android/webkit/WebView.html&quot;&gt;WebView&lt;/a&gt;
it’s really big for normal 3G connections. My final JS file that gets
downloaded only has 20KB of gzipped JS, in total, including the
libraries I mentioned and it won’t grow over 30KB. In combination with
a CDN like &lt;a href=&quot;http://aws.amazon.com/cloudfront/&quot;&gt;CloudFront&lt;/a&gt; that’s
still reasonable.&lt;/p&gt;

&lt;p&gt;The ideal would be to use something like the
&lt;a href=&quot;https://developers.google.com/closure/&quot;&gt;Google Closure&lt;/a&gt; compiler,
which can do tree-shaking, getting rid of pieces of code you don’t
need. However, the code has to follow the Closure conventions,
otherwise it will behave no better than a normal minifier and
libraries like jQuery don’t follow them. That’s why I have high hopes
for &lt;a href=&quot;http://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;, because it has a
built-in dependency system and you can annotate with types even
outside libraries, so a tree-shaker could work for popular libraries
if there’s enough interest, even if the library in question does not
follow any conventions. I also thought about using
&lt;a href=&quot;https://github.com/clojure/clojurescript&quot;&gt;ClojureScript&lt;/a&gt;, which emits
Closure-compatible JavaScript, but I’m not familiar enough with the
language, so maybe some other day :-)&lt;/p&gt;

&lt;h2 id=&quot;as-a-conclusion&quot;&gt;As a conclusion&lt;/h2&gt;

&lt;p&gt;Keep things simple and work with tools provided by the Node.js
community, because that’s where the real action is.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2012/11/07/notes-javascript-development/?pk_campaign=rss&quot;&gt;Notes On JavaScript Client-side Development&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Wed, 07 Nov 2012 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2012/11/07/notes-javascript-development/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2012/11/07/notes-javascript-development/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>JavaScript</category>
  <category>FP</category>
  <category>Browser</category>
  <category>Web</category>
  </item>


<item>
  <title>On Scala, Functional Programming and Type-Classes</title>
  <description>I’ve been following the excellent Coursera course on Functional Programming Principles in Scala led by Martin Odersky. This was not my first encounter with Scala as I’ve been using it including for my day job.
In this article I’m describing my impressions of the Scala programming language and why I fel in love with it.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2012/11/02/scala-functional-programming-type-classes/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/scala.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;675&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I’ve been following the excellent Coursera course on
  &lt;a href=&quot;https://www.coursera.org/course/progfun&quot;&gt;Functional Programming Principles in Scala&lt;/a&gt;
  led by Martin Odersky. This was not my first encounter with Scala as
  I’ve been using it including for my day job. In parallel, because I
  felt the need for a Javascript replacement, I’ve been learning Clojure
  too, because of the excellent ClojureScript.
&lt;/p&gt;

&lt;p&gt;I’ve fallen in love with both and I can’t really pick a favorite. For
what is worth this document represents my (rookie) experience with
Scala, being complete yack shaving on my part, or you could call it
the intellectual masturbation of a fool.&lt;/p&gt;

&lt;!-- read more --&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; as if the article wasn’t long enough, I’ve added to it some
more stuff (like a couple of times :-)&lt;/p&gt;

&lt;h2 id=&quot;1-functional-programming-for-the-win&quot;&gt;1. Functional Programming for the Win&lt;/h2&gt;

&lt;p&gt;It’s not a silver bullet, but on the whole it’s awesome. You really
have to experience it, while leaving aside the preconceptions and
biases you’ve been building up by honing those imperative skills for
years. Students learn functional programing more easily, fresh as they
are, otherwise the learning experience can be painful.&lt;/p&gt;

&lt;p&gt;But we haven’t evolved much in the last 200,000 years and so our brain
finds pleasure mostly in the things that appeal to our inner-animal,
being interested in the means to get laid, eat food, sleep and escape
wild beasts. Learning can be a pleasure, but not when you’re venturing
to unfamiliar grounds, so if you start, hang in there.&lt;/p&gt;

&lt;p&gt;We need some definitions though. Functional programming …&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;deals with computation by evaluating functions with
&lt;a href=&quot;http://en.wikipedia.org/wiki/Referential_transparency_(computer_science)&quot;&gt;referential transparency&lt;/a&gt;
as a property (i.e. functions behave like mathematical functions,
for the same input you must always get the same output)&lt;/li&gt;
  &lt;li&gt;the final output of a computation is composed out of multiple
transformations of your input data, instead of building that
solution by mutating state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A functional programming language is one that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;treats functions as first-class objects, meaning that dealing with
higher-order functions is not only possible, but comfortable&lt;/li&gt;
  &lt;li&gt;gives you the tools needed for &lt;em&gt;composing&lt;/em&gt; functions and types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By that definition languages like Ruby and Javascript can be
considered decent functional languages and they are. However I would
also add:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;has a rich collection of immutable/persistent data-structures (in
general if you want to assess the viability of any programming
language, disregarding the platform it runs on, it’s perfectly
characterized by its basic primitives and data-structures;
e.g. think of C++, Java, or Javascript)&lt;/li&gt;
  &lt;li&gt;exposes a type-system that deals efficiently with the
&lt;a href=&quot;http://en.wikipedia.org/wiki/Expression_problem&quot;&gt;expression problem&lt;/a&gt;;
Rich Hickey calls this “&lt;em&gt;polymorphism a la carte&lt;/em&gt;”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also go to the extreme of specifying that all side-effects
must be modeled with monadic types, but that’s a little too much IMHO,
as only one mostly-mainstream language fits that bill (Haskell).&lt;/p&gt;

&lt;h2 id=&quot;2-is-scala-a-functional-programming-language&quot;&gt;2. Is Scala a Functional Programming Language?&lt;/h2&gt;

&lt;p&gt;Yes it is. You only need to follow the excellent (I mentioned above)
&lt;a href=&quot;https://www.coursera.org/course/progfun&quot;&gt;Coursera course&lt;/a&gt; and solve
the assignments to realize that Scala is indeed a very FP
language. The course was a little short, but a follow-up is
planned. Now move along …&lt;/p&gt;

&lt;h2 id=&quot;3-polymorphism-à-la-carte&quot;&gt;3. Polymorphism À la Carte&lt;/h2&gt;

&lt;p&gt;This is a term that I’ve been hearing from Rich Hickey, when he talks
about open type-systems, referring primarily to Clojure’s Protocols
and Haskell’s Type-Classes.&lt;/p&gt;

&lt;p&gt;These mechanisms for polymorphisms are good solutions for dealing with
the expression problem being in stark contrast with Object-Oriented
Programming as we’ve come to know it from Java and C++.&lt;/p&gt;

&lt;p&gt;OOP is often a closed type-system, especially as used in static
languages. Adding new classes into an existing hierarchy, adding new
functions that operate on the whole hierarchy, adding new abstract
members to interfaces, making built-in types to behave in a certain
way - all of these cases are cumbersome.&lt;/p&gt;

&lt;p&gt;Haskell deals with it through
&lt;a href=&quot;http://en.wikipedia.org/wiki/Type_class&quot;&gt;Type Classes&lt;/a&gt;. Clojure deals
with this through
&lt;a href=&quot;http://en.wikipedia.org/wiki/Multiple_dispatch&quot;&gt;Multi-Methods&lt;/a&gt; and
protocols, protocols being the dynamic equivalent for type-classes in
a dynamic type-system.&lt;/p&gt;

&lt;h2 id=&quot;4-yes-virginia-scala-has-type-classes&quot;&gt;4. Yes Virginia, Scala has Type-Classes&lt;/h2&gt;

&lt;p&gt;So what’s a type class? It’s like an interface in Java, except that
you can make any existing types conform to it without modifying the
implementation of that type.&lt;/p&gt;

&lt;p&gt;As an example, what if we wanted a generic function that can add
things up … you know, like a &lt;code&gt;foldLeft()&lt;/code&gt; or a &lt;code&gt;sum()&lt;/code&gt;, but rather
than specifying how to fold, you want the environment to know how to
do that for each particular type.&lt;/p&gt;

&lt;p&gt;There are several problems with doing this in Java or C#:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;there is no interface defined for “&lt;code&gt;+&lt;/code&gt;” on types that support addition
(like Integers, BigInteger, BigDecimal, floating-point numbers,
strings, etc…)&lt;/li&gt;
  &lt;li&gt;we need to start from some &lt;em&gt;zero&lt;/em&gt; (the list of elements you want to
fold could be empty)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, you can define a type-class, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait CanFold[-T, R] {
  def sum(acc: R, elem: T): R
  def zero: R
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But wait, isn’t this just a simple Java-like interface? Well yes, yes
it is. That’s the awesome thing about Scala - in Scala every instance
is an object and every type is a class.&lt;/p&gt;

&lt;p&gt;So what makes this interface a type-class?
&lt;a href=&quot;http://ropas.snu.ac.kr/~bruno/papers/TypeClasses.pdf&quot;&gt;Objects in combination with implicit parameters&lt;/a&gt;
of course. Let’s look at how we’ll implement our &lt;code&gt;sum()&lt;/code&gt; function that
uses this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B =
  list.foldLeft(adder.zero)((acc,e) =&gt; adder.sum(acc, e))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So if the Scala compiler can find an implicit &lt;code&gt;CanFold&lt;/code&gt; in scope
that’s defined for type A, then it uses it to return a type B. This is
awesomeness on multiple levels:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the implicit defined in scope for type A are establishing the return
type B&lt;/li&gt;
  &lt;li&gt;you can define a CanFold for any type you want, integers, strings,
lists, whatever&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implicits are also scoped so you have to import them. If you want
default implicits for certain types (globally available) you have to
define them in the companion object of the trait &lt;code&gt;CanFold&lt;/code&gt;, like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;object CanFold {
  // default implementation for integers

  implicit object CanFoldInts extends CanFold[Int, Long] {
    def sum(acc: Long, e: Int) = acc + e
    def zero = 0
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And usage is as expected:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;// notice how the result of summing Integers is a Long
sum(1 :: 2 :: 3 :: Nil)
//=&gt; Long = 6
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’m not going to lie to you as this stuff gets hard to learn and while
learning how to do this, you’ll end-up pulling your hair out wishing
for dynamic typing where all of this is not a concern. However you
should distinguish between &lt;em&gt;hard&lt;/em&gt; and &lt;em&gt;complex&lt;/em&gt; (the former is
relative and subjective, the later is absolute and objective).&lt;/p&gt;

&lt;p&gt;One issue with our implementation is when you want to provide a
default implementation for base types. That’s why we’ve made the type
parameter T &lt;em&gt;contravariant&lt;/em&gt; in the &lt;code&gt;CanFold[-T,R]&lt;/code&gt; definition. What
contravariance means is precisely this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;if B inherits from A (B &lt;: A), then
CanFold[A, _] inherits from CanFold[B, _] (CanFold[A,_] &lt;: CanFold[B,_])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This allows us to define a CanFold for any Traversable and it will
work for any Seq / Vector / List and so on.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;implicit object CanFoldSeqs
extends CanFold[Traversable[_], Traversable[_]] {
  def sum(x: Traversable[_], y: Traversable[_]) = x ++ y
  def zero = Traversable()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So this can sum up any kind of &lt;code&gt;Traversable&lt;/code&gt;. The problem is that it
loses the type parameter in the process:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sum(List(1,2,3) :: List(4, 5) :: Nil)
//=&gt; Traversable[Any] = List(1, 2, 3, 4, 5)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the reason for why I mentioned this is hard is because after
pulling my hair out, I had to
&lt;a href=&quot;http://stackoverflow.com/questions/13176697/problems-with-contravariance-in-scala&quot;&gt;ask on StackOverflow&lt;/a&gt;
on how to get a &lt;code&gt;Traversable[Int]&lt;/code&gt; back. So instead of a concrete
implicit object, you can provide an implicit &lt;code&gt;def&lt;/code&gt; that can do the
right thing, helping the compiler to see the type embedded in that
container:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
  def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
  def zero = Traversable()
}

sum(List(1, 2, 3) :: List(4, 5) :: Nil)
//=&gt; Traversable[Int] = List(1, 2, 3, 4, 5)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Implicits are even more flexible than meets the eye. Apparently the
compiler can also work with functions that return the instance you
want, instead of concrete instances. As a side-note, what I did above
is difficult to do, even in Haskell, because sub-typing is involved,
although doing it in Clojure is easy because you simply do not care
about the returned types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE: the above code is not bullet-proof, as conflicts can happen&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Say in addition to a CanFold[Traversable,_] you also define something
for Sets (which are also traversable) …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] {
  def sum(x: Set[A], y: Set[A]) = x ++ y
  def zero = Set.empty[A]
}

sum(Set(1,2) :: Set(3,4) :: Nil)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will generate a conflict error and I’m still looking for a
solution that makes the compiler use the most specific type it can
find, while still keeping that nice contra-variance we’ve got going
(hey, I’m just getting started). The error message looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;both method CanFoldSeqs in object ...
and method CanFoldSets in object ...
match expected type CanFold[Set[Int], B]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s not bad at all as far as error messages go. You could just
avoid being too general and in case you want to override the default
behavior in the current scope, you can shadow the conflicting
definitions:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;{
  // shadowing the more general definition
  // (notice the block, representing its own scope,
  //  so shadowing is local)
  def CanFoldSeqs = null

  // this now works
  sum(Set(1,2) :: Set(3,4) :: Nil)
  //=&gt; Set[Int] = Set(1, 2, 3, 4)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another solution that &lt;code&gt;CanBuildFrom&lt;/code&gt; uses is to define implicits on
multiple levels, such that some implicits take priority over others,
likes so:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;trait LowLevelImplicits {
  implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
    def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
    def zero = Traversable()
  }
}

object CanFold extends LowLevelImplicits {
  // higher precedence over the above
  implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] {
    def sum(x: Set[A], y: Set[A]) = x ++ y
    def zero = Set.empty[A]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And yeah, it will do the right thing. A little ugly though, as it
means you have to have specific knowledge about how these implicits
are prioritized. In essence, this is heavy stuff already and a little
complex too. Good design can make for kick-ass libraries though.&lt;/p&gt;

&lt;h2 id=&quot;5-scalas-collections-library-is-awesome&quot;&gt;5. Scala’s Collections Library is Awesome&lt;/h2&gt;

&lt;p&gt;So what does the above buy you anyway? The following are some examples
from Scala’s own collections library.&lt;/p&gt;

&lt;p&gt;You can sum things up in sequences, as long as you have an
implementation of type-class &lt;code&gt;Numeric[T]&lt;/code&gt; in scope:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;List(1,2,3,4).sum
//=&gt; Int = 10
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can sort things, as long as you have an implementation of
type-class &lt;code&gt;Ordering[T]&lt;/code&gt; in scope:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;List(&quot;d&quot;, &quot;c&quot;, &quot;e&quot;, &quot;a&quot;, &quot;b&quot;).sorted
//=&gt; List[java.lang.String] = List(a, b, c, d, e)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A collection will always do the right thing, returning the same kind
of collection when doing a &lt;code&gt;map()&lt;/code&gt; or a &lt;code&gt;flatMap()&lt;/code&gt; or a &lt;code&gt;filter()&lt;/code&gt;
over it. For instance to revert the keys and values of a Map:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;Map(1 -&gt; 2, 3 -&gt; 4).map{ case (k,v) =&gt; (v,k) }
//=&gt; scala.collection.immutable.Map[Int,Int] = Map(2 -&gt; 1, 4 -&gt; 3)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, if the function you give to &lt;code&gt;map()&lt;/code&gt; above does not return a
pair, then the result is converted to an iterable:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;Map(1 -&gt; 2, 3 -&gt; 4).map{ case (k,v) =&gt; v * 2 }
//=&gt; scala.collection.immutable.Iterable[Int] = List(4, 8)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Even more awesome than this, take for example the &lt;code&gt;BitSet&lt;/code&gt; which is a
compressed &lt;code&gt;Set&lt;/code&gt; of integers (so it’s optimized for storing integers):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import collection.immutable.BitSet

BitSet(1,2,3,4).map(_ + 2)
//=&gt; BitSet = BitSet(3, 4, 5, 6)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Mapping over it still returns a BitSet, as expected. However, look at
what happens when the mapping function returns Strings:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;BitSet(1,2,3,4).map(x =&gt; &quot;number &quot; + x.toString)
//=&gt; Set[java.lang.String] = Set(number 1, number 2, number 3, number 4)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, it did the right thing, because you can’t store Strings in a
BitSet, as BitSets are for integers. So it returned a plain Set of
strings. How is this possible, you may ask?&lt;/p&gt;

&lt;p&gt;The answer is in the
&lt;a href=&quot;http://www.scala-lang.org/api/current/scala/collection/generic/CanBuildFrom.html&quot;&gt;CanBuildFrom&lt;/a&gt;
pattern. The signature of &lt;code&gt;map()&lt;/code&gt; used above is a bit of a mouthful:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def map[B, That](f: (Int) =&gt; B)(implicit bf: CanBuildFrom[BitSet, B, That]): That
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, similar to my example with &lt;code&gt;CanFold&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the compiler takes type B from the mapping function &lt;code&gt;f: (Int) =&gt; B&lt;/code&gt; that’s provided as an argument&lt;/li&gt;
  &lt;li&gt;searches for an implicit in scope of type &lt;code&gt;CanBuildFrom[BitSet, B, _]&lt;/code&gt;
&lt;/li&gt;
  &lt;li&gt;the return type is established as the third type parameter of the implicit that is used&lt;/li&gt;
  &lt;li&gt;the actual building of the result is externalized; the BitSet does
not need to know how to build Sets of Strings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So basically, if you define your own types like so:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;class People extends Traversable[Person] { /* yada yada... */ }
case class Person(id: Int)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then if you want the mapping (or flatMapping) of a BitSet to return a
&lt;code&gt;People&lt;/code&gt; collection in case the function returns &lt;code&gt;Person&lt;/code&gt;, then you
have to implement an implicit object of this type:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;CanBuildFrom[BitSet, Person, People]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then this will work:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;BitSet(1,2,3,4).map(x =&gt; Person(x))
//=&gt; People = People(Person(1), Person(2), Person(3), Person(4))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So what’s great is that the provided implicits for &lt;code&gt;CanBuildFrom&lt;/code&gt; can
be overridden by your own implementations and you can provide
CanBuildFrom implementations for your own types, etc…&lt;/p&gt;

&lt;p&gt;(as a side note, Clojure cannot do conversions based on the given
mapping function, even if the Seq protocol is awesome nonetheless and
doing something akin to CanBuildFrom in Haskell is difficult from what
I’ve been told)&lt;/p&gt;

&lt;p&gt;If you want a lazy
&lt;a href=&quot;http://www.scala-lang.org/api/current/scala/collection/Iterator.html&quot;&gt;Iterator&lt;/a&gt;
(like
&lt;a href=&quot;https://github.com/alexandru/shifter/blob/master/db/src/main/scala/shifter/db/Sql.scala#L83&quot;&gt;if you want to wrap JDBC result-sets&lt;/a&gt;),
you only need to wrap the JDBC result-set in an Iterator by
implementing &lt;code&gt;next()&lt;/code&gt; and &lt;code&gt;hasNext&lt;/code&gt;. You then get
&lt;code&gt;filter()&lt;/code&gt;/&lt;code&gt;map()&lt;/code&gt;/&lt;code&gt;flatMap()&lt;/code&gt; for free, but with a twist - Iterators
are lazy and can only be traversed once. Applying filter/map/flatMap
will not traverse the Iterator, being lazy operations. To convert this
into a lazy sequence that also memoizes (stores) the results for
multiple traversals, you only need to do &lt;code&gt;iterator.toStream&lt;/code&gt;, or to
get all the results at once &lt;code&gt;iterator.toList&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.scala-lang.org/api/current/scala/collection/immutable/Stream.html&quot;&gt;Streams&lt;/a&gt;
in Scala are lazy sequences. You can easily implement infinite lists
of things, like Fibonacci numbers or the digits of PI or
something. But Streams are not the only lazy collections, Scala also has
&lt;a href=&quot;http://www.scala-lang.org/docu/files/collections-api/collections_42.html&quot;&gt;Views&lt;/a&gt;
and you can transform any collection into a corresponding view, including Maps.&lt;/p&gt;

&lt;p&gt;But that’s not all. Scala also has implementations of collections that
do things in parallel. Here’s how to calculate if a number is prime,
sequentially:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;import math._

def isPrime(n: Int) = {
  val range = 2 to sqrt(abs(n)).toInt
  ! range.exists(x =&gt; n % x == 0)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have multiple cores around doing nothing, here’s how to
calculate it by putting those extra cores at work:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def isPrime(n: Int) = {
  val range = 2 to sqrt(abs(n)).toInt
  ! range.par.exists(x =&gt; n % x == 0)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice the difference?&lt;/p&gt;

&lt;h2 id=&quot;6-is-this-complex&quot;&gt;6. Is this complex?&lt;/h2&gt;

&lt;p&gt;I mentioned above that this stuff is not complex, it’s just
hard. Scala does have complexities when it comes to really advanced
use-cases, as can be seen in this article:
&lt;a href=&quot;http://yz.mit.edu/wp/true-scala-complexity/&quot;&gt;True Scala Complexity&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s worth mentioning however that, as Martin Odersky noted in the
Hacker News thread of that article, the author tries to accomplish
something that’s not possible in most languages out there, while a
solution is still possible in Scala (albeit with small limitations).&lt;/p&gt;

&lt;h2 id=&quot;7-are-oop-features-getting-in-the-way&quot;&gt;7. Are OOP Features Getting in the Way?&lt;/h2&gt;

&lt;p&gt;I happen to disagree and I actually love the blend of OOP with
functional features. Martin Odersky claims that OOP is orthogonal to
functional programming. But if you pay attention, you’ll notice it’s
not only orthogonal, but complementary in an elegant way.&lt;/p&gt;

&lt;p&gt;I’m indicating below instances where I think OOP helps, but as a clear
example of what the combination can do, consider Scala’s
&lt;a href=&quot;http://www.scala-lang.org/api/current/scala/collection/immutable/Set.html&quot;&gt;Set&lt;/a&gt;. A
&lt;code&gt;Set[T]&lt;/code&gt; can be viewed as a function that takes a parameter of type T
and returns either True if the value is in the Set, or False
otherwise. This means you can do this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;val primaryColors = Set(&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;)

val colors = List(&quot;red&quot;, &quot;purple&quot;, &quot;yellow&quot;, &quot;vanilla&quot;, &quot;white&quot;, &quot;black&quot;, &quot;blue&quot;)

colors.filter(primaryColors)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is possible because our set is in fact a subtype of
&lt;code&gt;Function1[String, Boolean]&lt;/code&gt;, so you can pass it to any higher-order
function that expects that signature.&lt;/p&gt;

&lt;p&gt;But the similarity goes deeper than simple resemblance and syntactic
sugar. If you remember from school, a mathematical Set can be perfectly
described by what is called a
&lt;a href=&quot;http://en.wikipedia.org/wiki/Indicator_function&quot;&gt;characteristic function&lt;/a&gt;,
so Sets are interchangeable with functions in mathematics.&lt;/p&gt;

&lt;p&gt;This means operations on Sets like &lt;em&gt;unions&lt;/em&gt;, &lt;em&gt;intersections&lt;/em&gt;,
&lt;em&gt;complements&lt;/em&gt;, &lt;em&gt;Cartesian products&lt;/em&gt; and so on can be replaced with
operations on functions and that’s exactly what
&lt;a href=&quot;http://en.wikipedia.org/wiki/Boolean_algebra&quot;&gt;boolean algebra&lt;/a&gt; is
about. In mathematical terms, these mathematical structures (sets and
functions that take an argument and return 0/1) are equivalent
(indistinguishable) because there exists an isomorphism between them,
savvy? :-)&lt;/p&gt;

&lt;p&gt;And I don’t know how Haskell handles this for &lt;code&gt;Data.Set&lt;/code&gt;, or if it
handles it at all, but OOP subtyping seems like the easiest way to
model something like this in a static language …&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;for one, the hierarchy is simple to understand, simple to model, as subtyping is something that OOP simply does -
you just inherit from &lt;code&gt;Function1[-T, +R]&lt;/code&gt; - and you’re done&lt;/li&gt;
  &lt;li&gt;downcasting to a function is something OOP simply does - you just
pass your object to something that expects a function and you can forget the original type of that value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is just a small and insignificant example of course, like most
examples I’m giving here, but to me properly done OOP (where every
type is modeled with classes and every value is some kind of object)
just feels right … I like this principle of “&lt;em&gt;turtles all the way
down&lt;/em&gt;”, even if you could probably point to things that aren’t
“turtles”, but this also happens in languages that are the epitome of
kick-ass turtles-recursion, like Scheme or Smalltalk.&lt;/p&gt;

&lt;h2 id=&quot;8-scala-versus-haskell&quot;&gt;8. Scala versus Haskell&lt;/h2&gt;

&lt;p&gt;Scala’s static type-system is sometimes less expressive than that of
Haskell. In particular Haskell supports
&lt;a href=&quot;https://en.wikibooks.org/wiki/Haskell/Polymorphism#Higher_rank_types&quot;&gt;rank-2 polymorphism&lt;/a&gt;,
while Scala only rank-1. One point that Scala wins over Haskell is
definitely this one:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;List(1,2,3,4,5).flatMap(x =&gt; Option(x))
//=&gt; List[Int] = List(1, 2, 3, 4, 5)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Doing the above in Haskell (using the &lt;code&gt;bind&lt;/code&gt; operator) triggers a
compile-time error, because the return type of the mapping function is
expected to be of type &lt;code&gt;List&lt;/code&gt; and the &lt;code&gt;Maybe&lt;/code&gt; type (the equivalent of
&lt;code&gt;Option&lt;/code&gt;) is not a &lt;code&gt;List&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Option&lt;/code&gt; in Scala is not a collection, but it is &lt;em&gt;viewable&lt;/em&gt; as a
collection of either 0 or 1 elements. As a consequence, because of
good design decisions, the monadic types defined in Scala’s collection
library are more composable.&lt;/p&gt;

&lt;p&gt;EDIT: this example is simple and shallow. As pointed out in the
comments, it’s easy to make the conversion by yourself, however I’m
talking about the design choices of Scala’s library and the
awesomeness of implicits. As a result, the standard monadic types
provided by Scala (all collections, Futures, Promises, everything that
has a filter/map/flatMap, etc…) are inherently more composable and
friendlier.&lt;/p&gt;

&lt;p&gt;It’s also worth pointing out that Scala’s collections library is so
awesome precisely because OOP plays a part and there are cases where
doing similar things in Haskell require experimental GHC extensions.&lt;/p&gt;

&lt;p&gt;For instance, all of the collections in Scala share code in one way or
another. If you want to build your own
&lt;a href=&quot;http://www.scala-lang.org/api/current/scala/collection/Traversable.html&quot;&gt;Traversable&lt;/a&gt;
you only have to implement that trait with the abstract &lt;code&gt;foreach()&lt;/code&gt;,
but you get all other methods, including
&lt;code&gt;filter()&lt;/code&gt;/&lt;code&gt;map()&lt;/code&gt;/&lt;code&gt;flatMap()&lt;/code&gt; for free. As a side-effect your
collection will be a monadic type by default.&lt;/p&gt;

&lt;p&gt;Haskell is lazy by default. This is good for many problems. In Scala
lazyness is a choice. In Haskell this lazyness is awesome, but in my
experience while playing with it, it gets very hard to reason about
the resulting performance. Sometimes it’s fast without you doing
anything, other times - well, profiling and fixing performance issues
in Haskell is not for mortals. Scala is more predictable, being strict
and lazy when needed. It also has at its disposal the awesome JVM
ecosystem for profiling and monitoring.&lt;/p&gt;

&lt;h2 id=&quot;9-scala-versus-f--ocaml&quot;&gt;9. Scala versus F# / Ocaml&lt;/h2&gt;

&lt;p&gt;F# is good if you want to use C# 2020. But F# has rough edges
inherited from Ocaml, while it has not inherited all the benefits. F#
has nominative typing, instead of structural typing for OOP (as
Ocaml). And you really start wishing for an ad-hoc polymorphism
mechanism in which the types are open.&lt;/p&gt;

&lt;p&gt;In regards to how one implements &lt;code&gt;CanFold&lt;/code&gt; F# takes the crown as the
ugly ducklin’ as it follows the (really screwed) C# conventions of
defining “&lt;code&gt;+&lt;/code&gt;” as static functions on classes (a reminiscence of C++
btw), so even if you know that a T is an Integer, you can’t sum 2
Integers based on the interface definition alone, because the compiler
cannot make the connection to &lt;code&gt;T + T&lt;/code&gt;, as in OOP interfaces/subtyping
only applies to instances, not classes and “static members”. This is
why they had to extend the language. Take a look at the signature for
&lt;code&gt;List.sum&lt;/code&gt; in F#:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot;&gt;List.sum : ^T list -&gt; ^T (requires
  ^T with static member (+) and ^T with static member Zero)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First of all, this is bad from all perspectives, as it uses the
(really fucked up) notion of “&lt;em&gt;static members&lt;/em&gt;” that should have never
happened in OOP. It’s also not a type-class as it is &lt;em&gt;not open&lt;/em&gt; - you
cannot modify a built-in type to have the required static members,
being the same problem you get with classic OOP inheritance of
interfaces. You also cannot override the implementation, as you’d wish
in certain contexts.&lt;/p&gt;

&lt;p&gt;In Scala there is no such thing as “&lt;em&gt;static members&lt;/em&gt;”, “&lt;code&gt;+&lt;/code&gt;”
operations being plain polymorphic instance methods.&lt;/p&gt;

&lt;p&gt;The one thing I really like about
&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd233212.aspx&quot;&gt;F# are quotations&lt;/a&gt;,
which give you
&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb308959.aspx&quot;&gt;.NET LINQ&lt;/a&gt;,
with the difference that quotations in F# are more potent than what C#
can do. In simple words, quotations in F# give you the possibility of
repurposing/recompiling pieces of code at runtime (e.g. macros).&lt;/p&gt;

&lt;p&gt;But &lt;a href=&quot;http://scalamacros.org/&quot;&gt;macros support&lt;/a&gt; is an upcoming feature
of Scala 2.10, which is already at RC1 and you can play around with
the up-coming &lt;a href=&quot;http://slick.typesafe.com/&quot;&gt;Scala version of LINQ&lt;/a&gt;
right now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ocaml&lt;/strong&gt; goes a long way with its structural typing for OOP. Ocaml
has the most advanced type-inferencer out of the popular functional
languages, being more advanced than the one in Haskell. It’s a potent
language, but sadly it has no equivalent for type-classes.&lt;/p&gt;

&lt;p&gt;The right way to implement &lt;code&gt;CanFold&lt;/code&gt; in Ocaml/SML would be to
explicitly pass a dictionary of pointers around, as described here:
&lt;a href=&quot;http://okmij.org/ftp/ML/ML.html#typeclass&quot;&gt;Typeclass overloading and bounded polymorphism in ML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Scala, unlike Ocaml and F#, does not have 2 type-systems in the same
language, as Scala follows the “&lt;em&gt;uniform access
principle&lt;/em&gt;”. Type-classes and algebraic data-types are still modeled
by means of OOP classes and objects.&lt;/p&gt;

&lt;p&gt;Why does it matter? If you ever worked with C++ you can understand
this - if OOP is pervasive in your language and not just something
completely optional, then every type in the system should be
(or considered) polymorphic and extending from some Object,
otherwise you’ll end up with lots and lots of pain. It’s also a matter
of having to make choices.&lt;/p&gt;

&lt;p&gt;In Scala the code is indeed more verbose, but it reduces complexity a
lot because a big part of learning Ocaml is learning when OOP is
appropriate, or not, as you have to pick from the get-go and combining
approaches is very cumbersome.&lt;/p&gt;

&lt;p&gt;Take for instance the definition of an immutable and persistent
List. A List can be defined efficiently as an algebraic data-type,
being either an Empty List, or a Pair of 2 elements, the head and the
tail, right?&lt;/p&gt;

&lt;p&gt;In Ocaml:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ocaml&quot;&gt;type &apos;a my_list = Nil | List of &apos;a * &apos;a my_list
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Extremely elegant and simple. And in Scala:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed abstract class List[+T]
case class Pair[+t](head: T, tail: List[T]) extends List[T]
case object Nil extends List[Nothing]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What a mouthful.&lt;/p&gt;

&lt;p&gt;One difference should immediately be noticeable, our &lt;code&gt;List&lt;/code&gt; has
covariant behavior, meaning that a &lt;code&gt;List[String]&lt;/code&gt; is also a
&lt;code&gt;List[Any]&lt;/code&gt;, or a &lt;code&gt;List[j.u.HashMap]&lt;/code&gt; is also a
&lt;code&gt;List[j.u.AbstractMap]&lt;/code&gt;. Arrays in Java have the same behavior and
this leads to lots of gotchas, but if our List is immutable, then this
is not a problem, but a bonus. For instance this gives you polymorphic
behavior without needing type parameters or higher-kinded types or
other mechanisms, just plain OOP subtyping relationships:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def length(list: List[Any]) = list match {
   case Pair(head, tail) = 1 + length(tail)
   case Nil =&gt; 0
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;However, that’s not efficient. A much better approach is to make
&lt;code&gt;length()&lt;/code&gt; polymorphic (in the OOP sense), after all &lt;code&gt;length()&lt;/code&gt; is a
defining property of Lists, so there’s no reason for why it shouldn’t
be there:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;sealed abstract class List[+T] {
  // abstract definition
  def length: Int
}

case class Pair[+T](head: T, tail: List[T]) extends List[T] {
  val length = 1 + tail.length
}

case object Nil extends List[Nothing] {
  val length = 0
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, isn’t that nice? What would it take to turn this into a lazy
list?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;case class Pair[+T](head: T, tail: () =&gt; List[T]) extends List[T] {
  lazy val length = 1 + tail().length
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can see how &lt;code&gt;length&lt;/code&gt; hasn’t changed for either &lt;code&gt;List[T]&lt;/code&gt; or for
&lt;code&gt;Nil&lt;/code&gt;, just for &lt;code&gt;Pair&lt;/code&gt;, which makes it a good candidate for OOP. So
why not model this with OOP in Ocaml? Because for algebraic
data-types, the compiler helps you, like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;def sum(list: List[Int]): Int = list match {
   case Pair(head, tail) =&gt; head + sum(tail)
   //-&gt; oops, no termination
}

//-&gt; output from the compiler ...
warning: match is not exhaustive!
missing combination            Nil

       def sum(list: List[Int]): Int = list match {
	                                   ^
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Did I mention Scala also has structural typing if you want it? Yes it
can (albeit, without the awesome type-inferencing that Ocaml is
capable of and it’s mostly based on runtime reflection):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;type Closeable = { def close():Unit }

def using[A, B &lt;: Closeable](closable: B)(f: B =&gt; A): A =
  try {
    f(closable)
  }
  finally {
    closable.close()
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This comparisson isn’t really fair btw, because I’ve been fixating on
issues that Scala does really well. Ocaml is great, however I
personally find it limiting and awkward at the edges of the 2 type
systems it contains. Or maybe I’m just a spoiled brat.&lt;/p&gt;

&lt;h2 id=&quot;10-static-type-versus-dynamic-type-systems&quot;&gt;10. Static-type versus Dynamic-type Systems&lt;/h2&gt;

&lt;p&gt;Static versus dynamic is what polarizes developers most in separate
camps. It’s like a never-ending flamewar, with healthy dosages of
religiosity.&lt;/p&gt;

&lt;p&gt;At its core, a static type system helps you by providing proof at
compile-time that the types you’re using behave as you expect them to
behave (note I’m speaking of types, not instances). This is good,
because you need all the help you can get and static typing can
eliminate a lot of errors.&lt;/p&gt;

&lt;p&gt;This is a doubly-edged sword though. By definition a static type
system will reject pieces of code that are perfectly correct. Also,
it’s not a silver bullet, as Rich Hickey said in his excellent
&lt;a href=&quot;http://www.infoq.com/presentations/Simple-Made-Easy&quot;&gt;Simple Made Easy&lt;/a&gt;
talk: “&lt;em&gt;What’s the common thing that all bugs in the wild share? They
passed the type-checker, they passed all the tests!&lt;/em&gt;”&lt;/p&gt;

&lt;p&gt;I’ve seen opinions that “&lt;em&gt;structural typing&lt;/em&gt;” or “&lt;em&gt;type-inference&lt;/em&gt;”
are as good as “&lt;em&gt;duck typing&lt;/em&gt;”. That couldn’t be further from the
truth - the real power of duck typing comes from the ability to create
/ modify types and functions on the fly at runtime. In other words you
can make shit up and as long as it’s correct, then it works. In
contrast, a static type system actively rejects pieces of code if it
can’t prove that the types you’re using support the computation you’re
trying to do, so no matter how smart the type system is, you’ll always
end up in lots of instances where you have to spoon-feed the compiler
to allow you to do what &lt;em&gt;you mean&lt;/em&gt; (n.b. not all compilers are equal).&lt;/p&gt;

&lt;p&gt;This is not to say that static typing is bad. Well, it is bad in
languages where the type system is designed to help the IDE and not
the developer (e.g. Java, Delphi, Visual Basic). Otherwise, especially
in combination with referential transparency, it really eliminates a
whole class of errors.&lt;/p&gt;

&lt;p&gt;Here we define &lt;em&gt;an error&lt;/em&gt; as being an incorrect state of the
computation or corrupted output that takes the developers by
surprise. An exceptional state that’s being controlled is not an
error. This is why Haskell makes such a big fuss out of dealing with
side-effects by means of monadic types - because it makes you think
about exceptional state and either deal with it, or make it somebody
else’s problem.&lt;/p&gt;

&lt;p&gt;Thinking of Scala versus Clojure and Haskell, in regards to its
static-type system Scala sits somewhere in the middle. This is both
good and bad. On one hand Scala does not have the same (static)
expressive capabilities of Haskell, being a poor substitute for it
when working with higher-kinded types. On the other hand you can
&lt;a href=&quot;https://alexn.org/blog/2012/07/02/love-scala.html&quot;&gt;drill holes&lt;/a&gt;
in that static-type system to make it do what you want, which I think
is a good trade-off.&lt;/p&gt;

&lt;p&gt;I personally lean towards dynamic type systems, however the tradeoffs
I end up making in Scala are worth it for the extra type safety it
brings. On the other hand Clojure, because of its support for
multi-methods and protocols and macros, is a dynamic language that’s
more expressive than most other languages, including dynamic ones,
especially the mainstream, like Python, Ruby, Perl, Javascript or PHP.&lt;/p&gt;

&lt;h2 id=&quot;11-performance&quot;&gt;11. Performance&lt;/h2&gt;

&lt;p&gt;I don’t have any experience or proof on this, just personal feelings :-)&lt;/p&gt;

&lt;p&gt;Scala runs on top of the JVM. When using closures or immutable
data-structures, it is wasteful. However there are a few things to
consider:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Scala can be as low-level and as efficient as Java for the hot
codepaths and low-level Scala code is still higher-level than Java
(for instance the pimp-my-library pattern will have 0 overhead
starting with Scala 2.10, while implicit parameters are
compile-time)&lt;/li&gt;
  &lt;li&gt;the built-in immutable data-structures are optimized to be versioned
/ to reuse memory of prior states - just as when adding a new
element to a List the old reference gets used as the tail, this
also happens with Vectors and Maps - they are still less efficient
than Java’s collections, but it’s a good tradeoff as these
data-structures can be used without read-locks, so bye, bye
lock-contention of threads&lt;/li&gt;
  &lt;li&gt;Scala creates lots of short lived objects. This can stress the
garbage collector, but on the other hand the JVM has the most
advanced garbage collectors available, so you shouldn’t worry about
it unless profiling tools tell you to … for instance on the JVM
heap allocation is as cheap as stack allocation, it can also do some
escape analysis to get rid of some locks and to allocate some
short-lived objects on the stack and deallocation of short-lived
objects is cheap, because the GC is generational so it deallocates
whole chucks of memory at once instead of individual references
… so why worry about it?&lt;/li&gt;
  &lt;li&gt;the only instance to be concerned about is if you’re building on top
of Android, as Android does not have a JVM - but even there, Scala
is workable (or so I’ve heard)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;12-tools-of-the-trade&quot;&gt;12. Tools of the Trade&lt;/h2&gt;

&lt;p&gt;I have a love/hate relationship with SBT, the defacto builds manager
for Scala, the replacement for Maven, the slayer of XML files.&lt;/p&gt;

&lt;p&gt;The syntax is really weird and leads to cargo-culting. It broke
compatibility and so many examples available online are out of
date. When you’re reading the
&lt;a href=&quot;http://www.scala-sbt.org/release/docs/Getting-Started/Welcome.html&quot;&gt;Getting Started&lt;/a&gt;
tome, it describes something about immutable data-structures, settings
options that are either lazy or strict, how to transform values with a
&lt;code&gt;~=&lt;/code&gt; operator, something about another operator written as &lt;code&gt;&lt;&lt;=&lt;/code&gt; and
so on.&lt;/p&gt;

&lt;p&gt;Comparing this to how you work with Ruby Gems / Rake and Bundler is
simply not fun. Only a mother could love this syntax.&lt;/p&gt;

&lt;p&gt;Then I’ve already had problems with its Ivy integration, not being
able to solve some dependencies. Thankfully I could find a fix.&lt;/p&gt;

&lt;p&gt;On the other hand it’s really pragmatic and I prefer it over Maven,
even if the Scala Maven plugin is in really good shape right now. Here
are some highlights of SBT:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;it can do cross-builds between multiple Scala versions; as is well
known, major Scala versions are breaking binary compatibility, so if
you want your library to support multiple Scala versions then SBT is
a must, as it makes cross-building a breeze (it’s almost too easy)&lt;/li&gt;
  &lt;li&gt;it’s well integrated with ScalaTest, being able of continous
compilation and testing, with output in colors - a really good tool
for TDD&lt;/li&gt;
  &lt;li&gt;it makes it easy to deal with multiple sub-projects in the same root
project, sub-projects that can be worked-on, tested or published
individually or as a whole&lt;/li&gt;
  &lt;li&gt;all Scala projects have instructions for SBT first, Maven second and
missing instructions for everything else - this is particularly
painful if you’re dealing with plugins (like doing precompilation of
templates with Scalate or something)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use Emacs.&lt;/p&gt;

&lt;p&gt;IDEs are not on the same level as Java. But I tried out
&lt;a href=&quot;http://blog.jetbrains.com/scala/&quot;&gt;IntelliJ IDEA’s Scala plugin&lt;/a&gt; and
it’s quite decent, with refactoring, intellisense and everything
nice. An Eclipse plugin is also available, developed now by TypeSafe,
however last time I tried, it was unstable.&lt;/p&gt;

&lt;p&gt;So IDEs for Scala are in a worst shape than for Java, but on the other
hand these IDEs are functional and completely awesome when compared to
what you get by picking other functional languages, except maybe F#.&lt;/p&gt;

&lt;p&gt;With Scala you can use all the profiling and monitoring tools and
classpath reloading tricks that you can use with Java. Nothing’s
stopping you, as every tool meant for the JVM also works with Scala.&lt;/p&gt;

&lt;h2 id=&quot;13-concurrency-and-parallelism&quot;&gt;13. Concurrency and Parallelism&lt;/h2&gt;

&lt;p&gt;It’s enough to say that Scala doesn’t restrict you in any way:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;http://akka.io/&quot;&gt;Light-weight actors&lt;/a&gt; that can process tons of messages (Erlang-style)
and that work either on the same machine, in a single process, or
distributed over a network&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;http://doc.akka.io/docs/akka/2.0.1/scala/futures.html&quot;&gt;Futures and Promises&lt;/a&gt;,
which in contrast to other languages (* cough * javascript / jquery * cough *)
are properly implemented as monadic types&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;http://nbronson.github.com/scala-stm/&quot;&gt;Software transactional memory&lt;/a&gt;, as in Clojure&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://docs.scala-lang.org/overviews/parallel-collections/overview.html&quot;&gt;Parallel collections&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
&lt;a href=&quot;http://doc.akka.io/docs/akka/snapshot/scala/dataflow.html&quot;&gt;Async/await as in C#&lt;/a&gt;, though it requires a compiler plugin&lt;/li&gt;
  &lt;li&gt;The awesome Java NIO, along with Netty, Mina and the whole ecosystem
for async I/O (you don’t know what pleasure feels like until you
wrap &lt;a href=&quot;https://github.com/AsyncHttpClient/async-http-client&quot;&gt;Async-Http-Client&lt;/a&gt;
in Akka Promises which you can combine in for-comprehensions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically Scala has it all. This may seem like a curse, but what other
languages define as built-in / hard to change / hard to evolve
features, Scala defines as libraries. So there are definitely upsides ;-)&lt;/p&gt;

&lt;h2 id=&quot;14-learning-resources&quot;&gt;14. Learning Resources&lt;/h2&gt;

&lt;p&gt;I’ve found the following to be good resources for learning Scala (note
that Amazon links have my affiliate tag, but if you want the eBook
version don’t buy from Amazon, prefer buying directly from the
publisher, as you’ll get both a DRM-free Kindle version and a PDF):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.coursera.org/course/progfun&quot;&gt;Functional Programming Principles in Scala&lt;/a&gt;&lt;/strong&gt;,
already mentioned, is an excellent course provided by Coursera / EPFL,
taught by Martin Odersky. The course is almost over, but the material
will be left online, which means you can follow the lectures and do
the assignments and I’m pretty sure many students that attended will
remain on that forum for answering questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://twitter.github.com/scala_school/&quot;&gt;Scala School&lt;/a&gt;&lt;/strong&gt;: a freely
available online tutorial by Twitter, which is very friendly to
newbies. I’ve read it and it’s pretty good.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://docs.scala-lang.org/&quot;&gt;Scala Documentation Project&lt;/a&gt;&lt;/strong&gt;:
definitely checkout this website, as they aggregate everything good
here. If you want to learn more about Scala’s library, especially the
collections, this is the place to learn from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://aperiodic.net/phil/scala/s-99/&quot;&gt;Ninety-Nine Scala Problems&lt;/a&gt;&lt;/strong&gt;: a collection of 99 problems to be solved with Scala. If you get
stuck, you can view a solution which is often idiomatic. See also this
&lt;a href=&quot;https://github.com/etorreborre/s99&quot;&gt;GitHub project&lt;/a&gt; that gives you a
complete test-suite, to spare you of the effort.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/B004Z1FTXS/ref=as_li_ss_il?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B004Z1FTXS&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/programming-scala.jpg&quot; align=&quot;left&quot; style=&quot;max-width:100%;height:auto;&quot; class=&quot;left&quot; loading=&quot;lazy&quot; width=&quot;379&quot; height=&quot;500&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.amazon.com/gp/product/B004Z1FTXS/ref=as_li_ss_il?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B004Z1FTXS&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;&lt;b&gt;Programming in Scala&lt;/b&gt;&lt;/a&gt;
by Martin Odersky is a good book on programming, not just Scala - many
of the exercises in
&lt;a href=&quot;http://mitpress.mit.edu/sicp/&quot;&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;
are also present in this book, giving you the Scala-approach for
solving those problems, which is good.&lt;/p&gt;

&lt;div class=&quot;clear&quot; style=&quot;clear: both; &quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0321774094/ref=as_li_ss_il?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0321774094&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/scala-for-the-impatient.jpeg&quot; align=&quot;left&quot; style=&quot;max-width:100%;height:auto;&quot; class=&quot;left&quot; loading=&quot;lazy&quot; width=&quot;495&quot; height=&quot;648&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.amazon.com/gp/product/0321774094/ref=as_li_ss_il?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0321774094&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;&lt;b&gt;Scala for the Impatient&lt;/b&gt;&lt;/a&gt;
by Cay S. Horstmann, is a good pragmatic book on Scala (not so much on
functional programming), but it’s for developers experienced in other
languages, so it’s fast-paced while not scaring you away with endless
discussions on types (like I just did). The PDF for the first part (out of 3) is
available from the
&lt;a href=&quot;http://typesafe.com/resources/free-books&quot;&gt;Typesafe website&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;clear&quot; style=&quot;clear: both; &quot;&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/1935182706/ref=as_li_ss_il?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1935182706&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/scalaindepth.png&quot; align=&quot;left&quot; style=&quot;max-width:100%;height:auto;&quot; class=&quot;left&quot; loading=&quot;lazy&quot; width=&quot;495&quot; height=&quot;621&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.amazon.com/gp/product/1935182706/ref=as_li_ss_il?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1935182706&amp;linkCode=as2&amp;tag=bionicspirit-20&quot;&gt;&lt;b&gt;Scala in Depth&lt;/b&gt;&lt;/a&gt;
by Joshua Suereth D. - this is an advanced book on Scala, with many
insights into how functional idioms work in it. I’ve yet to finish
reading, as it’s not really an easy lecture. But it’s a good book. Get
the eBook straight from &lt;a href=&quot;http://www.manning.com/suereth/&quot;&gt;Manning&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;clear&quot; style=&quot;clear: both; &quot;&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-end-finally&quot;&gt;The End, Finally&lt;/h2&gt;

&lt;p&gt;A sequel on what makes Clojure great will follow when I have the time
or patience for it (or once I finish reading the
&lt;a href=&quot;http://joyofclojure.com/&quot;&gt;Joy of Clojure&lt;/a&gt;, great book btw).&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2012/11/02/scala-functional-programming-type-classes/?pk_campaign=rss&quot;&gt;On Scala, Functional Programming and Type-Classes&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 02 Nov 2012 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2012/11/02/scala-functional-programming-type-classes/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2012/11/02/scala-functional-programming-type-classes/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Languages</category>
  <category>FP</category>
  <category>Scala</category>
  </item>


<item>
  <title>How To Build a Naive Bayes Classifier</title>
  <description>In machine learning a classifier is able to predict, given an input, a probability distribution over a set of categories. Some use-cases for building a classifier: spam detection, for example you could build your own Akismet API, automatic assignment of categories to a set of items, automatic detection of the primary language (e.g. Google Translate), sentiment analysis, which in simple terms refers to discovering if an opinion is about love or hate about a certain topic.</description>
  <content:encoded>&lt;p class=&quot;intro&quot;&gt;
  In machine learning a classifier is able to predict, given an input, a probability distribution over a set of categories. Some use-cases for building a classifier:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Spam detection, for example you could build your own
&lt;a href=&quot;https://akismet.com/&quot;&gt;Akismet&lt;/a&gt; API&lt;/li&gt;
  &lt;li&gt;Automatic assignment of categories to a set of items&lt;/li&gt;
  &lt;li&gt;Automatic detection of the primary language (e.g. Google Translate)&lt;/li&gt;
  &lt;li&gt;Sentiment analysis, which in simple terms refers to discovering if
an opinion is about love or hate about a certain topic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general you can do a lot better with more specialized techniques,
however the Naive Bayes classifier is general-purpose, simple to
implement and good-enough for most applications. And while other
algorithms give better accuracy, in general I discovered that having
better data in combination with an algorithm that you can tweak does
give better results for less effort.&lt;/p&gt;

&lt;p&gt;In this article I’m describing the math behind it. Don’t fear the
math, as this is simple enough that a high schooler understands. And
even though there are a lot of libraries out there that already do
this, you’re far better off for understanding the concept behind it,
otherwise you won’t be able to tweak the implementation in response to
your needs.&lt;/p&gt;

&lt;h2 id=&quot;0-the-source-code&quot;&gt;0. The Source Code&lt;/h2&gt;

&lt;p&gt;I published the source-code associated at
&lt;a href=&quot;https://github.com/alexandru/stuff-classifier&quot;&gt;github.com/alexandru/stuff-classifier&lt;/a&gt;. The
implementation itself is at
&lt;a href=&quot;https://github.com/alexandru/stuff-classifier/blob/master/lib/stuff-classifier/bayes.rb&quot;&gt;lib/bayes.rb&lt;/a&gt;,
with the corresponding
&lt;a href=&quot;https://github.com/alexandru/stuff-classifier/blob/master/test/test_003_naive_bayes.rb&quot;&gt;test/test_003_naive_bayes.rb&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;1-introduction-to-probabilities&quot;&gt;1. Introduction to Probabilities&lt;/h2&gt;

&lt;p&gt;Let’s start by refreshing forgotten knowledge. Again, this is very
basic stuff, but if you can’t follow the theory here, you can always
go to the
&lt;a href=&quot;https://www.khanacademy.org/math/statistics-probability/probability-library&quot;&gt;probabilities section on khanacademy.org&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;11-events-and-event-types&quot;&gt;1.1. Events and Event Types&lt;/h3&gt;

&lt;p&gt;An “event” is a set of outcomes (a subset of all possible outcomes)
with a probability attached. So when flipping a coin, we can have one
of these 2 events happening: tail or head. Each of them has a
probability of 50%. Using a Venn diagram, this would look like this:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/coin-flip.png&quot; width=&quot;414&quot; height=&quot;218&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;And another example which clearly shows the &lt;em&gt;dependence&lt;/em&gt; between
“rain” and “cloud formation”, as raining can only happen if there are
clouds:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/inclusive.png&quot; width=&quot;432&quot; height=&quot;273&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;The relationship between events is very important, as you’ll see next:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;2 events are &lt;strong&gt;disjoint (exclusive)&lt;/strong&gt; if they can’t happen at the same
time (a single coin flip cannot yield a tail and a head at the same
time). For Bayes classification, we are not concerned with disjoint
events.&lt;/li&gt;
  &lt;li&gt;2 events are &lt;strong&gt;independent&lt;/strong&gt; when they can happen at the same time,
but the occurrence of one event does not make the occurrence of
another more or less probable. For example the second coin-flip you
make is not affected by the outcome of the first coin-flip.&lt;/li&gt;
  &lt;li&gt;2 events are &lt;strong&gt;dependent&lt;/strong&gt; if the outcome of one affects the other. In
the example above, clearly it cannot rain without a cloud
formation. Also, in a horse race, some horses have better
performance on rainy days.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What we are concerned here is the difference between dependent and
independent events, because calculating the intersection (both
happening at the same time) depends on it. So for independent events,
calculating the intersection is easy:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/d4dc272807b50935969c395a6c490e1a.svg&quot; alt=&quot;Math formula&quot; title=&quot;P(A \cap B) = P(A) \cdot P(B)&quot; width=&quot;288&quot; height=&quot;24&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Some examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;if you have 2 hard-drives, each of them having a 0.3 (30%)
probability of failure within the next year, that means there’s a
0.09 (9%) probability of them failing both within the next year&lt;/li&gt;
  &lt;li&gt;if you flip a coin 4 times, there’s a 0.0625 probability of getting
a tail 4 times in a row (0.5 ^ 4)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things are not so simple for dependent events, which is where the
Bayes Theorem comes into play.&lt;/p&gt;

&lt;h3 id=&quot;12-conditional-probabilities-and-the-bayes-theorem&quot;&gt;1.2. Conditional Probabilities and The Bayes Theorem&lt;/h3&gt;

&lt;p&gt;Let’s take one example. So we have the following stats:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;30 emails out of a total of 74 are spam messages&lt;/li&gt;
  &lt;li&gt;51 emails out of those 74 contain the word “penis”&lt;/li&gt;
  &lt;li&gt;20 emails containing the word “penis” have been marked as spam&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the question is: what is the probability that the latest received
email is a spam message, given that it contains the word “penis”?&lt;/p&gt;

&lt;p&gt;So these 2 events are clearly dependent, which is why you must use the
simple form of the Bayes Theorem:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/bfb225bb49b7b2633ce6e1a147f184c3.svg&quot; alt=&quot;Math formula&quot; title=&quot;P(A | B) = \frac{P(A \cap B)}{P(B)} = \frac{P(B|A) P(A)}{P(B)}&quot; width=&quot;444&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Or visually:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/conditional-prob.png&quot; width=&quot;490&quot; height=&quot;272&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;With the solution being:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/a9b78ca3ebfab7ec9977d1fb229b0052.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{eqnarray} r &amp;=&amp; P(spam|penis) \\[6pt] &amp;=&amp; \frac{P(penis|spam) \cdot P(spam)}{ P(penis) } \\[6pt] &amp;=&amp; \frac{\frac{20}{30} \cdot \frac{30}{74}}{\frac{51}{74}} = \frac{20}{51} = 0.39 \end{eqnarray}&quot; width=&quot;360&quot; height=&quot;216&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;This was a simple one, you could definitely see the result without
complicating yourself with the Bayes formula.&lt;/p&gt;

&lt;h3 id=&quot;13-the-naive-bayes-approach&quot;&gt;1.3. The Naive Bayes Approach&lt;/h3&gt;

&lt;p&gt;Let us complicate the problem above by adding to it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;25 emails out of the total contain the word “viagra”&lt;/li&gt;
  &lt;li&gt;24 emails out of those have been marked as spam&lt;/li&gt;
  &lt;li&gt;so what’s the probability that an email is spam, given that it
contains both “viagra” and “penis”?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shit just got more complicated, because now the formula is this one:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/b1447dcaddf1cac38e7fd6ba26e92af9.svg&quot; alt=&quot;Math formula&quot; title=&quot;\frac{ P(penis|spam \cap viagra) \cdot P(viagra|spam) \cdot P(spam) }{ P(penis|viagra) \cdot P(viagra) }&quot; width=&quot;624&quot; height=&quot;60&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;And you definitely don’t want to bother with it if we keep adding
words. But what if we simplified our assumptions and just say that the
occurrence of &lt;em&gt;penis&lt;/em&gt; is totally independent from the occurrence of
&lt;em&gt;viagra&lt;/em&gt;? Then the formula just got much simpler:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/504a9f4f3ecea69e23a8621a1ca5b8d1.svg&quot; alt=&quot;Math formula&quot; title=&quot;\begin{eqnarray} r &amp;=&amp; P(spam|penis,viagra) \\[6pt] &amp;=&amp; \frac{ P(penis|spam) \cdot P(viagra|spam) \cdot P(spam) }{ P(penis)\cdot P(viagra) } \\[6pt] &amp;=&amp; \frac{ \frac{24}{30} \cdot \frac{20}{30} \cdot \frac{30}{74} }{ \frac{25}{74} \cdot \frac{51}{74} } = 0.928 \end{eqnarray}&quot; width=&quot;564&quot; height=&quot;216&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;To classify an email as spam, you’ll have to calculate the conditional
probability by taking hints from the words contained. And the Naive
Bayes approach is exactly what I described above: we make the
assumption that the occurrence of one word is totally unrelated to the
occurrence of another, to simplify the processing and complexity
involved.&lt;/p&gt;

&lt;p&gt;This does highlight the flaw of this method of classification, because
clearly those 2 events we’ve picked (viagra and penis) are correlated
and our assumption is wrong. But this just means our results will be
less accurate.&lt;/p&gt;

&lt;h2 id=&quot;2-implementation&quot;&gt;2. Implementation&lt;/h2&gt;

&lt;p&gt;I mention it again, you can take a look at the source-code published
at
&lt;a href=&quot;https://github.com/alexandru/stuff-classifier/&quot;&gt;github.com/alexandru/stuff-classifier&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;21-general-algorithm&quot;&gt;2.1. General Algorithm&lt;/h3&gt;

&lt;p&gt;You simply get the probability for a text to belong to each of the
categories you test against. The category with the highest probability
for the given text wins:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/4a41191fa2d0823f7c1b542b10f65d34.svg&quot; alt=&quot;Math formula&quot; title=&quot;classify(word_1, word_2 \ldots word_n) = \\[6pt] \operatorname*{argmax}_{cat} P(cat) \cdot \prod_{i=1}^{n} P(word_i|cat)&quot; width=&quot;792&quot; height=&quot;72&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Do note that above I also eliminated the &lt;em&gt;denominator&lt;/em&gt; from our original
formula, because it is a constant that we do not need (called
&lt;em&gt;evidence&lt;/em&gt;).&lt;/p&gt;

&lt;h3 id=&quot;22-avoiding-floating-point-underflow-update-feb-27-2012&quot;&gt;2.2. Avoiding Floating Point Underflow (UPDATE Feb 27, 2012)&lt;/h3&gt;

&lt;p&gt;Because of the underlying limits of floating points, if you’re working
with big documents (not the case in this example), you do have to make
one important optimization to the above formula:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;instead of the probabilities of each word, you store the (natural)
logarithms of those probabilities&lt;/li&gt;
  &lt;li&gt;instead of multiplying the numbers, you add them instead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So instead of the above formula, if you need this optimization, then
use this one:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/8d348b5ff21c797e6ad1f23d6bf53297.svg&quot; alt=&quot;Math formula&quot; title=&quot;classify(word_1, word_2 \ldots word_n) = \\[6pt] \operatorname*{argmax}_{cat} log_{e} (P(cat)) + \sum_{i=1}^{n} log_{e} (P(word_i|cat))&quot; width=&quot;948&quot; height=&quot;72&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;h3 id=&quot;23-training&quot;&gt;2.3. Training&lt;/h3&gt;

&lt;p&gt;Your implementation must have a training method. Here’s how mine looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;def train(category, text)
  each_word(text) {|w| increment_word(w, category) }
  increment_cat(category)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And its usage:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;classifier.train :spam, &quot;Grow your penis to 20 inches in just 1 week&quot;
classifier.train :ham,  &quot;I&apos;m hungry, no I don&apos;t want your penis&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For the full implementation, take a look at
&lt;a href=&quot;https://github.com/alexandru/stuff-classifier/blob/master/lib/stuff-classifier/base.rb&quot;&gt;base.rb&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;24-getting-rid-of-stop-words--stemming&quot;&gt;2.4. Getting Rid of Stop Words / Stemming&lt;/h3&gt;

&lt;p&gt;First of all, you must get rid of the junk. Every language has words
that are so commonly used that make them meaningless for any kind of
classification you may want to do. For instance in English you have
words such as “the”, “to”, “you”, “he”, “only”, “if”, “it” that you
can safely strip out from the text.&lt;/p&gt;

&lt;p&gt;I’ve compiled a list of such words in this file:
&lt;a href=&quot;https://github.com/alexandru/stuff-classifier/blob/master/lib/stuff-classifier/stop_words.rb&quot;&gt;stop_words.rb&lt;/a&gt;. You
can compile such a list by yourself if you’re not using English for
example. Head over to &lt;a href=&quot;http://www.gutenberg.org/&quot;&gt;Project Gutenberg&lt;/a&gt;,
download some books in the language you want, count the words in them,
sort by popularity in descending order and keep the top words as words
that you can safely ignore.&lt;/p&gt;

&lt;p&gt;Also, our classifier is really dumb in the sense that it does not care
about the meaning or context of a word. So there’s a problem: consider
the word “running”. What you want is to treat this just as “run”,
which is the morphological root of the word. You also want to treat
“parenting” and “parents” as “parent”.&lt;/p&gt;

&lt;p&gt;This process is called &lt;em&gt;stemming&lt;/em&gt; and there are lots of libraries for
it. I think currently the most up-to-date and comprehensive library
for stemming is Snowball. It’s a C library with lots of bindings
available, including for Ruby and Python and it even has support for
my native language (Romanian).&lt;/p&gt;

&lt;p&gt;Take a look at what I’m doing in
&lt;a href=&quot;https://github.com/alexandru/stuff-classifier/blob/master/lib/stuff-classifier/tokenizer.rb&quot;&gt;tokenizer.rb&lt;/a&gt;,
where I’m getting rid of stop words and stemming the remaining.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;each_word(&apos;Hello world! How are you?&apos;)

# =&gt; [&quot;hello&quot;, &quot;world&quot;]

each_word(&apos;Lots of dogs, lots of cats!
  This is the information highway&apos;)

# =&gt; [&quot;lot&quot;, &quot;dog&quot;, &quot;lot&quot;, &quot;cat&quot;, &quot;inform&quot;, &quot;highwai&quot;]

each_word(&quot;I don&apos;t really get what you want to
  accomplish. There is a class TestEval2, you can do test_eval2 =
  TestEval2.new afterwards. And: class A ... end always yields nil, so
  your output is ok I guess ;-)&quot;)

# =&gt; [&quot;really&quot;, &quot;want&quot;, &quot;accomplish&quot;, &quot;class&quot;,
#     &quot;testeval&quot;, &quot;test&quot;, &quot;eval&quot;, &quot;testeval&quot;, &quot;new&quot;,
#     &quot;class&quot;, &quot;end&quot;, &quot;yields&quot;, &quot;nil&quot;, &quot;output&quot;,
#     &quot;ok&quot;, &quot;guess&quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; depending on the size of your training data, this may not be
a good idea. Stemming is useful in the beginning when you don’t have a
lot of data. Otherwise consider “&lt;em&gt;house&lt;/em&gt;” and “&lt;em&gt;housing&lt;/em&gt;” … the
former is used less frequently in a spammy context then the later.&lt;/p&gt;

&lt;h3 id=&quot;25-implementation-guidelines&quot;&gt;2.5. Implementation Guidelines&lt;/h3&gt;

&lt;p&gt;When classifying emails for spam, it is a good idea to be sure that a
certain message is a spam message, otherwise users may get pissed by
too many false positives.&lt;/p&gt;

&lt;p&gt;Therefore it is a good idea to have &lt;em&gt;thresholds&lt;/em&gt;. This is how my
implementation looks like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;def classify(text, default=nil)
  # Find the category with the highest probability

  max_prob = 0.0
  best = nil

  scores = cat_scores(text)
  scores.each do |score|
    cat, prob = score
    if prob &gt; max_prob
      max_prob = prob
      best = cat
    end
  end

  # Return the default category in case the threshold condition was
  # not met. For example, if the threshold for :spam is 1.2
  #
  #    :spam =&gt; 0.73, :ham =&gt; 0.40  (OK)
  #    :spam =&gt; 0.80, :ham =&gt; 0.70  (Fail, :ham is too close)

  return default unless best
  threshold = @thresholds[best] || 1.0

  scores.each do |score|
    cat, prob = score
    next if cat == best
    return default if prob * threshold &gt; max_prob
  end

  return best
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;final-words&quot;&gt;Final Words&lt;/h2&gt;

&lt;p&gt;My example involved spam classification, however this is not how
modern spam classifiers work btw. Because the independence assumptions
are often inaccurate, this type of classifier can be gamed by spammers
to trigger a lot of false positives, which will make the user turn the
feature off eventually.&lt;/p&gt;

&lt;p&gt;But it is general purpose, being good enough not only for spam
detection, but also for lots of other use-cases and it’s enough to get
you started.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2012/02/09/howto-build-naive-bayes-classifier/?pk_campaign=rss&quot;&gt;How To Build a Naive Bayes Classifier&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 09 Feb 2012 00:00:00 +0000</pubDate>
  <dc:modified>Sat, 25 Jan 2020 00:00:00 +0000</dc:modified>
  <atom:modified>Sat, 25 Jan 2020 00:00:00 +0000</atom:modified>
  <link>https://alexn.org/blog/2012/02/09/howto-build-naive-bayes-classifier/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2012/02/09/howto-build-naive-bayes-classifier/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Best Of</category>
  <category>Algorithms</category>
  <category>Mining</category>
  <category>Ruby</category>
  <category>Math</category>
  </item>


<item>
  <title>Data Mining: Finding Similar Items and Users</title>
  <description>How to find related items? Here are recipes based on really simple formulas. If you pay attention, this technique is used all over the web (like on Amazon) to personalize the user experience and increase conversion rates. Because we want to give kick-ass product recommendations.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2012/01/16/cosine-similarity-euclidean-distance/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/cosine-distance.png?202603060940&quot; alt=&quot;&quot; width=&quot;1285&quot; height=&quot;830&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  How to find related items? Here are recipes based on really simple
  formulas. If you pay attention, this technique is used all over the web
  (like on Amazon) to personalize the user experience and increase
  conversion rates. Because we want to give kick-ass product recommendations.
&lt;/p&gt;

&lt;p&gt;To get one question out of the way: there are already many available
libraries that do this, but as you’ll see there are multiple ways of
skinning the cat and you won’t be able to pick the right one without
understanding the process, at least intuitively.&lt;/p&gt;

&lt;h2 id=&quot;defining-the-problem&quot;&gt;Defining the Problem&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/amazon-recommended-items.png&quot; alt=&quot;Amazon gives kick-ass suggestions to their customers&quot; width=&quot;300&quot; height=&quot;273&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;&lt;/p&gt;

&lt;p&gt;To find similar items to a certain item, you’ve got to first define
what it means for 2 items to be similar and this depends on the
problem you’re trying to solve:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;on a blog, you may want to suggest similar articles that share the
same tags, or that have been viewed by the same people viewing the
item you want to compare with&lt;/li&gt;
  &lt;li&gt;Amazon has this section called “&lt;em&gt;customers that bought this item also
bought&lt;/em&gt;”, which is self-explanatory&lt;/li&gt;
  &lt;li&gt;a service like IMDB, based on your ratings, could find users similar
to you, users that liked or hated approximately the same movies you did,
thus giving you suggestions on movies you’d like to watch in the future&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In each case you need a way to classify these items you’re comparing,
whether it is tags, or items purchased, or movies reviewed. We’ll be
using tags, as it is simpler, but the formula holds for more
complicated instances.&lt;/p&gt;

&lt;h2 id=&quot;redefining-the-problem-in-terms-of-geometry&quot;&gt;Redefining the Problem in Terms of Geometry&lt;/h2&gt;

&lt;p&gt;We’ll be using my blog as sample. Let’s take some tags:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;[&quot;API&quot;, &quot;Algorithms&quot;, &quot;Amazon&quot;, &quot;Android&quot;, &quot;Books&quot;, &quot;Browser&quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s 6 tags. Well, what if we considered these tags as dimensions in
a 6-dimensional
&lt;a href=&quot;http://en.wikipedia.org/wiki/Euclidean_space&quot;&gt;Euclidean space&lt;/a&gt;? Then
each item you want to sort or compare becomes a point in this space,
in which a coordinate (representing a tag) is either one (tagged) or
zero (not tagged).&lt;/p&gt;

&lt;p&gt;So let’s say we’ve got one article tagged with &lt;em&gt;API&lt;/em&gt; and
&lt;em&gt;Browser&lt;/em&gt;. Then its associated point will be:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;[ 1, 0, 0, 0, 0, 1 ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now these coordinates could represent something else. For instance
they could represent users. If say you’ve got a total of 6 users in
your system, 2 of them rating an item with 3 and 5 stars respectively,
you could have for the article in question this associated point
(do note the order is very important):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;[ 0, 3, 0, 0, 5, 0 ]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now you can go ahead and calculate distances between these
points. For instance you could calculate the angle between the
associated vectors, or the actual euclidean distance between the 2
points. For a 2-dimensional Euclidean space, here’s how it would look
like:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/similarity-graphic.png&quot; width=&quot;1285&quot; height=&quot;830&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;euclidean-distance&quot;&gt;Euclidean Distance&lt;/h2&gt;

&lt;p&gt;The mathematical formula for the Euclidean distance is really
simple. Considering 2 points, A and B, with their associated
coordinates, the distance is defined as:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/269437dfcd757e4392c64a4c12dd6119.svg&quot; alt=&quot;Math formula&quot; title=&quot;distance(A, B) = \sqrt{(a_1-b_1)^2 + (a_2-b_2)^2 + \ldots + (a_n-b_n)^2}&quot; width=&quot;720&quot; height=&quot;48&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;The lower the distance between 2 points, then the higher the
similarity. Here’s some Ruby code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;# Returns the Euclidean distance between 2 points
#
# Params:
#  - a, b: list of coordinates (float or integer)
#
def euclidean_distance(a, b)
  sq = a.zip(b).map{|a,b| (a - b) ** 2}
  Math.sqrt(sq.inject(0) {|s,c| s + c})
end

# Returns the associated point of our tags_set, relative to our
# tags_space.
#
# Params:
#  - tags_set: list of tags
#  - tags_space: _ordered_ list of tags
def tags_to_point(tags_set, tags_space)
  tags_space.map{|c| tags_set.member?(c) ? 1 : 0}
end

# Returns other_items sorted by similarity to this_item
# (most relevant are first in the returned list)
#
# Params:
#  - items: list of hashes that have [:tags]
#  - by_these_tags: list of tags to compare with
def sort_by_similarity(items, by_these_tags)
  tags_space = by_these_tags + items.map{|x| x[:tags]}
  tags_space.flatten!.sort!.uniq!

  this_point = tags_to_point(by_these_tags, tags_space)
  other_points = items.map{|i|
    [i, tags_to_point(i[:tags], tags_space)]
  }

  similarities = other_points.map{|item, that_point|
    [item, euclidean_distance(this_point, that_point)]
  }

  sorted = similarities.sort {|a,b| a[1] &lt;=&gt; b[1]}
  return sorted.map{|point,s| point}
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And here is the test you could do, and btw you can copy the above and
the bellow script and run it directly:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;# SAMPLE DATA

all_articles = [
  {
   :article =&gt; &quot;Data Mining: Finding Similar Items&quot;,
   :tags =&gt; [&quot;Algorithms&quot;, &quot;Programming&quot;, &quot;Mining&quot;,
     &quot;Python&quot;, &quot;Ruby&quot;]
  },
  {
   :article =&gt; &quot;Blogging Platform for Hackers&quot;,
   :tags =&gt; [&quot;Publishing&quot;, &quot;Server&quot;, &quot;Cloud&quot;, &quot;Heroku&quot;,
     &quot;Jekyll&quot;, &quot;GAE&quot;]
  },
  {
   :article =&gt; &quot;UX Tip: Don&apos;t Hurt Me On Sign-Up&quot;,
   :tags =&gt; [&quot;Web&quot;, &quot;Design&quot;, &quot;UX&quot;]
  },
  {
   :article =&gt; &quot;Crawling the Android Marketplace&quot;,
   :tags =&gt; [&quot;Python&quot;, &quot;Android&quot;, &quot;Mining&quot;,
     &quot;Web&quot;, &quot;API&quot;]
  }
]

# SORTING these articles by similarity with an article
# tagged with Publishing + Web + API
#
#
# The list is returned in this order:
#
# 1. article: Crawling the Android Marketplace
#    similarity: 2.0
#
# 2. article: &quot;UX Tip: Don&apos;t Hurt Me On Sign-Up&quot;
#    similarity: 2.0
#
# 3. article: Blogging Platform for Hackers
#    similarity: 2.645751
#
# 4. article: &quot;Data Mining: Finding Similar Items&quot;
#    similarity: 2.828427
#

sorted = sort_by_similarity(
    all_articles, [&apos;Publishing&apos;, &apos;Web&apos;, &apos;API&apos;])

require &apos;yaml&apos;
puts YAML.dump(sorted)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;the-problem-or-strength-of-euclidean-distance&quot;&gt;The Problem (or Strength) of Euclidean Distance&lt;/h3&gt;

&lt;p&gt;Can you see one flaw with it for our chosen data-set and intention? I
think you can - the first 2 articles have the same Euclidean distance
to [“Publishing”, “Web”, “API”], even though the first article shares
2 tags with our chosen item, instead of just 1 tag as the rest.&lt;/p&gt;

&lt;p&gt;To visualize why, look at the points used in calculating the distance
for the first article:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So 4 coordinates are different. Now look at the points used for the
second article:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, 4 coordinates are different. So here’s the deal with Euclidean
distance: it measures &lt;em&gt;dissimilarity&lt;/em&gt;. The coordinates that are the
same are less important than the coordinates that are different. For
my purpose here, this is not good - because articles with more tags
(or less) tags than the average are going to be disadvantaged.&lt;/p&gt;

&lt;h2 id=&quot;cosine-similarity&quot;&gt;Cosine Similarity&lt;/h2&gt;

&lt;p&gt;This method is very similar to the one above, but does tend to give
slightly different results, because this one actually measures
similarity instead of dissimilarity. Here’s the formula:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/19edfdfad8dbb6177ba5e6651e30d12a.svg&quot; alt=&quot;Math formula&quot; title=&quot;similarity= cos(\theta)= \frac{A \cdot B}{\|A\| \|B\|}= \frac{ \displaystyle\sum_{i=1}^{n} A_i B_i }{ \sqrt{ \displaystyle\sum_{i=1}^{n} A_i^2 } \sqrt{ \displaystyle\sum_{i=1}^{n} B_i^2 } }&quot; width=&quot;624&quot; height=&quot;168&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;If you look at the visual with the 2 axis and 2 points, we need the
cosine of the angle &lt;em&gt;theta&lt;/em&gt; that’s between the vectors associated with
our 2 points. And for our sample it does give better results.&lt;/p&gt;

&lt;p&gt;The values will range between -1 and 1. -1 means that 2 items are
total opposites, 0 means that the 2 items are independent of each
other and 1 means that the 2 items are very similar (btw, because we
are only doing zeros and ones for coordinates here, this score will
never get negative for our sample).&lt;/p&gt;

&lt;p&gt;Here’s the Ruby code (leaving out the wiring to our sample data, do
that as an exercise):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;def dot_product(a, b)
  products = a.zip(b).map{|a, b| a * b}
  products.inject(0) {|s,p| s + p}
end

def magnitude(point)
  squares = point.map{|x| x ** 2}
  Math.sqrt(squares.inject(0) {|s, c| s + c})
end

# Returns the cosine of the angle between the vectors
#associated with 2 points
#
# Params:
#  - a, b: list of coordinates (float or integer)
#
def cosine_similarity(a, b)
  dot_product(a, b) / (magnitude(a) * magnitude(b))
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also, sorting the articles in the above sample gives me the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;- article: Crawling the Android Marketplace
  similarity: 0.5163977794943222

- article: &quot;UX Tip: Don&apos;t Hurt Me On Sign-Up&quot;
  similarity: 0.33333333333333337

- article: Blogging Platform for Hackers
  similarity: 0.23570226039551587

- article: &quot;Data Mining: Finding Similar Items&quot;
  similarity: 0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Right, so much better for this chosen sample and usage. Ain’t this
fun? BUT, you guessed it, there’s a problem with this too …&lt;/p&gt;

&lt;h3 id=&quot;the-problem-with-our-sample-the-tf-idf-weight&quot;&gt;The Problem with Our Sample; The Tf-Idf Weight&lt;/h3&gt;

&lt;p&gt;Our data sample is so simple that we could have simply counted the
number of common tags and use that as a metric. The result would be
the same without getting fancy with Cosine Similarity :-)&lt;/p&gt;

&lt;p&gt;Clearly a tag such as “Heroku” is more specific than a general purpose
tag such as “Web”. Also, just because Jekyll was mentioned in an
article, that doesn’t make the article about Jekyll. Also an article
tagged with “Android” may be twice as Android-related as another
article also tagged with “Android”.&lt;/p&gt;

&lt;p&gt;So here’s a solution to this: the
&lt;strong&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Tf%E2%80%93idf&quot;&gt;Tf-Idf weight&lt;/a&gt;&lt;/strong&gt;, &lt;em&gt;a
statistical measure used to evaluate how important a word is to a
document in a collection or corpus&lt;/em&gt;. With it you can give values to
your coordinates that are much more specific than simple ones and
zeros. But I’ll leave that for another day.&lt;/p&gt;

&lt;p&gt;Also, related to our simple data-set here, perhaps an even simpler
metric, like the
&lt;a href=&quot;http://en.wikipedia.org/wiki/Jaccard_index&quot;&gt;Jaccard index&lt;/a&gt; would be
better.&lt;/p&gt;

&lt;h2 id=&quot;pearson-correlation-coefficient&quot;&gt;Pearson Correlation Coefficient&lt;/h2&gt;

&lt;p&gt;The
&lt;a href=&quot;http://en.wikipedia.org/wiki/Pearson_product-moment_correlation_coefficient&quot;&gt;Pearson Correlation Coefficient&lt;/a&gt;
for finding the similarity of 2 items is slightly more sophisticated
and doesn’t really apply to my chosen data-set. This coefficient
measures how well two samples are linearly related.&lt;/p&gt;

&lt;p&gt;For example, on IMDB we may have 2 users. One of them, lets call him
John, has given the following ratings to 5 movies:
[1, 2, 3, 4, 5]. The other one, Mary, has given the following ratings
to the same 5 movies: [4, 5, 6, 7, 8]. The 2 users are very similar,
as there is a perfect linear correlation between them, since Mary just
gives the same rankings as John plus 3. The formula itself or the
theory is not very intuitive though. But it is simple to calculate:&lt;/p&gt;

&lt;div class=&quot;math-display page-width&quot;&gt;&lt;img src=&quot;https://alexn.org/assets/math/white/821ec4ec2cccf3a3ed64c859ae9fbf3f.svg&quot; alt=&quot;Math formula&quot; title=&quot;r = \frac{ \displaystyle\sum_{i=1}^{n} a_i b_i - \frac{ \displaystyle\sum_{i=1}^{n} a_i \displaystyle\sum_{i=1}^{n} b_i }{n} }{ \sqrt{ (\displaystyle\sum_{i=1}^{n} a_i^2 - \frac{(\displaystyle\sum_{i=1}^{n} a_i)^2}{n}) \cdot (\displaystyle\sum_{i=1}^{n} b_i^2 - \frac{(\displaystyle\sum_{i=1}^{n} b_i)^2}{n}) } }&quot; width=&quot;564&quot; height=&quot;264&quot; loading=&quot;lazy&quot;&gt;&lt;/div&gt;

&lt;p&gt;Here’s the code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;def pearson_score(a, b)
  n = a.length
  return 0 unless n &gt; 0

  # summing the preferences
  sum1 = a.inject(0) {|sum, c| sum + c}
  sum2 = b.inject(0) {|sum, c| sum + c}
  # summing up the squares
  sum1_sq = a.inject(0) {|sum, c| sum + c ** 2}
  sum2_sq = b.inject(0) {|sum, c| sum + c ** 2}
  # summing up the product
  prod_sum = a.zip(b).inject(0) {|sum, ab| sum + ab[0] * ab[1]}

  # calculating the Pearson score
  num = prod_sum - (sum1 *sum2 / n)
  den = Math.sqrt((sum1_sq - (sum1 ** 2) / n) * (sum2_sq - (sum2 ** 2) / n))

  return 0 if den == 0
  return num / den
end


puts pearson_score([1,2,3,4,5], [4,5,6,7,8])
# =&gt; 1.0
puts pearson_score([1,2,3,4,5], [4,5,0,7,8])
# =&gt; 0.5063696835418333
puts pearson_score([1,2,3,4,5], [4,5,0,7,7])
# =&gt; 0.4338609156373132
puts pearson_score([1,2,3,4,5], [8,7,6,5,4])
# =&gt; -1
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;manhattan-distance&quot;&gt;Manhattan Distance&lt;/h2&gt;

&lt;p&gt;There is no one size fits all and the formula you’re going to use
depends on your data and what you want out of it.&lt;/p&gt;

&lt;p&gt;For instance the
&lt;a href=&quot;http://en.wikipedia.org/wiki/Taxicab_geometry&quot;&gt;Manhattan Distance&lt;/a&gt;
computes the distance that would be traveled to get from one data
point to the other if a grid-like path is followed. I like this
graphic from Wikipedia that perfectly illustrates the difference with
Euclidean distance:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;https://alexn.org/assets/media/articles/manhattan.svg&quot; alt=&quot;Manhattan distance&quot; width=&quot;283&quot; height=&quot;283&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
&lt;/figure&gt;

&lt;p&gt;Red, yellow and blue lines all have the same length and the distance
is bigger than the corresponding green diagonal, which is the normal
Euclidean distance.&lt;/p&gt;

&lt;p&gt;Personally I haven’t found a usage for it, as it is more related to
path-finding algorithms, but it’s a good thing to keep in mind that it
exists and may prove useful. Since it measures how many changes you
have to do to your origin location to get to your destination while
being limited to taking small steps in a grid-like system, it is very
similar in spirit to the
&lt;a href=&quot;http://en.wikipedia.org/wiki/Levenshtein_distance&quot;&gt;Levenshtein distance&lt;/a&gt;,
which measures the minimum number of changes required to transform
some text into another.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2012/01/16/cosine-similarity-euclidean-distance/?pk_campaign=rss&quot;&gt;Data Mining: Finding Similar Items and Users&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 16 Jan 2012 00:00:00 +0000</pubDate>
  <dc:modified>Wed, 22 Oct 2025 05:56:17 +0000</dc:modified>
  <atom:modified>Wed, 22 Oct 2025 05:56:17 +0000</atom:modified>
  <link>https://alexn.org/blog/2012/01/16/cosine-similarity-euclidean-distance/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2012/01/16/cosine-similarity-euclidean-distance/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Best Of</category>
  <category>Algorithms</category>
  <category>Mining</category>
  <category>Ruby</category>
  <category>Math</category>
  </item>


<item>
  <title>Blogging Platform for Hackers</title>
  <description>Host your own static website on Heroku’s free plan, use Google’s App Engine as a CDN, keep Heroku’s free dyno alive, generate the website via Jekyll.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2012/01/05/blogging-for-hackers/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/jekyll.png?202603060940&quot; alt=&quot;&quot; width=&quot;960&quot; height=&quot;489&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;Host your own static website using free services. This article is a recipe for:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;building your website with &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;hosting your own static website on Heroku’s free plan;&lt;/li&gt;
  &lt;li&gt;using Google’s App Engine as a CDN, for better responsiveness;&lt;/li&gt;
  &lt;li&gt;keeping  Heroku’s free dyno alive, by using a GAE cron job;&lt;/li&gt;
  &lt;li&gt;having a very responsive, scalable and secure blog, with ultimate;
control and simplicity, for zero bucks per month;&lt;/li&gt;
&lt;/ul&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;UPDATE (2019-12-19):&lt;/strong&gt; these days there are better options available for hosting your static website for free, including &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; (also see &lt;a href=&quot;https://github.com/features/actions&quot;&gt;GitHub Actions&lt;/a&gt;) and &lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;You could just skip this article and browse the source code of my
blog:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/alexandru/alexn.org&quot;&gt;github.com/alexandru/alexn.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Forget about Wordpress or Blogger. Hacking your own stuff is much more
fun. Also, make sure to read
&lt;a href=&quot;http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html&quot;&gt;Blogging Like a Hacker&lt;/a&gt;,
by Tom Preston-Werner, GitHub’s cofounder and the author of Jekyll.&lt;/p&gt;

&lt;h2 id=&quot;jekyll-and-heroku-sitting-in-a-tree&quot;&gt;Jekyll and Heroku, Sitting in a Tree&lt;/h2&gt;

&lt;p&gt;I love &lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt;, the static
website generator. It is pure awesomeness for me:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;all content is hosted in a Git repository, the best CMS ever
invented&lt;/li&gt;
  &lt;li&gt;my articles are written in Markdown, with Emacs, the most potent
text editor ever created - think Textmate-snippets, macros, syntax
highlighting, keyboard-driven navigation and spelling corrections&lt;/li&gt;
  &lt;li&gt;static content scales like crazy, without any special gimmicks. A
small VPS can serve thousands of requests per second without a
sweat&lt;/li&gt;
  &lt;li&gt;static content is also secure by default, no constant upgrades
required, no SQL injections&lt;/li&gt;
  &lt;li&gt;I always make little tweaks to my design, I’m never satisfied, which
is why it makes sense to make my own, but checkout
&lt;a href=&quot;http://octopress.org/&quot;&gt;Octopress&lt;/a&gt; in case you want a reasonable
default&lt;/li&gt;
  &lt;li&gt;I’ve lost an entire blog when my hosting account got blocked in the
past. Never again, as my content is right now saved in 2 Git
repositories and on my local machine&lt;/li&gt;
  &lt;li&gt;by working with my own domain, making my own shit, Google will never
make me cry ;-)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jekyll’s first hosting option you should consider is
&lt;a href=&quot;http://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt;, however you will need &lt;em&gt;some&lt;/em&gt;
dynamic behavior, like having configurable redirects. If you don’t
then ignore this post and just read
&lt;a href=&quot;https://github.com/mojombo/jekyll/wiki/usage&quot;&gt;Jekyll’s tutorial&lt;/a&gt;, but
you can come back to this post when its limits start bothering you.&lt;/p&gt;

&lt;p&gt;Heroku’s free plan is awesome, in spite of what
&lt;a href=&quot;https://alexn.org/blog/2011/10/23/why-i-find-heroku-suboptimal/&quot;&gt;I said previously&lt;/a&gt;.
It’s great for prototyping and for quickly seeing your website
online. Instant gratification is awesome. Well, it does have some
problems and to tell you the truth, for hosting my blog I would have
rather used Google’s &lt;a href=&quot;http://code.google.com/appengine/&quot;&gt;App Engine&lt;/a&gt;,
if only they allowed me to have naked domains. I like my domains to be
naked.&lt;/p&gt;

&lt;p&gt;One note in regards to the scalability of static content I mentioned
above. In Heroku the Bamboo stack features a Varnish frontend. If you
set proper expiry headers on your content, subsequent requests will
not hit the Ruby server.&lt;/p&gt;

&lt;h2 id=&quot;hosting-static-content-on-heroku&quot;&gt;Hosting Static Content on Heroku&lt;/h2&gt;

&lt;p&gt;So this tutorial is about hosting a Jekyll website, which is why I’m
going to make some assumptions about your directory structure. However
you can modify these instructions for any static website, not just
Jekyll-generated stuff.&lt;/p&gt;

&lt;p&gt;First, the setup:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# install the heroku command-line utility
gem install heroku

# change to your website directory
cd website/

# initialize a git repo, if you haven&apos;t done so
git init
# ... and commit everything to it
git add .
git commit -m &apos;initial commit&apos;

# create the heroku app
heroku create
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, now we need a Rake-powered application to serve our
content. We’ll need a &lt;em&gt;./Gemfile&lt;/em&gt; …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;source &apos;http://rubygems.org&apos;

gem &apos;rack&apos;
gem &apos;mime-types&apos;

group :development do
  gem &apos;jekyll&apos;
  gem &apos;rdiscount&apos;
  gem &apos;hpricot&apos;
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then install these gems with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;bundle install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You also need a Rake configuration file, &lt;em&gt;./config.ru&lt;/em&gt;. What follows is the
configuration that I am using. You can go simpler, a lot simpler than
this actually, but I like flexibility and Heroku also does something
funny with files served through Rack::File, so I refrained from using
it …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;# Rack configuration file for serving a Jekyll-generated static
# website from Heroku, with some nice additions:
#
# * knows how to do redirects, with settings taken from ./_config.yaml
# * sets the cache expiry for HTML files differently from other static
#   assets, with settings taken from ./_config.yaml

require &apos;yaml&apos;
require &apos;mime/types&apos;

# main configuration file, also used by Jekyll
CONFIG = YAML::load_file(File.join(File.dirname(__FILE__), &apos;_config.yml&apos;))

# points to our generated website directory
PUBLIC = File.expand_path(File.join(File.dirname(__FILE__),
                          CONFIG[&apos;destination&apos;] || &apos;_site&apos;))

# For cutting down on the boilerplate

class BaseMiddleware
  def initialize(app)
    @app = app
  end

  def each(&amp;block)
  end
end


# Rack middleware for correcting paths:
#
# 1. redirects from the www. version to the naked domain version
#
# 2. converts directory/paths/ to directory/paths/index.html (most
#    importantly / to /index.html)

class PathCorrections &lt; BaseMiddleware
  def call(env)
    env[&apos;PATH_INFO&apos;] += &apos;index.html&apos; if env[&apos;PATH_INFO&apos;].end_with? &apos;/&apos;
    request = Rack::Request.new(env)

    if request.host.start_with?(&quot;www.&quot;)
      [301, {&quot;Location&quot; =&gt; request.url.sub(&quot;//www.&quot;, &quot;//&quot;)}, self]
    else
      @app.call(env)
    end
  end
end


# Middleware that enables configurable redirects. The configuration is
# done in the standard Jekyll _config.yml file.
#
# Sample configuration in _config.yml:
#
#   redirects:
#     - from: /docs/some-document.html
#       to: /archive/some-document.html
#       type: 301
#
# The sample above will do a permanent redirect from ((*/docs/dialer.html*))
# to ((*/archive/some-document.html*))

class Redirects &lt; BaseMiddleware
  def call(env)
    request = Rack::Request.new(env)

    path = request.path_info
    ext  = File.extname(path)
    path += &apos;/&apos; if ext == &apos;&apos; and ! path.end_with?(&apos;/&apos;)

    if redirect = CONFIG[&apos;redirects&apos;].find{|x| path == x[&apos;from&apos;]}
      new_location = redirect[&apos;to&apos;]
      new_location = request.base_url + new_location \
        unless new_location.start_with?(&quot;http&quot;)
      [redirect[&apos;type&apos;] || 302, {&apos;Location&apos; =&gt; new_location}, self]
    else
      @app.call(env)
    end
  end
end


# The 404 Not Found message should be a simple one in case the
# mimetype of a file is not HTML (like the message returned by
# Rack::File). However, in case of HTML files, then we should display
# a custom 404 message

class Fancy404NotFound &lt; BaseMiddleware
  def call(env)
    status, headers, response = @app.call(env)
    if status == 404
      ext = File.extname(env[&apos;PATH_INFO&apos;])
      if ext =~ /html?$/ or ext == &apos;&apos; or !ext
        headers = {&apos;Content-Type&apos; =&gt; &apos;text/html&apos;}
        response = File.open(File.join PUBLIC, &apos;pages&apos;, &apos;404.html&apos;)
      end
    end

    [status, headers, response]
  end
end


# Mimicking Rack::File
#
# I couldn&apos;t work with Rack::File directly, because for some reason
# Heroku prevents me from overriding the Cache-Control header, setting
# it to 12 hours. But 12 hours is not suitable for HTML content that
# may receive fixes and other assets should have an expiry in the far
# future, with 12 hours not being enough.

class Application &lt; BaseMiddleware
  class Http404 &lt; Exception; end

  def guess_mimetype(path)
    type = MIME::Types.of(path)[0] || nil
    type ? type.to_s : nil
  end

  def call(env)
    request = Rack::Request.new(env)
    path_info = request.path_info

    # a /ping request always hits the Ruby Rake server - useful in
    # case you want to setup a cron to check if the server is still
    # online or bring it back to life in case it sleeps

    if path_info == &quot;/ping&quot;
      return [200, {
          &apos;Content-Type&apos; =&gt; &apos;text/plain&apos;,
          &apos;Cache-Control&apos; =&gt; &apos;no-cache&apos;
      }, [DateTime.now.to_s]]
    end

    headers = {}
    if mimetype = guess_mimetype(path_info)
      headers[&apos;Content-Type&apos;] = mimetype
      if mimetype == &apos;text/html&apos;
        headers[&apos;Content-Language&apos;] = &apos;en&apos;
        headers[&apos;Content-Type&apos;] += &quot;; charset=utf-8&quot;
      end
    end

    begin
      # basic validation of the path provided
      raise Http404 if path_info.include? &apos;..&apos;
      abs_path = File.join(PUBLIC, path_info[1..-1])
      raise Http404 unless File.exists? abs_path

      # setting Cache-Control expiry headers
      type = path_info =~ /\.html?$/ ? &apos;html&apos; : &apos;assets&apos;
      headers[&apos;Cache-Control&apos;]  = &quot;public, max-age=&quot;
      headers[&apos;Cache-Control&apos;] += CONFIG[&apos;expires&apos;][type].to_s

      status, response = 200, File.open(abs_path, &apos;r&apos;)
    rescue Http404
      status, response = 404, [&quot;404 Not Found: #{path_info}&quot;]
    end

    [status, headers, response]
  end
end


#
# the actual Rack configuration, using
# the middleware defined above
#

use Redirects
use PathCorrections
use Fancy404NotFound

run Application.new(PUBLIC)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This Rack configuration uses settings defined in the standard Jekyll
&lt;em&gt;_config.yaml&lt;/em&gt; file. Here are some settings needed for it to work as
intended:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;destination: ./_site

expires:
  html: 3600 # one hour
  assets: 1314000 # one year

redirects:
  - from: /rss/
    to: http://feeds.feedburner.com/bionicspirit
    type: 302
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, so once done, test this configuration:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# generating the website
jekyll

# starting the server
rackup
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Deployment is as easy as pie:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git push heroku master
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;One note: Heroku could be configured to automatically generate the
website for you. However you either have to use the Cedar stack, or
generate the pages on the fly. In case of the Cedar stack, you lose
Varnish. Just keep your generated files in Git, it’s easier.&lt;/p&gt;

&lt;h2 id=&quot;commenting-with-disqus-facebook-or-roll-your-own&quot;&gt;Commenting with Disqus, Facebook or Roll Your Own&lt;/h2&gt;

&lt;p&gt;For commenting &lt;a href=&quot;http://disqus.com&quot;&gt;Disqus&lt;/a&gt; is a really good
service. In case you have a very popular website amongst normal
people, it may be even better to integrate Facebook’s commenting
widget.&lt;/p&gt;

&lt;p&gt;Well, I had some fun a while ago and created my own:
&lt;a href=&quot;https://github.com/alexandru/TheBuzzEngine&quot;&gt;TheBuzzEngine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately it doesn’t have all the features I want, but it does get
the job done and it isn’t bloated. These days I’ll probably get around
to adding some stuff to it, like threaded comments and email
subscriptions. This is what happens when working for fun on stuff -
once you’re over a certain threshold, the return of investment is too
low to bother with extra development.&lt;/p&gt;

&lt;p&gt;I recommend Disqus, although rolling your own is fun and keeps you in
control (which is the reason I’m using Jekyll in the first place).&lt;/p&gt;

&lt;h2 id=&quot;using-google-app-engine-as-your-cdn-or-cron-manager&quot;&gt;Using Google App Engine as Your CDN or Cron Manager&lt;/h2&gt;

&lt;p&gt;So when using Heroku’s free plan, I feel a little uncomfortable
because relying on one dyno can get you in trouble. Having Varnish in
front is great, but Varnish is a cache manager. For instance, if you
happen to push a new version of your latest article to Heroku, then
the Varnish cache gets cleared and the Ruby server can potentially get
exposed to a lot of requests and one dyno on Heroku can only serve one
request at a time.&lt;/p&gt;

&lt;p&gt;So why not push all our static assets, except HTML files, to a CDN?
It’s best practice anyway as your website should be more
responsive. If you have an Amazon AWS account, then CloudFront + S3
are great.&lt;/p&gt;

&lt;p&gt;However, I started with the goal of hosting this for zero bucks (it’s
fun, so why not?). Therefore I’m going to teach you how to push your
files to Google’s &lt;a href=&quot;http://code.google.com/appengine/&quot;&gt;App Engine&lt;/a&gt;. I
don’t really know how GAE works as a CDN for static files, but it
seems that it does have the
&lt;a href=&quot;http://blog.sallarp.com/google-app-engine-cdn/&quot;&gt;properties of a CDN&lt;/a&gt;
(i.e. serving content to users from servers closer to their location).&lt;/p&gt;

&lt;p&gt;Another problem with Heroku’s free plan is that the free dyno goes to
sleep, to save resources. While I advise you to just pay up for an
extra dyno, you can get around this restriction by just configuring
GAE to send a periodic &lt;em&gt;ping&lt;/em&gt; to your website.&lt;/p&gt;

&lt;p&gt;Here’s my GAE configuration file, &lt;em&gt;app.yaml&lt;/em&gt; which should sit in your
root (assuming &lt;em&gt;./assets&lt;/em&gt; is the directory you want to serve from GAE):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;application: assets-bionicspirit
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:

- url: /assets
  static_dir: assets
  expiration: &quot;365d&quot;

# next item is for our cron job, described below, but you can ignore
# it if you don&apos;t want a cron job ...

- url: /tasks/ping
  script: ping.app
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, I’m setting the expiry of my static assets to a
whooping 1 year.&lt;/p&gt;

&lt;p&gt;I also have a real handler, at &lt;em&gt;/tasks/ping&lt;/em&gt; configured. This will be
our cron job that sends a ping to our Heroku app, every X
minutes. Here’s the code for &lt;em&gt;ping.py&lt;/em&gt; …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import webapp2
from google.appengine.api import urlfetch

class PingService(webapp2.RequestHandler):
  def get(self):
      self.response.headers[&apos;Content-Type&apos;] = &apos;text/plain&apos;

      url = &quot;https://alexn.org/ping&quot;
      try:
          result = urlfetch.fetch(url, deadline=30)
          self.response.out.write(&apos;HTTP %d - %s&apos; %
              (result.status_code, (result.content or &apos;&apos;).strip()))
      except:
          self.response.out.write(&apos;ERROR: no response&apos;)

app = webapp2.WSGIApplication([(&apos;/tasks/ping&apos;, PingService)], debug=False)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But we are not done. To configure &lt;em&gt;/tasks/ping&lt;/em&gt; to run every X
minutes, you also need a &lt;em&gt;cron.yaml&lt;/em&gt; file …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;cron:
- description: ping alexn.org to wake it up
  url: /tasks/ping
  schedule: every 4 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Assuming you already have the
&lt;a href=&quot;http://code.google.com/appengine/docs/python/gettingstarted/devenvironment.html&quot;&gt;GAE SDK installed&lt;/a&gt;,
then run this command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;appcfg.py update .
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To see it working on this blog, here are the requests:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Heroku URL getting requested: &lt;a href=&quot;https://alexn.org/ping&quot;&gt;https://alexn.org/ping&lt;/a&gt;
&lt;/li&gt;
  &lt;li&gt;GAE Cron Job getting executed: &lt;a href=&quot;http://assets-bionicspirit.appspot.com/tasks/ping&quot;&gt;http://assets-bionicspirit.appspot.com/tasks/ping&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;extra-tip---cloudflare&quot;&gt;Extra Tip - CloudFlare&lt;/h2&gt;

&lt;p&gt;Luigi Montanez kindly pointed out in below’s comments the availability
of &lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;CloudFlare&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;CloudFlare is a proxy that sits between your website and your
users. It allegedly prevents DDOS attacks on your website, but it also
caches static content, which helps because apparently it also has the
properties of a CDN.&lt;/p&gt;

&lt;p&gt;I activated it to see how it works. The main reason is that GAE has a
1 GB bandwidth-out daily limit - and this article generated ~ 10,000
visits in only one day, which consumed ~ 700 MB of bandwidth on GAE
(for a couple of small images, I don’t want to imagine what would
happen for an image-rich post). So that’s not good and I placed
CloudFlare in front of GAE and my Heroku instance, which should save
some bandwidth for me.&lt;/p&gt;

&lt;p&gt;I don’t have a conclusion on CloudFlare. If it works as advertised,
then it is &lt;em&gt;awesome&lt;/em&gt;. Although be careful about it as I’ve seen
reports on the Internet that it may in fact add latency to your
website, instead of decreasing it.&lt;/p&gt;

&lt;p&gt;For my website however, everything seems to be fine. I am monitoring
my website with &lt;a href=&quot;http://pingdom.com&quot;&gt;Pingdom.com&lt;/a&gt;, a service which
also reports the average responsiveness of the website, calculated by
doing requests from multiple locations. The homepage, which is not
cached by CloudFlare or served by GAE, has an average load time of
300ms, while cached static resources from GAE and proxied through
CloudFlare are doing much better.&lt;/p&gt;

&lt;p&gt;So we’ll see.&lt;/p&gt;

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

&lt;p&gt;The result is a really responsive, scalable and kick-ass blog, for
zero bucks spent on hosting.&lt;/p&gt;

&lt;p&gt;This very blog is hosted using the method described above. Well, I’ll
probably return to my trustworthy VPS instance as I’m paying for it
anyway, but this was fun.&lt;/p&gt;

&lt;p&gt;Enjoy ~&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2012/01/05/blogging-for-hackers/?pk_campaign=rss&quot;&gt;Blogging Platform for Hackers&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 05 Jan 2012 00:00:00 +0000</pubDate>
  <dc:modified>Thu, 19 Dec 2019 00:00:00 +0000</dc:modified>
  <atom:modified>Thu, 19 Dec 2019 00:00:00 +0000</atom:modified>
  <link>https://alexn.org/blog/2012/01/05/blogging-for-hackers/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2012/01/05/blogging-for-hackers/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Blogging</category>
  <category>Server</category>
  <category>Cloud</category>
  <category>Heroku</category>
  <category>Ruby</category>
  <category>Jekyll</category>
  </item>


<item>
  <title>Crawling the Android Marketplace</title>
  <description>I had a very specific need for fetching the details for some apps in the Android marketplace, in an automated manner. Here I’m describing a script that I used to crawl the marketplace back in 2011.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2011/12/15/crawling-the-android-marketplace-155200-apps/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/wolf-spider.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;947&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;I had a very specific need for fetching the details for some apps in
the Android marketplace, in an automated manner. Here I&apos;m describing a
script that I used to crawl the marketplace back in 2011.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;UPDATE (2019-12-18):&lt;/strong&gt; this is an old article, the script I used no longer works, but it can still be a good starting point for building your own web crawler.
&lt;/p&gt;

&lt;p&gt;First I found &lt;a href=&quot;https://github.com/jberkel/supermarket&quot;&gt;the supermarket
gem&lt;/a&gt;, a wrapper for the
&lt;a href=&quot;http://code.google.com/p/android-market-api/&quot;&gt;Android Market API&lt;/a&gt;
Java implementation. However, it gives unpredictable results (it
wouldn’t return the details of our in-house apps or of many other
examples I tried) and Google is placing hard-limits on the number of
requests you can make per minute. This is an internal API, probably
used by the marketplace client and the implementation mentioned above
was created through reverse-engineering.&lt;/p&gt;

&lt;p&gt;This really pissed me off, this is Google, they should grok APIs. But
this info is already available from their website and so I went ahead
and crawled it.&lt;/p&gt;

&lt;p&gt;The script and the data collected are is available. Read below.&lt;/p&gt;

&lt;h2 id=&quot;how-to-do-it-by-yourself&quot;&gt;How To Do it By Yourself&lt;/h2&gt;

&lt;p&gt;The actual script that I created can be found in the
&lt;a href=&quot;https://github.com/alexandru/AndroidMarketCrawler&quot;&gt;AndroidMarketCrawler&lt;/a&gt;
GitHub Repository, with the relevant files being:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href=&quot;https://github.com/alexandru/AndroidMarketCrawler/blob/master/crawler.py&quot;&gt;crawler.py&lt;/a&gt; - source code with lots of comments, it’s really not complicated, you should go read it&lt;/li&gt;
  &lt;li&gt;marketplace_database.json_lines.bz2 - compressed file
containing the details of the crawled apps, one per each line; this
is not a proper JSON file, you use it by reading it line by line,
where each line represents a JSON object (personal preference, as
otherwise the file is pretty big and you can run out of
memory)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; The Android Marketplace explicitly bans crawling
apparently. This crawler and associated data only serves educational
purposes. Don’t abuse it.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;for app in AndroidMarketCrawler(concurrency=10):
    # app is at this point a dictionary with the details needed, like
    #  id, name, developer name, number of installs, etc...
    fh.write(json.dumps(app) + &quot;\n&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I used the Python programming language, along with
&lt;a href=&quot;http://eventlet.net&quot;&gt;Eventlet&lt;/a&gt; for fetching URLs in parallel (async I/O with
epoll/libevent, providing you with coroutines support and green
threads) and &lt;a href=&quot;http://packages.python.org/pyquery/&quot;&gt;PyQuery&lt;/a&gt; for
selecting DOM elements using CSS3 selectors (instead of XPath or
BeautifulSoup). If you fancy Ruby instead, you could use slight
equivalents such as
&lt;a href=&quot;https://github.com/igrigorik/em-http-request&quot;&gt;em-http-request&lt;/a&gt; and
&lt;a href=&quot;http://nokogiri.org/&quot;&gt;Nokogiri&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So you start fetching content from a root and add application links as
you encounter them in a queue. We are then using a (green) threadpool
to start fetching jobs for each of the links in the queue. So it’s
recursive. The results are also pushed in another queue, ready to be
consumed by the client.&lt;/p&gt;

&lt;p&gt;Be careful though, don’t abuse this, as it will generate a ton of
traffic and your IP may end up being banned by Google. It also takes a
lot of time; with good bandwidth and a VPS located in California, it
still took me 5 hours for the script to finish. Don’t abuse the
concurrency settings either, 10 is enough.&lt;/p&gt;

&lt;h2 id=&quot;155200-apps-available-from-the-us&quot;&gt;155,200 Apps Available From the US&lt;/h2&gt;

&lt;p&gt;You have to realize that this number is only approximate. Apps are
going strong in other countries, such as South Korea and Google does
Geo-IP filtering, which means some of the apps were unavailable to me,
depending on restrictions set by their developers.&lt;/p&gt;

&lt;p&gt;The numbers published by
&lt;a href=&quot;http://www.readwriteweb.com/mobile/2011/10/android-market-hits-500000-suc.php&quot;&gt;Research2Guidance in October&lt;/a&gt;
tell the story of 500,000 apps published on the Marketplace. But this
gets weird, as I took the number of downloads from those 155,200 apps
and it &lt;em&gt;matches&lt;/em&gt; the number of downloads
&lt;a href=&quot;http://android-developers.blogspot.com/2011/12/10-billion-android-market-downloads-and.html&quot;&gt;published by Google this month&lt;/a&gt;. See
below.&lt;/p&gt;

&lt;h3 id=&quot;an-average-of-1363-billion-downloads&quot;&gt;An Average of 13.63 Billion Downloads&lt;/h3&gt;

&lt;p&gt;So there have been between 5,514,202,281 and 21,545,335,515 downloads
for &lt;em&gt;free apps&lt;/em&gt;, making the average 13,529,768,898 downloads.&lt;/p&gt;

&lt;p&gt;More interesting however is that according to my data for paid apps,
the number of downloads is between 42,576,311 and 164,116,615. This
number seems rather low to me, making it clear that Android
distribution is freemium based.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2011/12/15/crawling-the-android-marketplace-155200-apps/?pk_campaign=rss&quot;&gt;Crawling the Android Marketplace&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 15 Dec 2011 00:00:00 +0000</pubDate>
  <dc:modified>Wed, 18 Dec 2019 00:00:00 +0000</dc:modified>
  <atom:modified>Wed, 18 Dec 2019 00:00:00 +0000</atom:modified>
  <link>https://alexn.org/blog/2011/12/15/crawling-the-android-marketplace-155200-apps/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2011/12/15/crawling-the-android-marketplace-155200-apps/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Python</category>
  <category>Android</category>
  <category>Web</category>
  <category>API</category>
  </item>


<item>
  <title>Android Learning Resources</title>
  <description>Starting out learning Android development may be intimidating at first, as with any new platform of reasonable complexity you’ll have a lot to learn. However the learning process is fun. So here are some learning resources that I’m currently following.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2011/12/12/android-learning-resources/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/android-development.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;800&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  Starting out learning Android development may be intimidating at first, as with any new platform of reasonable complexity you&apos;ll have a lot to learn. However the learning process is fun. So here are some learning resources that I&apos;m currently following.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;UPDATE (2019-12-18):&lt;/strong&gt; this is an old article, listing resources that may be obsolete and content that may not reflect my current views.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;DISCLAIMER:&lt;/strong&gt; the Amazon links in this article contain my affiliate code and I get a commission should you choose to buy from Amazon in the next 24 hours. However I’m including these links primarily because of the awesome reviews included, but you should buy straight from the publisher (publisher links also included, without an affiliate ID).
&lt;/p&gt;

&lt;h2 id=&quot;books-for-learning-android&quot;&gt;Books for Learning Android&lt;/h2&gt;

&lt;p&gt;My problem with books is that technical books get obsolete really
fast. Books from 2010, while still useful, are already insufficient
now with the release of Ice Cream Sandwich. The upside is that there
are a lot of books out there.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://commonsware.com&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;&lt;figure&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/books-commonsware.png&quot; width=&quot;220&quot; height=&quot;129&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;&lt;/figure&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For ~ $20 you can buy a 1-year subscription for
&lt;a href=&quot;https://commonsware.com&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;CommonsWare.com&lt;/a&gt;. The author, Mark Murphy, is
a very proficient Android developer, trainer and consultant, with a
huge &lt;a href=&quot;http://stackoverflow.com/users/115145/commonsware&quot;&gt;StackOverflow reputation&lt;/a&gt;
:) More seriously - for $20 you get 3 books that are continuously
updated, which is great.&lt;/p&gt;

&lt;p&gt;Here are the books (but don’t buy them from Amazon, as you won’t get
the 1-year subscription, which is the main reason I’m recommending
these):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0981678009/ref=as_li_ss_tl?ie=UTF8&amp;tag=bionicspirit-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0981678009&quot;&gt;The Busy Coder’s Guide to Android Development&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/098167805X/ref=as_li_ss_tl?ie=UTF8&amp;tag=bionicspirit-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=098167805X&quot;&gt;The Busy Coder’s Guide to Advanced Android Development&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0981678041/ref=as_li_ss_tl?ie=UTF8&amp;tag=bionicspirit-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0981678041&quot;&gt;Android Programming Tutorials&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://www.amazon.com/gp/product/1934356565/ref=as_li_ss_tl?ie=UTF8&amp;tag=bionicspirit-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1934356565&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;&lt;figure&gt;&lt;img src=&quot;https://alexn.org/assets/media/articles/prag_hello_android.jpg&quot; width=&quot;190&quot; height=&quot;228&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;&lt;/figure&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, don’t buy these items from Amazon. Buy them with the 1-year
subscription from the &lt;a href=&quot;http://commonsware.com&quot;&gt;Author’s Website&lt;/a&gt; (I
did so myself and btw, I have no affiliation with the author). The
subscription is useful because you’ll get upgrades for new versions of
Android and bug-fixes, for a whole year.&lt;/p&gt;

&lt;p&gt;Another book I’ve been reading is
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/1934356565/ref=as_li_ss_tl?ie=UTF8&amp;tag=bionicspirit-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1934356565&quot;&gt;Hello Android&lt;/a&gt;
by &lt;a href=&quot;http://www.zdnet.com/blog/burnette&quot;&gt;Ed Burnette&lt;/a&gt;, published by the
&lt;a href=&quot;http://pragprog.com/book/eband3/hello-android&quot;&gt;Pragmatic Programmers&lt;/a&gt;.
It’s pretty good, but it is more of an introduction (truly a Hello
World).&lt;/p&gt;

&lt;p&gt;Other books I have not tried, so my list stops here, but updates will
follow.&lt;/p&gt;

&lt;h2 id=&quot;free-stuff-available-online&quot;&gt;Free Stuff Available Online&lt;/h2&gt;

&lt;p&gt;I’m the kind of developer that prefers to rely on freely available
stuff, because I learn by doing and technical books on APIs are
boring. Plus, I like free stuff, however if you plan on getting
serious about it, then a small investment is worth it and will keep
you focused (nothing will keep you more focused than spending some
money).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://developer.android.com/guide/&quot;&gt;Android Developer Guides&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seriously, you won’t find a faster learning path than reading and
understanding the source-code of real apps. However to not attempt
doing this without going through some of the tutorials in the link
above.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://developer.android.com/videos/index.html#v=twmuBbC_oB8&quot;&gt;Videos from Google I/O&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://developer.android.com/guide/developing/index.html&quot;&gt;The Official Dev Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The videos from Google I/O are a gold mine, providing insight you
won’t find anywhere else. Highly recommended. All in all, the
official documentation is good, although lacking beginner
friendliness and a structured clear path. Plus I noticed it has
holes in it, but you’ll be fine.&lt;/p&gt;

&lt;p&gt;For asking questions, or browse around for insightful gems, there’s
nothing better than:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/questions/tagged/android&quot;&gt;The Android tag on StackOverflow.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At the time of this writing, I don’t have many Android-related
blogs to share with you and the ones I know about are of poor
quality - apparently not many people blog about their Android
experience. Hopefully this will change for the better.&lt;/p&gt;

&lt;p&gt;Please help me out in identifying other resources! Thanks!&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2011/12/12/android-learning-resources/?pk_campaign=rss&quot;&gt;Android Learning Resources&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Mon, 12 Dec 2011 00:00:00 +0000</pubDate>
  <dc:modified>Wed, 18 Dec 2019 00:00:00 +0000</dc:modified>
  <atom:modified>Wed, 18 Dec 2019 00:00:00 +0000</atom:modified>
  <link>https://alexn.org/blog/2011/12/12/android-learning-resources/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2011/12/12/android-learning-resources/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Books</category>
  <category>Android</category>
  </item>


<item>
  <title>Earning Money as an Amazon Affiliate</title>
  <description>I published an article that I&apos;ve meant to publish for a long
  time. I&apos;m usually lazy to not bother writing many articles, however
  this time I also thought about doing an experiment - you see I&apos;m (1)
  on a tight budget and (2) a cheap bastard - so what if I could get
  enough money to pay for my monthly hosting on Linode, while
  satisfying my urge to write from time to time?</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2011/11/29/earning-money-as-an-amazon-affiliate/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/amazon-associates.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;650&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I published an article that I&apos;ve meant to publish for a long
  time. I&apos;m usually lazy to not bother writing many articles, however
  this time I also thought about doing an experiment - you see I&apos;m (1)
  on a tight budget and (2) a cheap bastard - so what if I could get
  enough money to pay for my monthly hosting on Linode, while
  satisfying my urge to write from time to time?
&lt;/p&gt;

&lt;p&gt;
  As such I included Amazon Affiliate links in that post to see what
  happens.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;UPDATE (2019-12-18):&lt;/strong&gt; this is an old article, listing resources that may be obsolete and content that may not reflect my current views.
&lt;/p&gt;

&lt;h2&gt;Moral Considerations Against Amazon&apos;s Associates&lt;/h2&gt;

&lt;p&gt;
  The discussion on &lt;a href=&quot;http://news.ycombinator.com/item?id=3291167&quot; target=&quot;_blank&quot;&gt;Hacker News&lt;/a&gt; took an interesting turn. A couple
  of comments are a little unbalanced, however there&apos;s &lt;a href=&quot;http://news.ycombinator.com/item?id=3292508&quot; target=&quot;_blank&quot;&gt;a
  comment&lt;/a&gt; that I like and with which I am in agreement:
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;i&gt;
    Having affiliate links creates incentives that may not align with
    faithfully serving your readers. It does not automatically bias your
    writing, but it can certainly create the appearance of bias.
  &lt;/i&gt;
  &lt;br&gt; &lt;br&gt;
  &lt;i&gt;
    A concrete example would be writing an especially glowing review
    of the new Kindle because you have a vested stake in people buying
    them. Or, perhaps, NOT writing a glowing review because you fear
    it will be perceived as shilling for affiliate cash.
  &lt;/i&gt;
  &lt;br&gt; &lt;br&gt;
  &lt;i&gt;
    In fact On The Media recently did a story about the Washington
    Post struggling with whether or not to include Amazon affiliate
    links in its book reviews. I think it presents both sides of the
    argument: &lt;a href=&quot;http://www.onthemedia.org/2011/nov/11/web-links-money-makers/transcript/&quot; target=&quot;_blank&quot;&gt;www.onthemedia.org/2011/nov/11/web-links...&lt;/a&gt;
  &lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
  This comment is striking, as when I started fantasizing about where
  should I go from here, the one thing that crossed my mind was that I
  could write a review for the Kindle (I own one) - and oops,
  unfortunately in that instance my actual opinion would have been
  &lt;i&gt;unfaithful&lt;/i&gt; - &lt;a href=&quot;http://www.elidickinson.com/&quot; target=&quot;_blank&quot;&gt;@esd&lt;/a&gt; nailed it.
&lt;/p&gt;

&lt;p&gt;
  Also, &lt;a href=&quot;http://news.ycombinator.com/item?id=3292777&quot;&gt;a
  reply&lt;/a&gt; puts the above in balance:
&lt;/p&gt;

&lt;p class=&quot;dialog&quot;&gt;
  &lt;i&gt;
    Newspapers likely disallow such practices in order to maintain
    journalistic integrity, but a blog author who is writing posts on
    purpose to sell things is probably not interested in maintaining
    journalistic integrity. The blog author is just interested in
    selling stuff. Maybe the blog posts are well-written and
    interesting, or maybe they are not. If they are not, then readers
    who care principally about content will likely avoid the blog on the
    lack of merit of the content itself.
  &lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
  (the quality of Hacker News still amazes me)
&lt;/p&gt;

&lt;p&gt;
  In my oppinion, putting affiliate links is not bad or evil per se -
  for instance you could say that customers of Apple or Google have an
  inherent bias because they feel the need to protect their monetary
  and/or emotional investment. And we aren&apos;t professional journalists,
  trained to watch out for such things - but a mistake is a
  mistake. So from now on, no more Amazon-related reviews coming from
  me (maybe I&apos;ll try clearly delimited boxes or something).
&lt;/p&gt;

&lt;h2&gt;Some Facts and Stats&lt;/h2&gt;

&lt;p&gt;
  The article I&apos;m talking about:
&lt;/p&gt;

&lt;p&gt;
  &lt;a href=&quot;https://alexn.org/blog/2011/11/25/4-books-for-learning-to-design-the-hard-way/&quot;&gt;4 Books for Learning to Design, the Hard Way&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
  I published this article on the 25th, &lt;i&gt;The Black Friday&lt;/i&gt; - so
  it had perfect timing. Then I pushed this link to Hacker News and
  Reddit. I hope you will forgive me, since this was a little
  self-promotion and I don&apos;t deny it, however I hope you found the
  content therein to be worth it, as it was published with my best
  intentions.
&lt;/p&gt;

&lt;p&gt;
  The resulting traffic and the fee that Amazon gives for the orders
  generated took me by surprise. Here&apos;s how my traffic looks like
  (unique visitors):
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Nov 24: 45&lt;/li&gt;
  &lt;li&gt;Nov 25: 10,263&lt;/li&gt;
  &lt;li&gt;Nov 26: 6,939&lt;/li&gt;
  &lt;li&gt;Nov 27: 1,713&lt;/li&gt;
  &lt;li&gt;Nov 28: 1,299&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Wow. I never generated this much traffic with my blog. Also, here&apos;s
  the Amazon stats (updated for Nov 28th):
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ordered items: 333&lt;/li&gt;
  &lt;li&gt;Clicks: 6,259&lt;/li&gt;
  &lt;li&gt;Conversion: 5.32%&lt;/li&gt;
  &lt;li&gt;Total items shipped: 294&lt;/li&gt;
  &lt;li&gt;Total earnings: $367.10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  So considering that not all items have been shipped and this ain&apos;t
  over yet (I&apos;m still getting traffic), we&apos;re looking at:
  a half-an-hour effort for a single article, earning &lt;b&gt;$400&lt;/b&gt;, in
  4 days, on a very low-traffic personal blog.
&lt;/p&gt;

&lt;p&gt;
  My goal was achieved too - I now have enough money for ~20 months of
  hosting on Linode. Thank you dear readers, I am in your debt.
&lt;/p&gt;

&lt;h2&gt;Amazon Associates versus Google AdSense&lt;/h2&gt;

&lt;p&gt;
  &lt;i&gt;Google AdSense&lt;/i&gt; rewards are &lt;i&gt;per-click&lt;/i&gt; and is the first
  option of many webmasters, because it does generate more
  money. However I feel that the overall user experience suffers a lot
  - the links served may be context-dependent, but the quality is poor.
&lt;/p&gt;

&lt;p&gt;
  &lt;i&gt;Amazon Associates&lt;/i&gt; rewards are instead &lt;i&gt;per-action&lt;/i&gt;. When
  the user buys something, you get a referral fee. This can work very
  well because the items displayed are hand-picked by you and the
  links add value to your content - whenever I search for reviews of
  individuals (which I trust more than those of experts), my first
  stop is on Amazon.
&lt;/p&gt;

&lt;h2&gt;Why A Single Flower Doesn&apos;t Bring Spring&lt;/h2&gt;

&lt;p&gt;
  So whenever anybody does this successfully, the appetite only grows
  bigger. After all, this kind of revenue has the potential of being
  passive. However don&apos;t get your hopes up:
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    in this instance, the timing was perfect and so the circumstances
    can&apos;t be reproduced every month
  &lt;/li&gt;
  &lt;li&gt;
    to have constant conversions you need a big and loyal following
    that trusts your recommendations
  &lt;/li&gt;
  &lt;li&gt;
    to have a big and loyal following, you also need lots of traffic
    driven by search engines
  &lt;/li&gt;
  &lt;li&gt;
    to score well in search engines, you need lots of articles with
    lots of keywords and good ranking
  &lt;/li&gt;
  &lt;li&gt;
    to have loyal readers and a good ranking on Google, those articles
    must be high-quality
  &lt;/li&gt;
  &lt;li&gt;
    it takes lots and lots of work for the above, probably 1 or 2
    years, considering you have the talent of writing content already,
    or the money to hire people to do it
  &lt;/li&gt;
  &lt;li&gt;
    if you can&apos;t recommend anything else other than books, then you&apos;re
    screwed, as you don&apos;t have the time to read so many
  &lt;/li&gt;
  &lt;li&gt;
    if the products getting recommended are not relevant to your
    audience, then they won&apos;t convert
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  So there you have it. My experiment with Amazon&apos;s Associates, while
  probably a short one, has brought joy in my heart :)
&lt;/p&gt;

&lt;p&gt;
  Thank you,
&lt;/p&gt;


      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2011/11/29/earning-money-as-an-amazon-affiliate/?pk_campaign=rss&quot;&gt;Earning Money as an Amazon Affiliate&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 29 Nov 2011 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2011/11/29/earning-money-as-an-amazon-affiliate/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2011/11/29/earning-money-as-an-amazon-affiliate/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  </item>


<item>
  <title>4 Books For Learning to Design, The Hard Way</title>
  <description>I present some books I enjoyed, which is the path I’m taking to get better at design and user experience.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2011/11/25/4-books-for-learning-to-design-the-hard-way/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/book-design-all.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1915&quot; height=&quot;648&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  This is the path I&apos;m taking to &lt;i&gt;not suck&lt;/i&gt; at design anymore, as
  frankly, I&apos;m getting tired of sucking. I&apos;ve read the first 3 books
  here and I&apos;m having progress on the last one. I highly recommend all
  4.
&lt;/p&gt;

&lt;h2&gt;The Design of Everyday Things (&lt;a href=&quot;http://www.amazon.com/gp/product/0465067107/&quot; rel=&quot;nofollow&quot; title=&quot;The Design of Everyday Things&quot; target=&quot;_blank&quot;&gt;link&lt;/a&gt;)&lt;/h2&gt;

&lt;a href=&quot;http://www.amazon.com/gp/product/0465067107/&quot; title=&quot;The Design of Everyday Things&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;
  &lt;figure&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/book-design-1.jpg&quot; style=&quot;max-width:100%;height:auto;&quot; width=&quot;677&quot; height=&quot;1023&quot;&gt;
  &lt;/figure&gt;
&lt;/a&gt;

&lt;p&gt;
  It explains the design of common household objects that you may use
  daily and it is one of the best books you can read on user
  experience.
&lt;/p&gt;

&lt;p&gt;
  To me this was an eye opener that completely changed the way I think
  about interfaces. It explains how people interact with the objects
  around them and how they learn. It explains the importance of a
  user&apos;s mental model of how your product works. It gives you a good
  feeling on what it means and why it matters to &lt;i&gt;design for
  errors&lt;/i&gt;. It helps you to prevent a lot of design errors that a
  lot of products have.
&lt;/p&gt;

&lt;p style=&quot;clear:both;&quot;&gt;
  The book itself was written in 1990, so it does have here and there
  some references to products that are outdated, but the analysis
  itself will never be outdated or obsolete. Quite the contrary - it&apos;s
  fascinating how user centric design guidlines &lt;i&gt;stay the same&lt;/i&gt;,
  even though there are a lot of people out there that repeat the same
  mistakes over and over again.
&lt;/p&gt;

&lt;p&gt;
  When it comes to software, a complement article on the subject is &lt;a href=&quot;http://www.joelonsoftware.com/uibook/fog0000000249.html&quot;&gt;User
  Interface Design For Programmers&lt;/a&gt;, by Joel Spolsky.
&lt;/p&gt;

&lt;h2&gt;Non-Designer&apos;s Design Book (&lt;a href=&quot;http://www.amazon.com/gp/product/0321534042/&quot; rel=&quot;nofollow&quot; title=&quot;Non-Designer&apos;s Design Book&quot; target=&quot;_blank&quot;&gt;link&lt;/a&gt;)&lt;/h2&gt;

&lt;a href=&quot;http://www.amazon.com/gp/product/0321534042/&quot; title=&quot;Non-Designer&apos;s Design Book&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;
  &lt;figure&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/book-design-2.jpg&quot; width=&quot;454&quot; height=&quot;648&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
  &lt;/figure&gt;
&lt;/a&gt;

&lt;p&gt;
  Robin Williams does an excelent job introducing you to the basic
  concepts of designing visuals, with clearly explained principles and
  techniques.
&lt;/p&gt;

&lt;p&gt;
  It&apos;s pretty hard for us developers to design anything pleasing to
  the eye. And that&apos;s not the only problem you&apos;re facing - the visuals
  of a site have to give hints to the user about their next actions,
  so you&apos;ve got many constraints to worry about. Sometimes you get
  lucky by just copying and combining other designs you
  like. Sometimes you have a good idea about what you want, but one
  day you like the result, then the next it looks like an abomination.
&lt;/p&gt;

&lt;p&gt;
  The book goes into some detail about how designers think. It has
  plenty of visual examples, it gives you many examples of what &lt;i&gt;not
  to do&lt;/i&gt;, it explains how to work around those problems, it is
  concise and doesn&apos;t bore you to tears - while not that useful for
  someone with design experience, for a developer that sucks at this
  game, this is a really, really good design manual.
&lt;/p&gt;

&lt;h2&gt;Color: A Course in Mastering the Art of Mixing Colors (&lt;a href=&quot;http://www.amazon.com/gp/product/1585422193/&quot; rel=&quot;nofollow&quot; title=&quot;Color: A Course in Mastering the Art of Mixing Colors&quot; target=&quot;_blank&quot;&gt;link&lt;/a&gt;)&lt;/h2&gt;

&lt;a href=&quot;http://www.amazon.com/gp/product/1585422193/&quot; rel=&quot;nofollow&quot; title=&quot;Color: A Course in Mastering the Art of Mixing Colors&quot; target=&quot;_blank&quot;&gt;
  &lt;figure&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/book-design-3.jpg&quot; style=&quot;max-width:100%;height:auto;&quot; width=&quot;800&quot; height=&quot;975&quot;&gt;
  &lt;/figure&gt;
&lt;/a&gt;

&lt;p&gt;
  One of the most surprisingly difficult problems when creating
  designs is picking the colors palette. This is so goddamn difficult
  sometimes. We do know that certain color combinations work better
  than others, but how do you pick them? How can you achieve
  &lt;i&gt;harmony&lt;/i&gt; as to not make your users&apos; eyes bleed?

  And not only that, but you also want to emphasise certain portions
  of your pages in a way to attract attention - did you know that
  according to statistics, &lt;i&gt;more car accidents involve red cars than
  any other color?&lt;/i&gt;
&lt;/p&gt;

&lt;p&gt;
  There are web services out there, like &lt;a href=&quot;http://kuler.adobe.com/&quot;&gt;Adobe Kuler&lt;/a&gt; or &lt;a href=&quot;http://www.colourlovers.com/&quot;&gt;COLOURlovers.com&lt;/a&gt; which allow you to choose color
  palettes created by other people - the PROBLEM being that you&apos;ll
  never know what makes a palette work and so you&apos;ll make good changes
  to it only by luck or with expensive A/B testing.
&lt;/p&gt;

&lt;p&gt;
  This book by Betty Edwards is not your only choice for learning
  Color Theory. It isn&apos;t even related to web design in any way, having
  a whole section on mixing oil paint.
&lt;/p&gt;

&lt;p&gt;
  However, I believe that color theory can only be learned from people
  that have real experience in mixing colors. For this reason,
  articles or books about color theory that aren&apos;t written by painters
  are quite shallow - and the theory in this book transcends the tools
  used.
&lt;/p&gt;

&lt;p&gt;
  It explains notions on color harmony, on the importance of contrast
  and gives you valuable insight and advices on how to mix and match
  colors. It&apos;s a fun read too, because of the quotes from faimous
  people contained - however, it&apos;s not a light read because you do
  have to execute the exercises within for best results. But I think
  it is worth it.
&lt;/p&gt;

&lt;p&gt;
  (I&apos;m now my wife&apos;s advisor on colors, although our bedroom ended up
  looking awful, but there&apos;s no substitute for experience earned by
  making mistakes and at least I know where I went wrong ;))
&lt;/p&gt;

&lt;h2&gt;Drawing on the Right Side of the Brain (&lt;a href=&quot;http://www.amazon.com/gp/product/0874774195/&quot; rel=&quot;nofollow&quot; title=&quot;The New Drawing on the Right Side of the Brain&quot; target=&quot;_blank&quot;&gt;link&lt;/a&gt;)&lt;/h2&gt;

&lt;a href=&quot;http://www.amazon.com/gp/product/0874774195/&quot; rel=&quot;nofollow&quot; title=&quot;The New Drawing on the Right Side of the Brain&quot; target=&quot;_blank&quot;&gt;
  &lt;figure&gt;
    &lt;img src=&quot;https://alexn.org/assets/media/articles/book-design-4.jpg&quot; style=&quot;max-width:100%;height:auto;&quot; width=&quot;800&quot; height=&quot;1034&quot;&gt;
  &lt;/figure&gt;
&lt;/a&gt;

&lt;p&gt;
  I&apos;ve picked up drawing as my hobby. I&apos;m only a beginner, but it&apos;s
  a fun hobby to have - it&apos;s impressive, silent and inexpensive. It also
  boosts your creativity like nothing else, as the only real limit you
  have is your imagination (much like software development ;))
&lt;/p&gt;

&lt;p&gt;
  Ever tried drawing anything lately? You should. The results will be
  awful. But do you know why? It&apos;s not your hand, it&apos;s not from a lack
  of talent, it&apos;s your eyes that are deceiving you - &lt;i&gt;in order to
  learn how to draw, you have to relearn how to see&lt;/i&gt;. That&apos;s
  because everything you see is right now filtered and transformed by
  your brain - as a cheap/fast exercise, look in a mirror at an arm&apos;s
  length and take a guess if your mirrored head is of the same size as
  your actual head (then use your hands to measure). The picture
  you&apos;re getting through your mind&apos;s eye is deceiving and for drawing
  skill and creativity to emerge you have to silence your brain.
&lt;/p&gt;

&lt;p&gt;
  This book of Betty Edwards has an awesome technique that works for
  everybody. Or so she says, but as far as I&apos;m concerned I&apos;m
  progressing in leaps and bounds and can already do drawings that I
  couldn&apos;t hope of doing before starting to read this book ... I also
  promise to publish some drawings, but only after I&apos;ll get decent
  (only started to do this 2 months ago, a frog doesn&apos;t transform into
  a prince overnight you know).
&lt;/p&gt;

&lt;p&gt;
  How does drawing help you in web design? Well, do you really have to
  ask?
&lt;/p&gt;

&lt;h2&gt;Update: Suggestions Received from Readers&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0201362988/&quot; target=&quot;_blank&quot;&gt;The Design of Design&lt;/a&gt;, by Frederick P. Brooks&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/1592537413/&quot; target=&quot;_blank&quot;&gt;Visual Language for Designers&lt;/a&gt;, by Connie Malamed&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0300115954/&quot; target=&quot;_blank&quot;&gt;Interaction of Color&lt;/a&gt;, by Josef Albers (&lt;a href=&quot;http://www.handprint.com/HP/WCL/book3.html#albers&quot; rel=&quot;nofollow&quot;&gt;review&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0891343377/&quot; target=&quot;_blank&quot;&gt;Keys to Drawing&lt;/a&gt;, by Bert Dodson&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/1119998956/&quot; target=&quot;_blank&quot;&gt;Design for Hackers&lt;/a&gt;, by David Kadavy&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0442240392/&quot; target=&quot;_blank&quot;&gt;Design and Form&lt;/a&gt;, by Johannes Itten&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/041238390X/&quot; target=&quot;_blank&quot;&gt;Elements of Color&lt;/a&gt;, by Johannes Itten&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0471285528/&quot; target=&quot;_blank&quot;&gt;Principles of Form and Design&lt;/a&gt;, by Wucius Wong&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0898150523/&quot; target=&quot;_blank&quot;&gt;Thinking with a Pencil&lt;/a&gt;, by Henning Nelms&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0262691914/&quot; target=&quot;_blank&quot;&gt;The Sciences of the Artificial&lt;/a&gt;, by Herbert A. Simon&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/3764384840/&quot; target=&quot;_blank&quot;&gt;Designerly Ways of Knowing&lt;/a&gt;, by Nigel Cross&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0133033899/&quot; target=&quot;_blank&quot;&gt;Designing Visual Interfaces&lt;/a&gt;, by Kevin Mullet and Darrell Sano&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/1568984650/&quot; target=&quot;_blank&quot;&gt;Grid Systems: Principles of Organizing Type&lt;/a&gt;, by Kimberly Elam (&lt;a href=&quot;http://filtercake.tumblr.com/post/7999571798/design-is-not-decoration&quot; rel=&quot;nofollow&quot;&gt;presentation&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://www.amazon.com/gp/product/0262062666/&quot; target=&quot;_blank&quot;&gt;101 Things I Learned in Architecture School&lt;/a&gt;, by Matthew Frederick&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
  Thanks people, wow, I know have my hands full :) ... keep `em coming!
&lt;/p&gt;


      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2011/11/25/4-books-for-learning-to-design-the-hard-way/?pk_campaign=rss&quot;&gt;4 Books For Learning to Design, The Hard Way&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 25 Nov 2011 00:00:00 +0000</pubDate>
  <dc:modified>Mon, 16 Jan 2023 07:03:55 +0000</dc:modified>
  <atom:modified>Mon, 16 Jan 2023 07:03:55 +0000</atom:modified>
  <link>https://alexn.org/blog/2011/11/25/4-books-for-learning-to-design-the-hard-way/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2011/11/25/4-books-for-learning-to-design-the-hard-way/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Best Of</category>
  <category>Books</category>
  </item>


<item>
  <title>How I Use Flickr: For Backup</title>
  <description>I’ve got a growing number of personal pictures and the collection is growing since 2003 … Pro accounts on Flickr have unlimited storage and can upload and access full-resolution pictures.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2011/10/29/how-i-use-flickr/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/flickr.jpg?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;800&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I&apos;ve got a growing number of personal pictures and the collection is growing since 2003, when I got my first digital camera, a shitty Sanyo that still works and that I still use whenever I forget about my Nikon.
&lt;/p&gt;

&lt;p&gt;But here’s the thing with digital pictures - &lt;em&gt;&lt;strong&gt;they are cheap to make, but also easy to lose&lt;/strong&gt;&lt;/em&gt;. Digital storage is not as reliable as glossy paper. Pictures printed on paper can easily last for a 100 years. That’s not the case with any digital storage medium and we will suffer for it.&lt;/p&gt;

&lt;h2 id=&quot;storing-my-pictures-in-the-cloud&quot;&gt;Storing My Pictures In The Cloud&lt;/h2&gt;

&lt;p&gt;Pro accounts on Flickr have unlimited storage and can upload and access full-resolution pictures. This is great, although be careful about believing in “unlimited plans”, as nothing is really unlimited and by abusing Flickr you may find yourself locked out of your account.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;UPDATE (2019-12-15):&lt;/strong&gt; since Flickr has been acquired by SmugMug, the free accounts no longer have unlimited, or the 1 TB of space we had in the Yahoo days. Pro accounts continue to have unlimited storage, but you have to keep paying for Pro, otherwise they’ll eventually delete your archive.
&lt;/p&gt;

&lt;p&gt;Unfortunately the tools for uploading really suck and I haven’t encountered yet a graphical interface that did what I needed. So for synchronizing, I’ve built my own script in Ruby using the excelent &lt;a href=&quot;https://hanklords.github.com/flickraw/&quot;&gt;Flickraw gem&lt;/a&gt; and &lt;a href=&quot;https://github.com/remvee/exifr&quot;&gt;exifr&lt;/a&gt;, another Ruby gem that reads Exif headers from Jpeg files.&lt;/p&gt;

&lt;p&gt;One common problem is that you ALWAYS have duplicates. And you don’t want to upload duplicates. What you really want is an “&lt;em&gt;rsync&lt;/em&gt;” command for Flickr. But how do you know if a picture was already uploaded?&lt;/p&gt;

&lt;p&gt;The approach I’m using is to add a &lt;a href=&quot;http://www.flickr.com/groups/api/discuss/72157594497877875/&quot;&gt;machine tag&lt;/a&gt; to my pictures, which is set like a tag, but has the format “namespace:key=value”. This machine tag represents the MD5 hash of the picture and if you want to see if a certain photo was already uploaded to flickr, you can always &lt;a href=&quot;https://www.flickr.com/services/api/flickr.photos.search.html&quot;&gt;search for it&lt;/a&gt;. Here’s how it looks on one of my pictures:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;checksum:md5=5b2fa91c38a7f878088e1420b924e6d9
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Besides this, I have this problem with some of the older photos taken by my Sanyo, where the taken-date is totally fucked and for personal photos the taken date is maybe more important than the actual photo quality. I use the excelent &lt;a href=&quot;http://www.sno.phy.queensu.ca/~phil/exiftool/&quot;&gt;ExifTool&lt;/a&gt; to correct those photos. It’s nice building on the hard work of other people ;)&lt;/p&gt;

&lt;p&gt;So, currently I have 3545 pictures uploaded on Flickr in full resolution and the number will more than triple as soon as I make an inventory of my pictures stored on old hardware I’ve got lying around.&lt;/p&gt;

&lt;p&gt;It is fun being a developer. I can make shit happen.&lt;/p&gt;

&lt;h2 id=&quot;flickr-is-not-a-reliable-backup&quot;&gt;Flickr is Not A Reliable Backup&lt;/h2&gt;

&lt;p&gt;Flickr is an online service that isn’t meant for being a backup. I share only a fraction of what I upload, everything else is &lt;em&gt;family only&lt;/em&gt;. They may terminate your account at any time for whatever reason. They may also go out of business. Yahoo may sell it, etc, etc… I do think Flickr is awesome btw and one reason that I store my photos on Flickr is to be able to always have the whole archive with me. But for backup alone, that’s not enough.&lt;/p&gt;

&lt;p&gt;What you really need to do is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;your main repository should be stored locally and properly maintained - I do that on my main computer currently, but multi-TB external hard-drives are cheap&lt;/li&gt;
  &lt;li&gt;in case of cloud backup, you always need a secondary service for redundancy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google’s Picasa is a good option because you can explicitly buy storage. This means that if you pay for 80 GB of storage nobody is going to get upset that you uploaded 80 GB of private photos … also, if your photo collection matters to you, I wouldn’t put my trust in their Google+ offering (photos of up to 2048x2048 pixels do not count towards your free quota). That’s because that offer is not meant for you. Just pay up.&lt;/p&gt;

&lt;p&gt;So on Google’s Picasa, I’m currently working on integrating with their API too. The desktop app is nice, but too limited for me.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2011/10/29/how-i-use-flickr/?pk_campaign=rss&quot;&gt;How I Use Flickr: For Backup&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sat, 29 Oct 2011 00:00:00 +0000</pubDate>
  <dc:modified>Sun, 10 Apr 2022 10:02:46 +0000</dc:modified>
  <atom:modified>Sun, 10 Apr 2022 10:02:46 +0000</atom:modified>
  <link>https://alexn.org/blog/2011/10/29/how-i-use-flickr/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2011/10/29/how-i-use-flickr/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Cloud</category>
  <category>API</category>
  <category>Ruby</category>
  </item>


<item>
  <title>Why I Find Heroku Suboptimal</title>
  <description>Heroku is great. It basically allows you to avoid growing-up. The deployment itself couldn’t be simpler, and when browsing their web interface for available add-ons, I feel like a child in a candy-store. But I’ve outgrown it.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2011/10/23/why-i-find-heroku-suboptimal/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/heroku.png?202603060940&quot; alt=&quot;&quot; width=&quot;1440&quot; height=&quot;608&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  I love freebies. I often find myself compelled to search for the best price / convenience ratio, and from this perspective you cannot really argue against something offered for free. And yet, here I am bitching and moaning about Heroku.
&lt;/p&gt;

&lt;p&gt;Heroku provides a free-quota that’s a LOT more reasonable than all the shitty PHP hosting offerings out there. And when time comes to scale, it lets you scale nicely for a price.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;UPDATE (Oct 21, 2013):&lt;/strong&gt; This article is outdated, sort of. Heroku’s Cedar stack is awesome and cost-effective if you can design your app to be efficient in terms of throughput (which you can only achieve if you use a platform capable of high performance, like the JVM). I still think that when starting out, the next step after the free Heroku dyno, is to get your own VPS.
&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  &lt;strong&gt;UPDATE (Dec 18, 2019):&lt;/strong&gt; this is an old article, listing resources that may be obsolete and content that may not reflect my current views.
&lt;/p&gt;

&lt;p&gt;Normally you develop your app on your localhost (which is like this warm and cozy place for all developers, &lt;em&gt;no place like 127.0.0.1&lt;/em&gt; and all that), but then you want to deploy. You have to get out of your comfort zone and face the jungle and it’s a true jungle out there, filled with shitty / underpowered and expensive hosting offerings. If going for a normal VPS, you’ll have to configure your application server, your database server, your webserver that sits on top, maybe a reverse proxy cache, a memcached instance or two, a load balancer, a firewall, an email server and it goes on and on. And if going for a classic shared-hosting environment, then God help you.&lt;/p&gt;

&lt;p&gt;There’s a reason children with happy childhoods don’t want to grow up - the world is an ugly and scary place.&lt;/p&gt;

&lt;h2 id=&quot;git-push-heroku-master&quot;&gt;git push heroku master&lt;/h2&gt;

&lt;p&gt;Heroku is great. It basically allows you to avoid growing-up. The deployment itself couldn’t be simpler, and when browsing their web interface for available add-ons, I feel like a child in a candy-store.&lt;/p&gt;

&lt;p&gt;Basically you start with a free worker, to which you can add other “free” services, like a 5MB PostgreSql database and a 5MB Memcached instance, allowing you to prototype stuff. They even have plugins from third-parties that give you freebies, like a 250MB CouchDB, or a 240MB MongoDB. Then as you grow, you start adding more and more resources as needed. This has been labeled as &lt;em&gt;platform as a service&lt;/em&gt; and it’s what the cool kids are talking about these days. Heck, there are people that are living within that free-quota without problems. One such example that I know of is &lt;a href=&quot;http://tzigla.com&quot;&gt;http://tzigla.com&lt;/a&gt; … or it was last time I talked to the authors, both acquaintances of mine, and Cristi described how he ended-up doing lots of workarounds to get around limitations and he was really excited about how everything fell into place.&lt;/p&gt;

&lt;p&gt;But as I was sitting there admiring their determination and skill, I started wondering why the hell haven’t they rented a normal VPS?&lt;/p&gt;

&lt;p&gt;I mean really, if you end up pulling all kinds of crap to get around limitations, wouldn’t it be better to just pay up? And if you’re short on cash or you’re the kind of entrepreneur that likes to spend frugally, then wouldn’t you be better just renting a normal VPS? I asked him just that of course, and his reply was basically:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hate to do sys-admin stuff, installing and upgrading packages and all that&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But it doesn’t have to be that way. It’s really not that hard. The reason for these feelings is the Ubuntu I have had installed on my primary laptop for 5 years already. Once you work with Ubuntu or your favorite Linux distribution, every day, configuring a web-server for starters is something like a half-an-hour chore. Or let’s say 1 hour, and then it’s done. And you don’t have to worry about it again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And there are disadvantages to Heroku&lt;/strong&gt;, lots of them: that’s because you lose control and end up on top of a platform that’s designed as a common denominator to appeal to all needs in an equally substandard manner.&lt;/p&gt;

&lt;h2 id=&quot;example-1-nginx&quot;&gt;Example 1: Nginx&lt;/h2&gt;

&lt;p&gt;Nginx is a freakishly fast web server that consumes really few resources. Its main appeal is in serving static files and you do have static files to serve. When you grow you may want to move those static files to a CDN, like CloudFront, which serves content from locations closer to the actual users, but for serving css/javascript and small images - a properly configured Nginx is all you need. And you can’t really move any files served from your main domain to a CDN (like HTML content).&lt;/p&gt;

&lt;p&gt;You can also be smart about semi-static pages in Rails - you can cache the output inside the &lt;em&gt;public/&lt;/em&gt; directory to be served by Nginx. And if you still want to hit your controller on every request, like when doing A/B Testing on a page, you can send an &lt;em&gt;X-Accel-Redirect&lt;/em&gt; header in your response to Nginx and let Nginx to the actual content streaming for you. You can also instruct Nginx to serve files from different locations, based on certain variables like the domain name, thus avoiding hitting the Rails application server on every request.&lt;/p&gt;

&lt;p&gt;There’s a lot you can do with Nginx if you’re on a budget, and yet this is not possible within Heroku … which even though it may use Nginx as an http reverse proxy, it certainly doesn’t use it for serving static files. All files are thus served by hitting the Rails server, unless Varnish is involved.&lt;/p&gt;

&lt;h2 id=&quot;example-2-varnish&quot;&gt;Example 2: Varnish&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.varnish-cache.org/&quot;&gt;Varnish&lt;/a&gt; is described as being a &lt;em&gt;web application accelerator&lt;/em&gt; and the things it can do are truly mind-blowing.&lt;/p&gt;

&lt;p&gt;Varnish sits in front of your application servers. It can do &lt;em&gt;load-balancing&lt;/em&gt; for you with extreme efficiency, although that’s not its main purpose. Its main purpose is to cache content.&lt;/p&gt;

&lt;p&gt;When caching content you have an extreme freedom to specify the Key for fetching cached items. You can use anything when instructing Varnish on what and how to cache, like cookies or the user’s IP or any HTTP header. Do you want to also cache content for logged-in users, even though that content is slightly different from user to user? Not a problem. The configuration language is also extremely flexible, allowing you to tap in the request pipeline with any custom behavior you want. The performance of Varnish coupled with this extreme flexibility is what makes it great. It also has this uncanny ability to reload its configuration without restarting or dropping active connections.&lt;/p&gt;

&lt;p&gt;Heroku has Varnish in its stable stack, called Bamboo. But you cannot configure it. The configuration is the same for everybody … you basically set expiry headers on your response, Varnish caches it for you and the cache gets invalidated on every new deployment.&lt;/p&gt;

&lt;p&gt;This is actually good and has given rise to the famous Heroku use-case: hosting mostly static websites on it. But Varnish can be much more than that, otherwise it kind of gets in your way, and surprise - Heroku is pulling Varnish out of the configuration, starting with the new Celadon Cedar stack. This is because Varnish gets in the way of their ambitious plans: to make heroku platform-agnostic, thus adding support for Node.js and long-pooling.&lt;/p&gt;

&lt;p&gt;The now recommended alternative for serving cached static content is to use Rack::Cache in combination with their Memcached add-on. But this sucks because (1) it hits the Rails server on every request and in the free plan you only have a single process to serve those requests + (2) the free plan for Memcached is only 5MB.&lt;/p&gt;

&lt;h2 id=&quot;example-3-asynchronous-jobs&quot;&gt;Example 3: asynchronous jobs&lt;/h2&gt;

&lt;p&gt;One common-sense approach to not having a sluggish web interface is to get slow code out of your HTTP process. Lots of libraries and plugins are available for all web frameworks, like &lt;em&gt;delayed_job&lt;/em&gt; for Rails or &lt;em&gt;Celery&lt;/em&gt; for Django. And you can just write your own half-baked jobs queue and shove it in your cron.&lt;/p&gt;

&lt;p&gt;You cannot have asynchronous jobs using Heroku’s free plan. You must get an extra dyno for that.&lt;/p&gt;

&lt;h2 id=&quot;price-comparison-with-linode&quot;&gt;Price comparison with Linode&lt;/h2&gt;

&lt;p&gt;The cheapest &lt;a href=&quot;http://www.linode.com/?r=c7376c22b7853329bfb629a54dc9a843be935c36&quot;&gt;Linode instance&lt;/a&gt; is &lt;strong&gt;$20&lt;/strong&gt; per month, and for starters you can have …&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1 Nginx server&lt;/li&gt;
  &lt;li&gt;2 Passenger/Rails processes&lt;/li&gt;
  &lt;li&gt;1 worker for processing asynchronous jobs, it can even be a plain cron-job ; you do have complete flexibility in configuring cron-jobs&lt;/li&gt;
  &lt;li&gt;1 PostgreSQL database, configured for 256MB RAM usage, with 18 GB of storage. It’s not much, but it isn’t &lt;em&gt;shared&lt;/em&gt; either and does just fine, trust me … btw, the &lt;a href=&quot;http://pgmag.org/&quot;&gt;PostgreSQL magazine&lt;/a&gt; (first issue) has an article about configuring/optimizing PostgreSQL’s memory usage&lt;/li&gt;
  &lt;li&gt;1 Postfix email server, for bug reports + sending all the spam you want (Linode lets you configure reverse DNS lookup, so you can have a cheap email server that doesn’t trigger spam alerts)&lt;/li&gt;
  &lt;li&gt;ability to serve for any domain you want, including wildcard subdomains&lt;/li&gt;
  &lt;li&gt;your own SSL certificate, for free depending on provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The equivalent Heroku configuration would cost a minimum of &lt;strong&gt;$114 per month&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So lets say that you’re growing and you want to add Ronin, Heroku’s plan for a database of 1.7 GB &lt;em&gt;hot data set&lt;/em&gt; (whatever the fuck that means). That will cost you a whooping &lt;strong&gt;$200 per month&lt;/strong&gt; extra, versus &lt;strong&gt;$80&lt;/strong&gt; for a 2GB of RAM instance on Linode, or even better, $160 for a 4GB of RAM instance.&lt;/p&gt;

&lt;h2 id=&quot;linode-sucks-too-but-thats-besides-the-point&quot;&gt;Linode sucks too, but that’s besides the point&lt;/h2&gt;

&lt;p&gt;You lose the ability to increase your dynos in response to traffic surges. On the other hand you’ll be amazed at how much you can squeeze out of your rented hardware and if a properly configured setup fails to serve, then the problems you have probably can’t be solved by just adding extra web servers.&lt;/p&gt;

&lt;p&gt;Really, do some reading on why Reddit is down so often. Do some reading on why Amazon’s EBS is completely unreliable for databases (btw, Heroku does use EBS and they’ve also had their share of downtime due to AWS experiencing problems).&lt;/p&gt;

&lt;p&gt;Stop fearing the penguin and start configuring your own damn servers. As with everything that’s actually worth it in life (like having children of your own), it’s hard at first but the return of investment will be tenfold.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2011/10/23/why-i-find-heroku-suboptimal/?pk_campaign=rss&quot;&gt;Why I Find Heroku Suboptimal&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 23 Oct 2011 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 16:15:16 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 16:15:16 +0000</atom:modified>
  <link>https://alexn.org/blog/2011/10/23/why-i-find-heroku-suboptimal/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2011/10/23/why-i-find-heroku-suboptimal/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Heroku</category>
  <category>Server</category>
  <category>Cloud</category>
  </item>


<item>
  <title>Cross-Domain, Cross-Browser AJAX Requests</title>
  <description>This article describes how to make cross-browser requests, in all browsers (including IExplorer 6), using web standards along with fallbacks and without using a proxy or JSONP (which is limited and awkward) – as long as you control the destination server, or if the destination server allows.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2011/03/24/cross-domain-requests/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/cors-ajax.png?202603060940&quot; alt=&quot;&quot; width=&quot;1368&quot; height=&quot;328&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  This article describes how to make cross-browser requests, in all browsers (including &lt;u&gt;IExplorer 6&lt;/u&gt;), using web standards along with fallbacks and without using a proxy or JSONP (which is limited and awkward) -- as long as you control the destination server, or if the destination server allows.
&lt;/p&gt;

&lt;p&gt;I’m explaining this file: &lt;a href=&quot;https://github.com/alexandru/crossdomain-requests-js/blob/gh-pages/public/crossdomain-ajax.js&quot;&gt;crossdomain-ajax.js&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;updates&quot;&gt;Updates&lt;/h2&gt;

&lt;h3 id=&quot;oct-27-2011&quot;&gt;Oct 27, 2011&lt;/h3&gt;

&lt;p&gt;Added restrictions of usage and removed functionality that doesn’t work on IExplorer. So in case this doesn’t work for you, please see this page: &lt;a href=&quot;https://github.com/alexandru/crossdomain-requests-js/wiki/Troubleshooting&quot;&gt;Troubleshooting&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;in-modern-browsers---meet-cross-origin-resource-sharing&quot;&gt;In Modern Browsers - Meet Cross-Origin Resource Sharing&lt;/h2&gt;

&lt;p&gt;Or &lt;a href=&quot;http://www.w3.org/TR/cors/&quot;&gt;CORS&lt;/a&gt; for short, or &lt;a href=&quot;https://developer.mozilla.org/en/http_access_control&quot;&gt;HTTP Access Control&lt;/a&gt;, available in recent browsers, allows you to make cross-domain HTTP requests; the only requirement being that you must have control over the server-side implementation of the domain targeted in your XMLHttpRequest calls.&lt;/p&gt;

&lt;p&gt;This little piece of technology is available since Firefox 3.5 / IExplorer 8 and yet when searching for answers on websites like StackOverflow, it rarely comes up.&lt;/p&gt;

&lt;p&gt;For the purposes of this tutorial, we’ll assume we want to make a request from website &lt;code&gt;http://source.com&lt;/code&gt; to &lt;code&gt;http://destination.org&lt;/code&gt;, and that you control the implementation to both.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;var xhr = new XMLHttpRequest();
// NOPE, it doesn&apos;t work, yet
xhr.open(&quot;POST&quot;, &quot;http://destination.org&quot;, true);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;response-of-destinationorg&quot;&gt;Response of &lt;em&gt;destination.org&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;It’s pretty simple really, all you need to do is to return these headers in your response:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://source.com
Access-Control-Allow-Headers: Content-Type, *
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can find a description of them on &lt;a href=&quot;https://developer.mozilla.org/en/http_access_control#The_HTTP_request_headers&quot;&gt;Mozilla Doc Center&lt;/a&gt;, but the most important one is &lt;em&gt;Access-Control-Allow-Origin&lt;/em&gt;, which indicates the Origin(s) allowed to make such a request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; these options allow for wildcards (like you can say that you allow for any Origin by putting a “*” in that header), but it is better to be explicit about what’s allowed, otherwise your request won’t work very well cross-browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(New) Note:&lt;/strong&gt; In regards to Access-Control-Allow-Origin, IExplorer DOES NOT support wildcards. See &lt;a href=&quot;https://github.com/alexandru/crossdomain-requests-js/wiki/Troubleshooting&quot;&gt;Troubleshooting&lt;/a&gt; for details.&lt;/p&gt;

&lt;h2 id=&quot;client-side-implementation-of-ajax-request-for-cors&quot;&gt;Client-side Implementation of Ajax Request for CORS&lt;/h2&gt;

&lt;p&gt;On browsers where &lt;u&gt;XMLHttpRequest&lt;/u&gt; is valid, support for CORS can be validated by checking for the availability of the &lt;u&gt;withCredentials&lt;/u&gt; property.&lt;/p&gt;

&lt;p&gt;So we’ve got a tiny issue: &lt;u&gt;IExplorer&apos;s&lt;/u&gt; implementation is different than that of Firefox’s or the rest of the browsers (naturally). Instead of using the same &lt;u&gt;XMLHttpRequest&lt;/u&gt; object, IExplorer 8 adds an &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/cc288060(v=vs.85).aspx&quot;&gt;XDomainRequest&lt;/a&gt; object.&lt;/p&gt;

&lt;p&gt;So to initialize an async request, that will work on IExplorer 8, Firefox, Chrome and the other browsers supporting it:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;try {
    var xhr = new XMLHttpRequest();
} catch(e) {}

if (xhr &amp;&amp; &quot;withCredentials&quot; in xhr){
  xhr.open(type, url, true);
} else if (typeof XDomainRequest != &quot;undefined&quot;){
  xhr = new XDomainRequest();
  xhr.open(type, url);
} else {
  xhr = null;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But we aren’t done yet, the callbacks used by these request objects have different behavior on IExplorer. So let’s say we’ve got 2 callbacks that we want to register, one for success, one for errors, having the following signatures (same as jQuery):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;function success(responseText, XHRobj) { ... }
function error(XHRobj) { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To have correct behavior cross-browser:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;//
// combines the success/error handlers into one
// higher-order function (getting a little fancy for code-reuse)
//
var handle_load = function (event_type) {
  return function (XHRobj) {
    //
    // stupid IExplorer won&apos;t receive any param on callbacks!!!
    // thus the object used is the initial `xhr` object
    // (bound to this function because it&apos;s a closure)
    //
    var XHRobj = is_iexplorer() ? xhr : XHRobj;

    //
    // IExplorer also skips on readyState
    // Also, it&apos;s success/error based on the `event_type` used at the call-site
    //
    if (event_type == &apos;load&apos; &amp;&amp; (is_iexplorer() || XHRobj.readyState == 4) &amp;&amp; success)
      success(XHRobj.responseText, XHRobj);
    else if (error)
      error(XHRobj);
  }
};

try {
  // IExplorer throws an exception on this one
  //
  // Setting this to `true` is specifying to make the request with Cookies attached.
  // BUT -- it&apos;s pretty useless, as IExplorer doesn&apos;t support sending Cookies.
  //
  // Also, trying to set cookies from the response is not really possible directly
  // (workarounds are available though -- you can return anything in the response&apos;s
  //  body and use local javascript for persistence/propagation on next request)
  //
  xhr.withCredentials = false;
} catch(e) {};

//
// `onload` + `onerror` are actually new additions to these browsers.
//
// IExplorer doesn&apos;t actually push params on calling these callbacks.
// For every other browser, the XHRobj we want is in `e.target`,
// where `e` is an event object.
//
xhr.onload  = function (e) {
  handle_load(&apos;load&apos;)(is_iexplorer() ? e : e.target)
};
xhr.onerror = function (e) {
  handle_load(&apos;error&apos;)(is_iexplorer() ? e : e.target)
};
xhr.send(data);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also of notice, here’s how to check if the browser is IExplorer:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;function is_iexplorer() {
  return navigator.userAgent.indexOf(&apos;MSIE&apos;) !=-1
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, that’s it, unless you want to support the rest of desktop browsers in use.&lt;/p&gt;

&lt;h2 id=&quot;fallback-for-older-browsers&quot;&gt;Fallback for Older Browsers&lt;/h2&gt;

&lt;p&gt;&lt;u&gt;Opera 10&lt;/u&gt; doesn’t have this feature, neither do IExplorer &lt; 8, Firefox &lt; 3.5 – and I don’t really know when Chrome/Safari added it. Fortunately there’s a workaround – Flash can do whatever you want and runs the same on ~90% of desktop browsers out there, AND it can interact with Javascript.&lt;/p&gt;

&lt;p&gt;Not to reinvent the wheel, here’s a cool plugin: &lt;a href=&quot;http://flxhr.flensed.com/&quot;&gt;flensed.flXHR&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;why-bother-with-cors&quot;&gt;Why bother with CORS?&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Flash is not available on the iPhone&lt;/li&gt;
  &lt;li&gt;Flash loads slower than Javascript&lt;/li&gt;
  &lt;li&gt;Flash SWF files come with a lot of junk that your browser has to download&lt;/li&gt;
  &lt;li&gt;The whole experience using flXHR will be visibly slower than with CORS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;flxhr-usage&quot;&gt;flXHR Usage&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;//
// Does a request using flXHR (the JS-Flash alternative
// implementation for XMLHttpRequest)
//
function _ajax_with_flxhr(options) {
  var url = options[&apos;url&apos;];
  var type = options[&apos;type&apos;] || &apos;GET&apos;;
  var success = options[&apos;success&apos;];
  var error = options[&apos;error&apos;];
  var data = options[&apos;data&apos;];

  //
  // handles callbacks, just as above
  //
  function handle_load(XHRobj) {
    if (XHRobj.readyState == 4) {
      if (XHRobj.status == 200 &amp;&amp; success)
        success(XHRobj.responseText, XHRobj);
      else
        error(XHRobj);
    }
  }

  var flproxy = new flensed.flXHR({
    autoUpdatePlayer: false,
    instanceId: &quot;myproxy1&quot;,
    xmlResponseText: false,
    onreadystatechange: handle_load
  });

  flproxy.open(type, url, true);
  flproxy.send(data);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We are NOT done. The destination server also needs a file called &lt;u&gt;crossdomain.xml&lt;/u&gt;, which represents a &lt;a href=&quot;http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html&quot;&gt;Crossdomain Policy File Spec&lt;/a&gt;. As a requirement, this file has to be placed in the domain’s root, i.e. &lt;u&gt;http://destination.org/crossdomain.xml&lt;/u&gt; …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;!DOCTYPE cross-domain-policy SYSTEM &quot;http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd&quot;&gt;
&lt;cross-domain-policy&gt;
  &lt;!-- wildcard means &apos;allow all&apos; --&gt;
  &lt;allow-access-from domain=&quot;*&quot; /&gt;
  &lt;allow-http-request-headers-from domain=&quot;*&quot; headers=&quot;*&quot; /&gt;
&lt;/cross-domain-policy&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;not-loading-the-junk-when-not-needed&quot;&gt;Not Loading the Junk when Not Needed&lt;/h2&gt;

&lt;p&gt;Javascript is &lt;u&gt;asynchronous&lt;/u&gt; and we should take advantage of that by not loading &lt;u&gt;flensed.flXHR&lt;/u&gt;, unless needed and at the last moment too (no need to load it until we want to make a request).&lt;/p&gt;

&lt;p&gt;We need a method for asynchronously loading a Javascript file and executing a callback onload. And since we may be executing this function multiple times at once, we need to take care of race-conditions. First things first:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;// keeps count of files already included
var FILES_INCLUDED = {};

// keeps count of files in the processes of getting loaded
// for avoiding race conditions
var FILES_LOADING = {};

// stacks of registered callbacks, that will get executed once
// a file loads -- this to deal with multiple file inclusions at once,
// and not ignoring anything
var REGISTERED_CALLBACKS = {};

function register_callback(file, callback) {
  if (!REGISTERED_CALLBACKS[file])
    REGISTERED_CALLBACKS[file] = new Array();
  REGISTERED_CALLBACKS[file].push(callback);
}

function execute_callbacks(file) {
  while (REGISTERED_CALLBACKS[file].length &gt; 0) {
    var callback = REGISTERED_CALLBACKS[file].pop();
    if (callback) callback();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To asynchronously load a Javascript file, with onload callback, behold:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;//
// Loads a Javascript file asynchronously, executing a `callback`
// if/when file gets loaded.
//
// Returns `true` if callback got executed immediately, `false` otherwise.
//
function async_load_javascript(file, callback) {
  // stores callback in the stack
  register_callback(file, callback);

  // dealing with race conditions

  if (FILES_INCLUDED[file]) {
    execute_callbacks(file);
    return true;
  }
  if (FILES_LOADING[file])
    return false;

  FILES_LOADING[file] = true;

  // dynamically adds a &lt;script&gt; tag to the document
  var html_doc = document.getElementsByTagName(&apos;head&apos;)[0];
  js = document.createElement(&apos;script&apos;);
  js.setAttribute(&apos;type&apos;, &apos;text/javascript&apos;);
  js.setAttribute(&apos;src&apos;, file);
  html_doc.appendChild(js);

  // onload, then go through the stack of callbacks,
  // and execute all of them
  js.onreadystatechange = function () {
    if (js.readyState == &apos;complete&apos; || js.readyState == &apos;loaded&apos;) {
      if (!FILES_INCLUDED[file]) {
        FILES_INCLUDED[file] = true;
        execute_callbacks(file);
      }
    }
  };

  // same as above, same shit for dealing with incompatibilities
  js.onload = function () {
    if (!FILES_INCLUDED[file]) {
      FILES_INCLUDED[file] = true;
      execute_callbacks(file);
    }
  };

  return false;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;almost-there&quot;&gt;Almost there&lt;/h2&gt;

&lt;p&gt;To bind it all together we need to plug this into our main logic. So if browser does not support CORS, it fallbacks to this implementation.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;// to recapitulate
if (xhr &amp;&amp; &quot;withCredentials&quot; in xhr) {
  xhr.open(type, url, true);
} else if (typeof XDomainRequest != &quot;undefined&quot;) {
  xhr = new XDomainRequest();
  xhr.open(type, url);
} else {
  xhr = null;
}

// NOT SUPPORTED, then fallback
if (!xhr) {
  async_load_javascript(CROSSDOMAINJS_PATH + &quot;flXHR/flXHR.js&quot;, function () {
    _ajax_with_flxhr(options);
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To see the final code, go here: &lt;a href=&quot;https://github.com/alexandru/crossdomain-requests-js/blob/gh-pages/public/crossdomain-ajax.js&quot;&gt;crossdomain-ajax.js&lt;/a&gt;.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2011/03/24/cross-domain-requests/?pk_campaign=rss&quot;&gt;Cross-Domain, Cross-Browser AJAX Requests&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Thu, 24 Mar 2011 00:00:00 +0000</pubDate>
  <dc:modified>Sat, 14 Dec 2019 00:00:00 +0000</dc:modified>
  <atom:modified>Sat, 14 Dec 2019 00:00:00 +0000</atom:modified>
  <link>https://alexn.org/blog/2011/03/24/cross-domain-requests/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2011/03/24/cross-domain-requests/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>JavaScript</category>
  <category>Browser</category>
  <category>Web</category>
  </item>


<item>
  <title>I hate NULL and all its variants!</title>
  <description>How many times have you had a chain of methods like this (example showing BeautifulSoup in action) …</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2010/05/25/i-hate-null/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/beautiful-soup.png?202603060940&quot; alt=&quot;&quot; width=&quot;1542&quot; height=&quot;592&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
    How many times have you had a chain of methods like this (example showing &lt;a href=&quot;https://www.crummy.com/software/BeautifulSoup/&quot;&gt;BeautifulSoup&lt;/a&gt; in action) …
&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;soup.find(&apos;table&apos;, {&apos;class&apos;:&apos;search-params&apos;})\
    .findParent(&apos;form&apos;)\
    .find(&apos;td&apos;, {&apos;class&apos;: &apos;elem&apos;})\
    .find(&apos;input&apos;)\
    .get(&apos;name&apos;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;BeautifulSoup is not JQuery, and when it doesn’t find an element on find actions, it just returns None or an empty list. Then you get a beautiful index error or a method not available on NoneType kind of error, with the result being that the error itself doesn’t say anything useful about what happened (except the source-code line number) … whereas in the case above I would probably prefer a WebUIError or something.&lt;/p&gt;

&lt;p&gt;And really, most of the time I just want the result of such an expression to be None, in case one method invocation fails, and I do not think that having a try/except block for every line of code that does something interesting is ideal.&lt;/p&gt;

&lt;p&gt;Fortunately Python is dynamic, and you can come up with something resembling the &lt;a href=&quot;http://en.wikipedia.org/wiki/Monad_(functional_programming)#Maybe_monad&quot;&gt;Maybe monad&lt;/a&gt;. Here’s one way to do it …&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;instead of sending invocations to your initial object / collection (in my case a BeautifulSoup object used for querying), you’re sending them to a proxy&lt;/li&gt;
  &lt;li&gt;for each invocation type you want, the proxy stores the invocation types into a list&lt;/li&gt;
  &lt;li&gt;when you want to execute the resulting expression, you iterate through that list actually invoking those actions, keeping an intermediate result&lt;/li&gt;
  &lt;li&gt;if at any point that intermediate result becomes None (or something that evaluates to False) or an exception is thrown, then you can either invoke some handler (specializing the exception thrown) or you can return None&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are 3 types of invocations I needed to work with BeautifulSoup …&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;attribute access (overridden with &lt;code&gt;__getattr__&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;method invocation (overridden with &lt;code&gt;__call__&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;indexer (overridden with &lt;code&gt;__getitem__&lt;/code&gt; and &lt;code&gt;__setitem__&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My proxy implementation starts something like this …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class Proxy(object):
    def __init__(self, instance, on_error_callback = None, _chain=None, _memo=None):
        self._wrapped_inst = instance
        self._chain = _chain or []
        self._on_error_callback = on_error_callback
        self._memo = _memo or []

    def __getattr__(self, name):
        return self._new_proxy(ProxyAttribute(name))

    def __call__(self, *args, **kwargs):
        return self._new_proxy(ProxyInvoke(args, kwargs))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, there’s an &lt;em&gt;instance&lt;/em&gt; of an object getting wrapped (&lt;code&gt;_wrapped_instance&lt;/code&gt;), there’s a &lt;code&gt;_chain&lt;/code&gt; of expressions memorized, there’s an &lt;code&gt;_on_error_callback&lt;/code&gt; that gets executed in case of error, and there’s a &lt;code&gt;_memo&lt;/code&gt; that keeps the result of the last execution (libraries like BeautifulSoup are slow).&lt;/p&gt;

&lt;p&gt;Of course, I’m getting fancy, because I want &lt;a href=&quot;https://en.wikipedia.org/wiki/Memoization&quot;&gt;memoization&lt;/a&gt; and because in order to prevent the proxy getting into an inconsistent state, when adding a new invocation type to the &lt;code&gt;_chain&lt;/code&gt; I’m taking a page from functional programming by creating a new proxy object (making the proxy somewhat immutable).&lt;/p&gt;

&lt;p&gt;So I override &lt;code&gt;__getattr__&lt;/code&gt; and &lt;code&gt;__call__&lt;/code&gt; and &lt;code&gt;__getitem__&lt;/code&gt; and &lt;code&gt;__setitem__&lt;/code&gt;. For example on &lt;code&gt;__getattr__&lt;/code&gt; I add to &lt;code&gt;_chain&lt;/code&gt; an instance of a &lt;code&gt;ProxyAttribute&lt;/code&gt;, which looks something like this …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class ProxyAttribute(object):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return &quot;.&quot; + self.name

    def do(self, obj):
        return getattr(obj, self.name)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And when I want the result of such invocation, if the intermediate result is stored in &lt;code&gt;obj&lt;/code&gt;, then it would look like …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;obj = proxy_attribute_instance.do(obj)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, for how it would look in practice …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def handler_soup_error(**kwargs):
     raise WebUIError(&quot;Web interface specification changed&quot;)

soup = Proxy(BeautifulSoup(document), handler_soup_error)

soup.find(&apos;table&apos;, {&apos;class&apos;:&apos;search-params&apos;}).findParent(&apos;form&apos;)\
    .find(&apos;td&apos;, {&apos;class&apos;: &apos;elem&apos;})\
    .find(&apos;input&apos;)\
    .get(&apos;name&apos;)\
    .do()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So at the actual call site, the only difference is that &lt;code&gt;do()&lt;/code&gt; call. If the error handler wouldn’t be specified, the result returned would be &lt;code&gt;None&lt;/code&gt;. Simple as that.&lt;/p&gt;

&lt;p&gt;I also needed an utility, because I want to capture a partial evaluation to not rerun it for multiple special cases (like in the above case capturing all “td” elements) …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;all_td_elems = soup.find(&apos;table&apos;, {&apos;class&apos;:&apos;search-params&apos;})\
    .findParent(&apos;form&apos;)\
    .find(&apos;td&apos;, {&apos;class&apos;: &apos;elem&apos;})\
    .do_cache() # not an inspiring name unfortunately

    # and then resume with the same behavior ...
    all_td_elements.find(&apos;input&apos;).get(&apos;name&apos;).do()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Yeah, it’s just a small hack, but it’s so damn useful sometimes.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2010/05/25/i-hate-null/?pk_campaign=rss&quot;&gt;I hate NULL and all its variants!&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Tue, 25 May 2010 00:00:00 +0000</pubDate>
  <link>https://alexn.org/blog/2010/05/25/i-hate-null/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2010/05/25/i-hate-null/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Python</category>
  </item>


<item>
  <title>Introduction</title>
  <description>FreeSWITCH is a free and open source application server for real-time communication, WebRTC, telecommunications, video and Voice over Internet Protocol. Let’s build a VoIP dialer with it.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2009/02/20/tips-for-creating-voip-dialer/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/freeswitch1.png?202603060940&quot; alt=&quot;&quot; width=&quot;1200&quot; height=&quot;674&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;FreeSWITCH is a free and open source application server for real-time communication, WebRTC, telecommunications, video and Voice over Internet Protocol. Let&apos;s build a VoIP dialer with it.&lt;/p&gt;

&lt;p class=&quot;info-bubble&quot;&gt;
  This article also refers to FreeSWITCH Revision &lt;code&gt;10694&lt;/code&gt;. Things could have changed since then, there might be better ways for doing what’s described in this article; ask on their mailing list.
&lt;/p&gt;

&lt;p&gt;We are trying to migrate one of our existing Asterisk setups to FreeSWITCH. These are some tips to walk you thorough the hard part of learning the inners of FreeSWITCH for creating a simple dialer.&lt;/p&gt;

&lt;p&gt;As you will learn, FreeSWITCH is a little overwhelming, while being flexible and easy to use.&lt;/p&gt;

&lt;p&gt;Being a software developer, I prefer the flexibility of a programming language, rather than working with XML configuration files. Fortunately the standard FreeSWITCH distribution comes with both a SpiderMonkey engine (javascript) and Lua embeded. And it works great for our needs.&lt;/p&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;Our setup is based on Debian Linux. You should have no problem following it for other Linux-distros or operating systems though.&lt;/p&gt;

&lt;p&gt;For external scripts, we prefer Perl, and I’ll give a code sample using it, but I don’t think it would be a problem porting it to the language of your choice.&lt;/p&gt;

&lt;p&gt;You’ll also need a &lt;a href=&quot;http://en.wikipedia.org/wiki/Session_Initiation_Protocol&quot;&gt;SIP&lt;/a&gt; provider for initiating external VoIP calls.&lt;/p&gt;

&lt;h2 id=&quot;step-1-instalation&quot;&gt;Step 1: Instalation&lt;/h2&gt;

&lt;p&gt;You can find detailed installation instructions here: &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Installation_Guide&quot;&gt;http://wiki.freeswitch.org/wiki/Installation_Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our setups are based on Debian, and there are also instructions for &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Installation_Guide#Debian_Linux&quot;&gt;building Debian packages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you build Debian packages, the default instalation path is &lt;code&gt;/opt/freeswitch&lt;/code&gt; (revision 10694). You can change that by modifying debian/rules in the sources directory (search for “&lt;code&gt;/opt/freeswitch&lt;/code&gt;”, you’ll find a “&lt;code&gt;./configure&lt;/code&gt;” section), once you download it. But this tutorial is based on the default settings.&lt;/p&gt;

&lt;h2 id=&quot;step-2-configuration&quot;&gt;Step 2: Configuration&lt;/h2&gt;

&lt;p&gt;I won’t dwell on details since the configuration can be a painful process, and you would be better served contacting the &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Main_Page#Community_and_Support&quot;&gt;FreeSWITCH community&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But you’ll probably need to configure authentication settings for your SIP provider. To do that, look at the lead on the wiki: &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Getting_Started_Guide#External&quot;&gt;external SIP profiles&lt;/a&gt;. For us it was easy since our provider doesn’t require user/password authentication, and no extra configuration was necessary.&lt;/p&gt;

&lt;h2 id=&quot;step-3-initiating-external-calls&quot;&gt;Step 3: Initiating External Calls&lt;/h2&gt;

&lt;p&gt;In case the FreeSWITCH daemon has started, you need to stop it for now …&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;/etc/init.d/freeswitch stop
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you also have Asterisk up and runnings, you should stop it also, to avoid any conflicts.&lt;/p&gt;

&lt;p&gt;Then open the FreeSWITCH console:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;/opt/freeswitch/bin/freeswitch -c
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Calls can be initiated by using the &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Mod_commands#originate&quot;&gt;originate command&lt;/a&gt;. You’ll need a “call url” with the syntax described on the wiki: &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Sofia#Syntax&quot;&gt;Sofia#Syntax&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To make a simple call, let’s setup a simple dialplan. Also, let’s also play a simple audio file, according &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Playing_recording_external_media#Play_wav&quot;&gt;to the wiki example&lt;/a&gt;.To do that, create a dialplan extension by creating a file named &lt;code&gt;/opt/freeswitch/conf/dialplan/default/2009_play.xml&lt;/code&gt; with the following text:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;include&gt;
  &lt;extension name=&quot;wavs&quot;&gt;

    &lt;condition field=&quot;destination_number&quot; expression=&quot;^2009$&quot;&gt;
      &lt;action application=&quot;sleep&quot; data=&quot;2000&quot;/&gt;
      &lt;action application=&quot;playback&quot; data=&quot;/path/to/your.wav&quot;/&gt;
    &lt;/condition&gt;

  &lt;/extension&gt;
&lt;/include&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The file is self-descriptive. When the phone is answered, it waits 2 seconds before playing your audio file of choice.&lt;/p&gt;

&lt;p&gt;Now, in the Free console execute the following command (while providing a real number and your own SIP provider, of course):&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;originate sofia/external/$number@$myprovider.com 2009
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If everything goes well (the phone rings, and you can hear the audion file), then &lt;strong&gt;congratulations&lt;/strong&gt;, you’re well on your way :)&lt;/p&gt;

&lt;h2 id=&quot;step-4-scripting&quot;&gt;Step 4: Scripting&lt;/h2&gt;

&lt;p&gt;Freeswitch comes with Spidermonkey, and Lua embedded, and also offers integration with other languages, like Python and Perl. I’m going to exemplify Javascript, because it’s a decent mainstream language that I like, but if you’re worried about performance or you just want to have some fun, you should give Lua a try.&lt;/p&gt;

&lt;p&gt;I also really, really hate XML configuration files. So I wanted to do everything from a script file, with these reasons on top of my head:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;general-purpose scripting languages make me happy&lt;/li&gt;
  &lt;li&gt;you gain flexibility … and stuff like retrying the call based on certain conditions, or a finite state automata depending on the client/campaign … easy as pie&lt;/li&gt;
  &lt;li&gt;have I mentioned that I hate XML?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In your favorite text editor, create a file “voice.js”, with the following code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;session = new Session(&apos;sofia/external/$number@provider&apos;);
// The following line is a deprecated method
// session.originate(undefined, &apos;sofia/external/$number@provider&apos;);

session.waitForAnswer(10000);

if (session.ready()) {
    session.sleep(1000);
    session.streamFile(&apos;/path/to/your.wav&apos;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.freeswitch.org/wiki/Session_waitForAnswer&quot;&gt;waitForAnswer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.freeswitch.org/wiki/Session_streamFile&quot;&gt;streamFile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For our purposes, this snippet is almost equivalent to our initial dialplan extension. To execute it, in the FreeSWITCH console run the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;jsrun /path/to/voice.js
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;step-5-more-scripting&quot;&gt;Step 5: More Scripting&lt;/h2&gt;

&lt;p&gt;Now that we’ve got working code, lets expand it a little to make it more useful.&lt;/p&gt;

&lt;h3 id=&quot;how-to-send-a-caller-id-when-initiating-calls&quot;&gt;How to send a caller-id when initiating calls?&lt;/h3&gt;

&lt;p&gt;We want the call to have an associated caller-ID. The caller-ID is passed by setting the channel variables &lt;em&gt;origination_caller_id_number&lt;/em&gt; and &lt;em&gt;origination_caller_id_name&lt;/em&gt;. Try it in a FreeSWITCH console right now by executing this command:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;originate {origination_caller_id_number=123456, \
           ignore_early_media=true}sofia/external/$number@provider &amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or in your script:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;var session = new Session(
  &quot;{origination_caller_id_number=1234567}&quot;
  + &quot;sofia/external/$number@provider&quot;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For the B-leg of a bridged connection, you either set “&lt;code&gt;origination_caller_id_(name/number)&lt;/code&gt;” on the new connection, or, as a shortcut, on the A-leg you can specify the channel variables &lt;em&gt;effective_caller_id_number&lt;/em&gt; and &lt;em&gt;effective_caller_id_name&lt;/em&gt; which are passed to any B-leg call initiated. Try it in a console:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;originate {origination_caller_id_number=1111111111, \
           effective_caller_id_number=222222222, \
           ignore_early_media=true}sofia/external/$number@provider \
           &amp;bridge(sofia/external/$second_number@provider)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;how-to-retry-if-phone-is-busy&quot;&gt;How to retry if phone is busy?&lt;/h3&gt;

&lt;p&gt;We want to retry the call immediately after, maybe the client pressed the wrong button and rejected the call. As in this &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Busy_Call_Retry&quot;&gt;wiki page&lt;/a&gt;, but with a twist: we wouldn’t want to retry more than once, because annoyed customers are not happy customers.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;function makeCall(nr_or_tries) {
    session = new Session(&apos;sofia/external/$number@provider&apos;);
    // The following line is a deprecated method
    //session.originate(undefined, &apos;sofia/external/$number@provider&apos;);

    session.waitForAnswer(10000);

    if (session.cause == &quot;USER_BUSY&quot;) {
        // not sure if this is necessary
	// session.hangup();

	if (nr_or_tries &lt;= 1) {
	    console_log(&quot;Action: Trying again!&quot;);
	    return true;
	}

	console_log(&quot;Action: Cannot try again, skipping!&quot;);
    }


    if (session.ready()) {
        session.sleep(1000);
	session.streamFile(&apos;/path/to/your.wav&apos;);
	session.hangup();
    }
}

var nr_or_tries = 0;

while (nr_or_tries &lt; 2) {
    if (!makeCall(nr_or_tries++)) break;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See: &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Session_hangup&quot;&gt;hangup&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course, this script retries the call immediately. This may not be what you want (you may want to wait 10 minutes for a retry), so our favorite way for retries is through an external script that handles the calls queue.&lt;/p&gt;

&lt;h3 id=&quot;how-to-detect-phone-keys-pressed&quot;&gt;How to detect phone keys pressed?&lt;/h3&gt;

&lt;p&gt;Now we’re getting somewhere :)&lt;/p&gt;

&lt;p&gt;The first thing you have to do, after the originate command, is activating &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Misc._Dialplan_Tools_start_dtmf&quot;&gt;DTFM detection&lt;/a&gt;. This can be done in an extension configuration file, but I prefer doing it from our script, for reasons stated above. So after you execute the &lt;em&gt;originate&lt;/em&gt; command, you have to execute the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;session.execute(&quot;start_dtmf&quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, when you play an audio file, the &lt;code&gt;streamFile&lt;/code&gt; function accepts as parameter an event handler, which can be used to detect keys pressed. So, lets say than when you press “1”, you want to repeat your message, and when you press “2”, you want to play another audio file:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;var session = new Session(/*... params ... */);
// The following line is a deprecated method
//session.originate(/*... params ... */);
session.execute(&quot;start_dtmf&quot;);

var on_event = function ( session, type, data, arg ) {

    // we are only concerned with &quot;dtmf&quot; event types
    if (type != &quot;dtmf&quot;) return;

    if (data.digit == &quot;1&quot;) {
        return &quot;seek:0&quot;;
    }
    else if (data.digit == &quot;2&quot;) {

        session.sleep(1000);
	session.streamFile(&quot;/path/to/another.wav&quot;);

	/* current audio file is stopped
	* on returning false
	*/
	return false;
    }


    /* for any other key pressed
    * returning true keeps the current audio playing
    */
    return true;
};

if (session.ready()) {
    session.sleep(2000);
    session.streamFile(&quot;/path/to/your.wav&quot;, on_event);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; minutes cost money, so you should add a counter to limit the maximum times a message can be replayed. There are many weirdos out there 😉&lt;/p&gt;

&lt;h3 id=&quot;how-to-create-a-connection-between-your-session-and-another-phone&quot;&gt;How to create a connection between your session and another phone?&lt;/h3&gt;

&lt;p&gt;Maybe you want your client to be connected to a real operator (when he’s pressing “0” on his phone keyboard maybe?). It’s easy, here’s how:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;// the original session
session = new Session(&apos;sofia/external/$number@provider&apos;);
// The following line is a deprecated method
// session.originate(undefined, &apos;sofia/external/$number@provider&apos;);

session.answer();

if (session.ready()) {
    var new_session = new Session(&apos;sofia/external/$another_number&gt;@provider&apos;);
    // The following line is a deprecated method
    //new_session.originate(session, &apos;sofia/external/$another_number@provider&apos;);
    new_session.answer();

    if (new_session.ready()) {
        bridge(session, new_session);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See: &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Mod_commands#bridge&quot;&gt;bridge&lt;/a&gt;. If you want to add the actual key-press event, see the example above.&lt;/p&gt;

&lt;h3 id=&quot;how-to-execute-external-commands-from-your-script&quot;&gt;How to execute external commands from your script?&lt;/h3&gt;

&lt;p&gt;If you want to execute an external script (like for sending a notification when a certain event happens), you can use the &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Javascript_Misc_system&quot;&gt;system&lt;/a&gt; command.&lt;/p&gt;

&lt;p&gt;If you want to execute an external command, and process its output, you can open a pipe using the &lt;a href=&quot;http://wiki.freeswitch.org/wiki/File&quot;&gt;File&lt;/a&gt; object. In FreeSWITCH you do have the possibility of accessing a database using ODBC, but I haven’t tried it, and in case it doesn’t work, you can always write an external script that does the processing you need, and then returns a JSON, or an XML file.&lt;/p&gt;

&lt;h2 id=&quot;step-6-communicating-with-freeswitch-using-mod_event_socket&quot;&gt;Step 6: Communicating with FreeSWITCH using mod_event_socket&lt;/h2&gt;

&lt;p&gt;Playing in the FreeSWITCH console is fun, but what you need is a server who receives notifications from an external script.&lt;/p&gt;

&lt;p&gt;First, shut down the FreeSWITCH console, and start FS in daemon mode.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;/etc/init.d/freeswitch start
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, copy your work thus far (which I assume it’s located in &lt;code&gt;dialer.js&lt;/code&gt;) to &lt;code&gt;/opt/freeswitch/scripts&lt;/code&gt;. That’s where scripts are usually deployed in FreeSWITCH.&lt;/p&gt;

&lt;p&gt;FreeSWITCH can communicate through &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Mod_event_socket&quot;&gt;mod_event_socket&lt;/a&gt;. You can communicate using a simple telnet connection, but I’m lazy, and &lt;a href=&quot;http://search.cpan.org/~jrogers/Net-Telnet-3.03/lib/Net/Telnet.pm&quot;&gt;Net::Telnet&lt;/a&gt; is complaining about a missing login prompt. Luckily, in the FreeSWITCH sources directory, you’ll find a sample &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Mod_event_socket#perl_command_client&quot;&gt;perl command client&lt;/a&gt;. The source code is located in &lt;code&gt;freeswitch_src/scripts/socket&lt;/code&gt; and in there you’ll find the perl package &lt;em&gt;FreeSWITCH::Client&lt;/em&gt;. Copy it to your project’s location, and create a script called &lt;code&gt;dialer.pl&lt;/code&gt; with the following code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-perl&quot;&gt;#!/usr/bin/perl
use strict;
use warnings;

# make sure it&apos;s located in your @USE paths
use FreeSWITCH::Client;

my $fs = init FreeSWITCH::Client {-password =&gt; &apos;ClueCon&apos;} or die &quot;Error: $@&quot;;

# shows number of active channels ...
# useful when you want to control the maximum number of
# calls made simultaneously

$reply = $fs-&gt;command(&quot;show channels&quot;);
print &quot;Channels\n------------\n$reply\n&quot;;

# calls our script, that initiates a call
# the command is non-blocking, so you can make multiple
# calls in parallel

$fs-&gt;command(&quot;jsrun dialer.js&quot;);

$fs-&gt;disconnect();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Btw, if you’re not feeling comfortable about communicating through plain-old sockets with FreeSWITCH, try &lt;a href=&quot;http://wiki.freeswitch.org/wiki/Mod_http&quot;&gt;mod_http&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;Congratulations, you’ve made it to the end. You just need to add you’re specific business logic, and you already have a kick-ass dialer.&lt;/p&gt;

&lt;p&gt;There are lots of scenarios not addressed by this tutorial. One need you might have would be to get the logs of your calls, and see what customers haven’t answered, what customers pressed what key, the average duration of a call, and other such niceties. Since this is a big topic to talk about, and since I still have some research to do, this deserves a whole new article.&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2009/02/20/tips-for-creating-voip-dialer/?pk_campaign=rss&quot;&gt;Introduction&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Fri, 20 Feb 2009 00:00:00 +0000</pubDate>
  <dc:modified>Fri, 01 Apr 2022 16:13:50 +0000</dc:modified>
  <atom:modified>Fri, 01 Apr 2022 16:13:50 +0000</atom:modified>
  <link>https://alexn.org/blog/2009/02/20/tips-for-creating-voip-dialer/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2009/02/20/tips-for-creating-voip-dialer/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  <category>Best Of</category>
  <category>JavaScript</category>
  <category>Perl</category>
  </item>


<item>
  <title>Using the Best Tools in Programming: Not Really Doable</title>
  <description>There&apos;s something that bothers me when it comes to starting a new project. You can&apos;t really use the best tool for a certain job, if that tool is not integrated with the rest of your platform. Let me explain.</description>
  <content:encoded>&lt;div class=&quot;post-featured-image&quot;&gt;
    
      &lt;figure&gt;
        &lt;a href=&quot;https://alexn.org/blog/2009/02/01/using-best-tools-programming-not-doable/?pk_campaign=rss&quot; title=&quot;Open article in browser&quot;&gt;
          &lt;img src=&quot;https://alexn.org/assets/media/articles/tools.png?202603060940&quot; alt=&quot;&quot; width=&quot;768&quot; height=&quot;768&quot; style=&quot;max-width:100%;height:auto;&quot;&gt;
        &lt;/a&gt;
        
      &lt;/figure&gt;
    &lt;/div&gt;
  
      &lt;p class=&quot;intro&quot;&gt;
  There&apos;s something that bothers me when it comes to starting a new project. You can&apos;t really use the best tool for a certain job, if that tool is not integrated with the rest of your platform. Let me explain.
&lt;/p&gt;

&lt;p&gt;At our startup we pride ourselves with our pragmatism. We are true polyglots :) capable of diving in any project, no matter the language it was written in. This also gives us the power to make educated choices about the technologies we’re going to use for our own gigs.&lt;/p&gt;

&lt;p&gt;Our programming language of choice is Perl, because of its flexibility and because usually there’s no need to reinvent the wheel since you can find a CPAN module for almost anything.&lt;/p&gt;

&lt;p&gt;But recently I began experimenting with data-mining techniques, flirting with various NLP libraries. You can find almost anything in CPAN’s &lt;a href=&quot;https://search.cpan.org/search?query=AI%3A%3A&amp;mode=module&quot;&gt;AI:: namespace&lt;/a&gt;. But I also knew about &lt;a href=&quot;https://www.nltk.org/&quot;&gt;NLTK&lt;/a&gt;, a Python collection of libraries with excellent documentation, and I also found &lt;a href=&quot;https://opennlp.sourceforge.net/&quot;&gt;OpenNLP&lt;/a&gt;, &lt;a href=&quot;https://web.media.mit.edu/~hugo/montylingua/&quot;&gt;MontyLingua&lt;/a&gt;, &lt;a href=&quot;https://web.media.mit.edu/~hugo/conceptnet/&quot;&gt;ConceptNet&lt;/a&gt;, &lt;a href=&quot;https://www.abisource.com/projects/link-grammar/&quot;&gt;link-grammar&lt;/a&gt; and various &lt;a href=&quot;https://www2.nict.go.jp/x/x161/members/mutiyama/software.html&quot;&gt;Ruby modules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And all of a sudden I got cold feet. Java packages in OpenNLP may have the advantage of speed (just a guess and it doesn’t matter for the purpose of this discussion). NLTK has pedigree and great documentation, not to mention that many books related to NLP, AI and data mining have Python samples (for example I own &lt;a href=&quot;https://oreilly.com/catalog/9780596529321/&quot;&gt;Programming Collective Intelligence&lt;/a&gt; and &lt;a href=&quot;https://aima.cs.berkeley.edu/&quot;&gt;AIMA&lt;/a&gt;). Usually the solution is straightforward: you test all the options, and choose the best one.&lt;/p&gt;

&lt;p&gt;But what if you want to combine them?&lt;/p&gt;

&lt;p&gt;Well, then you’re shit out of luck. Surely you can do that with inter-process communication, but for that you’ll have to write glue-code and pay the price for extra latency, bandwidth and memory … parsing millions of documents, moving results between processes, it’s not really practical. Perl does have &lt;a href=&quot;https://search.cpan.org/dist/Inline-Java/Java.pod&quot;&gt;Inline::Java&lt;/a&gt;, but I would only use it in extreme situations.&lt;/p&gt;

&lt;p&gt;That’s why there’s so much wheel reinvention around. Unless a module is written in C, for which any language has a FFI, almost nobody wants to use a Java module from Ruby, or a Python module from Perl. That’s why there’s &lt;a href=&quot;https://lucene.apache.org/&quot;&gt;Lucene&lt;/a&gt;, and then there’s &lt;a href=&quot;https://incubator.apache.org/lucene.net/&quot;&gt;Lucene.NET&lt;/a&gt;, &lt;a href=&quot;https://sourceforge.net/projects/clucene&quot;&gt;CLucene&lt;/a&gt;, &lt;a href=&quot;https://www.oreillynet.com/onlamp/blog/2005/10/lucene_in_ruby_name_ferret_thi.html&quot;&gt;Ferret&lt;/a&gt;, &lt;a href=&quot;https://framework.zend.com/manual/en/zend.search.lucene.html#zend.search.lucene.introduction&quot;&gt;Zend_Search_Lucene&lt;/a&gt;, &lt;a href=&quot;https://search.cpan.org/~tmtm/Plucene-1.25/lib/Plucene.pm&quot;&gt;Plucene&lt;/a&gt; and &lt;a href=&quot;https://incubator.apache.org/lucene4c/&quot;&gt;Lucene4c&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What is really needed is a universal virtual machine with a flexible &lt;a href=&quot;https://en.wikipedia.org/wiki/Metaobject_Protocol&quot;&gt;MOP&lt;/a&gt;, allowing seamless communication between languages. I’m happy there are a couple of efforts in this space, including &lt;a href=&quot;https://www.parrot.org/&quot;&gt;Parrot&lt;/a&gt;, and the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic_Language_Runtime&quot;&gt;DLR&lt;/a&gt;. Also, the biggest obstacles of alternative implementations are the modules written in C. Fortunately, JRuby/Rubinius have a brand new implementation-independent &lt;a href=&quot;https://blog.headius.com/2008/10/ffi-for-ruby-now-available.html&quot;&gt;FFI&lt;/a&gt;, and &lt;a href=&quot;https://code.google.com/p/ironclad/&quot;&gt;Ironclad&lt;/a&gt; will allow IronPython users to use CPython extensions (number one on their list being numpy).&lt;/p&gt;

&lt;p&gt;These developments make me happy :)&lt;/p&gt;

      &lt;hr&gt;
      &lt;p&gt;
        &lt;i&gt;The article &lt;a href=&quot;https://alexn.org/blog/2009/02/01/using-best-tools-programming-not-doable/?pk_campaign=rss&quot;&gt;Using the Best Tools in Programming: Not Really Doable&lt;/a&gt; first appeared on &lt;a href=&quot;https://alexn.org?pk_campaign=rss&quot;&gt;alexn.org&lt;/a&gt;.&lt;/i&gt;
      &lt;/p&gt;</content:encoded>
  <pubDate>Sun, 01 Feb 2009 00:00:00 +0000</pubDate>
  <dc:modified>Mon, 19 Sep 2022 08:17:51 +0000</dc:modified>
  <atom:modified>Mon, 19 Sep 2022 08:17:51 +0000</atom:modified>
  <link>https://alexn.org/blog/2009/02/01/using-best-tools-programming-not-doable/?pk_campaign=rss</link>
  <guid isPermaLink="true">https://alexn.org/blog/2009/02/01/using-best-tools-programming-not-doable/</guid>
  <dc:creator>Alexandru Nedelcu</dc:creator>
  <category>Blog</category>
  </item>
</channel>
</rss>
