The power of finding facts about personal preferences

It is unfortunate, really, that it’s 2021, and we still try to justify our personal preferences with “facts” that simply don’t exist.

I’m really sorry if this sounds aggressive, but as someone that saw this same pattern happening again and again, I’m quite tired. As Obie told us on a great talk about programming, music students, and painting, the pallette is not the point! Programming languages, frameworks, libraries, virtual machines are pallettes, tools, to make things better. As as with anything, people will prefer water paint, or crayons, or whatever – it simply does not matter. What matters is the ability to make great tools. Imagine if we treated music the same way we do with programming languages. It’s not hard to imagine bizarre conversations like:

  • “What, you play piano? Why, how are you going to play on the streets? The streets is where you earn money, don’t you know?”
  • “Wait, why are you learning guitar? How are you going to play on an orchestra?”
  • “Ocean Drums? Why invent another percursion instrument?”

Sounds crazy, right? So, just read this tweet, and see the madness appearing. Maybe the way that Robert Martin posed the question was not the best way to convince people to try Clojure, but anyway, people jumped up on defense of their pallets, their tools, to the point it was quite tiring, really. I’ll not post who told what, and I’m not going to post the exact replies, but let’s debunk some myths:

Static Typing – the dangers of incomplete info

Ok, so I’m going to use this post – Making Illegal States Unrepresentable – and I’ll add my experience to it. For people that don’t know F# (or that don’t want to check all the post to see what’s the point), the idea is that he’s trying to construct a type that will only be valid if a user does at least an e-mail address or a postal contact. Then, he ends with the following type (I’m “inventing” a way to represent this type that’s close to Scala, but easier to read for people that don’t know Scala or Haskell or F#):

type Contact {
  Name: String
  AND Contact: ContactInfo

type ContactInfo {
  EmailOnly: EmailInfo
  OR PostOnly: PostalInfo
  OR EmailAndPost: EmailInfo with PostalInfo

// Types EmailInfo and PostalInfo have to be defined also

Then, he uses 13 lines to construct a ContactInfo, and another 12 to update a contact info. He ends up concluding that these complicated types are necessary because the logic is complicated. And that’s where we start to disagree.

My 2020 retrospective

As my therapist said: 2020 was a year that put brakes on the whole world. And yet, for me, it was one of the best years of my life by far – maybe with the exception of 2012, where lots of other wonderful things happened too.

On this year, my daughter was born. There was also the covid-19 pandemic (yeah, it’s obvious right now, but maybe some years from now someone reading this post will probably not remember that it did exist) so if you join these two things, you’ll see how worried I was. It was always my wife’s dream to be a mother, and to have me at her side on the delivery room, but because of the pandemic, this would not be possible… or would it?

At that time, I was still living in Brazil. There are laws over there for the expecting mother to have someone helping her on the birth process – and we did use these laws so the hospital would be forced to accept that I would be with her. They tried to persuade me to not do it, multiple times, until I was able to get the maternity’s director cellphone and talk to her. So, yes – I was there, saw my daughter born, and I was with my wife’s and my daughter the whole time! It was probably the most incredible, magic moment of my life: when my daughter was born, she stayed with us the whole time, dimmed lights, looking at us. Recognizing us. She kept biting my fingers (when my wife had to rest for a while), and even today (she’s 6 months now) it’s one of her most enjoyable actions: to grab my fingers and gently bite then.

Last hours on my country

Right now, as I’m writing this, I have about 6 bags full of (mostly) clothes, a file with different documents, a bunch of fears, and a lot of hope. Tomorrow, if everything goes well, is my last day living in Brazil.

It was a strange adventure, first by making a simple trip (well, as far as “jump on a motorcycle with my wife and travel though the country and beyond, and end up traveling 6,449km” is considered simple), then by staying a whole month on an Airbnb and trying everything, from local meetups to social projects to local culture, restaurants, food, etc, and then finally getting all the documentation to live on the country we chose: Uruguay.

Implementing shadow.remote API

Since version 0.8.0 of Chlorine, there’s a new way to evaluate ClojureScript code: that’s the Shadow-CLJS Remote API. It is basically a new REPL (not nREPL, no Socket REPL) over WebSockets to try to solve problems when translating other REPLs to ClojureScript. So, to understand why these problems exist, I’ll first introduce the difference between ClojureScript and Clojure.

On Clojure, you’re always inside a JVM. This means that compilation happens on the same JVM that your REPL, and your code is running. If you practice REPL-Driven Development, even your tests are running on the same JVM. In practical terms, it means that when you fire up your REPL, you already have everything ready to run code, compile code, and evaluate forms.

On ClojureScript, the compiler is written in Clojure – that means it’s running on the JVM. So, to produce Javascript code you don’t need a Javascript environment – and that’s when things become confusing, because when exactly will you run the REPL? Let’s try from another angle: if you start the REPL on compilation time, you can’t evaluate code (because there’s no Javascript generated, nor any Javascript engine running). If you start the REPL when you run the compiled code, this REPL can become unusable if you stop the Javascript environment, and also you have to coordinate lots of state and translations between formats.

Reagent Mastermind

One of these days, a friend of mine posted about his experience writing the “Mastermind” game in React (in portuguese only). The game is quite simple:

  1. You have six possible colors
  2. A combination of 4 colors is chosen randomly (they can be repeated – for example, blue,blue,blue,blue is a valid combination) – you have to guess that number
  3. You have up to 10 guesses of 4 colors. For each color on the right position, you win a “black” point. For each color in the wrong position, you win a “white” point
  4. If you can’t guess on the 10th try, you loose.

So, first, we’ll create a shadow-cljs app – create a package.json file, fill it with {"name": "Mastermind"}, then run npm install shadow-cljs. Traditional stuff.

Then, we’ll create the shadow-cljs.edn file. It’ll only contain a single target (:browser), opening up a dev-http server so we can serve our code, and we’ll add reagent library dependency. I also added the material-ui dependency, but you don’t really need it for the code. Now, running npx shadow-cljs watch browser will start a webserver at port 3000, and we can start to develop things.

Please, use the right terms for “typing”…

Names matter. That’s one of the things that I learned, working multiple years on programming software. When you have something called “integration”, for example, that means different things for different people, that’s a recipe for disaster.

That’s why I get quite triggered when people use Untyped / Typed, Weak / Strong typed, Uni / Multi typed, to describe programming languages – because it means different things to different people, or are simply wrong. So let’s dive into it:

Untyped languages or languages without types are quite rare: Assembly is the most interesting example (there’s literally no types in Assembly: everything is a memory address, byte, word, etc). Some virtual machines’ bytecodes are also untyped. In this case, most languages are typed. Ruby, for example, have types, and you can dispatch different behavior depending on the type of the caller (because it’s a class-based object-oriented language). Clojure is also typed, because you can do type-based polymorphism with protocols using defprotocol and defrecord for example. You can also use deftype, and if there’s a specific command to define types, how can we call it “untyped”?

Weak / Strong typed is a term that’s hard to define. Some people say that it’s when you have pointers, because you can bypass the typing at all; others, when the compiler erases typing at run-time; some say that’s when the language tries to coerce and implicitly convert from one type to another, to try to figure out what you want…

Now, a language that allows you to bypass typing because you have pointers is called “memory unsafe”; if the compiler erases typing information, is called “type erasure”; coercion of course is called “coercion”, and can be “automatic” or “manual” coercion (for example, most languages try to coerce integers to decimals at some point); even the ability to convert between types is controversial: on Ruby and Scala, operators are also methods of the class (and, on Ruby, you can rewrite methods on classes that already exist, so automatic conversion is a user-defined feature) – so, please use the right term.

Unityped means a language that only have one type. I believe only some markup languages enter on this classification. Calling a language that have multiple types as unityped because someone imagined that all these multiple types can somewhat collapse into a single one is, at minimum, strange; and also, again, we do have a term for languages like Javascript, Ruby, Python, Smalltalk, and Clojure.

ClojureScript vs clojure.core.async

I’m going to make a somewhat bold statement: core.async does not work with ClojureScript. And, in this post, I’m going to show some examples why this is true, at least for the current versions of core.async.

So let’s start by understanding a little bit about the runtime: Javascript is a single-threaded runtime that implicitly runs an event-loop. So, for example, when you ask to read a file, you can do it synchronously or asynchronously. If you decide to run in that asynchronously, it means that as soon as you issue the fs.readFile command, you need to register a callback and the control is returned to the “main thread”. It’ll keep running until it runs out of commands to execute, then the runtime will wait the result from the callback; when it returns, the function that you registered will be called with the file contents. When the function ends, the JS runtime will await to see if there’s any other pending call, and it’ll exit if there’s nothing else to do.

The same thing happens in browser environment, but in this case the callbacks are events from the DOM: like clicking on buttons or listening for changes in some elements. The same rules apply here: the runtime is single threaded and when something happens it will first execute everything that needs to be executed, then it will be called back with the event that happened.

So maybe we can change these callbacks with core.async channels right? But the answer is no, because core.asyncs go blocks will not run in different threads (because, again, the runtime is single-threaded). Instead, it creates a state machine and it’ll control of when each of these go blocks will be called, at what time, eventually replacing the event-loop that Javascript environment already have.

What’s happening on Brazil?

I don’t really like to talk about non-technical things here, but… sometimes the circumstances push me to do it.

We are facing strange times: covid-19. We, as people, plural. There’s no individuals in this matter, because if only one person takes action, nothing will change. If only one country, again nothing will change. We need union, more than ever.

Then, comes Brazil. People simply believe that “our climate is warmer”, “the pandemic is nothing to worry about”, and “it’s just a small flu” – I’m not talking only about the bizarre declarations of the president, but from the common person. Our approximate numbers (approximate because we’re not testing all cases: I, personally, know three people that had the exact right symptoms for Covid-19 that didn’t receive any testing, and were asked to just “rest at home, and if it becomes worse search a medic”. One of then, as soon as he felt a little better, was visiting his friends and eating food at restaurants) keep skyrocketing, and fake news are appearing here and there that these numbers were fabricated by the enemies of the current government.

So, there are only guidelines – no official laws, no real restrictions. They all have to be decided by local authorities, and all against the president (that, on this day, made some insinuations that he can start a coup if people don’t obey him!) that I really hope doesn’t have all the power he thinks he have.