<VR>

  • Home
  • Talks
  • Podcast
  • Blog

Approaching functional programming through compile-to-JS languages

Published on Aug 30, 2021

🛫4 mins to read

  • typescript
  • mustache
  • templating
  • purescript
  • rescript
  • haskell
  • articles
  • thoughts

For the longest time, my head has been thinking in functional programming constructs. Since Javascript can be used to do purely functional programming, I was able to start implementing these ideas in JS/TS as part of my daily work.

I particularly find it easy to reason about code when it's broken into small chunks of pure functions that do one thing. It makes debugging easy when you can look at a chain of functions and go down the list, identify when the problem is not in one particular function and stop worrying about it. In my mind, being able to replace that function call with the return value makes it easier to narrow down a problem.

Pure functions also make it easy to test and ensure your logic is tight. Of course, this, by no means, is "pure" functional programming but that's the part I liked about this paradigm and practice everyday.

Of late, I have been reading up a lot on Elm, Purescript and Rescript. I'm toying around with some of these languages that compile to JS but enforce a pure functional pattern while authoring. Things that have been mental blocks for me in this journey has been two fold.

1. Javascript interop and escape hatches

Having worked in the frontend space for a while, I know there will always be a time where you will need to integrate a third party library. It could be for UI reasons like a map or a carousel that you don't want to build from scratch. It could also be for "product" reasons like integrating a third-party pixel or fraud detection provider.

All of these will require some kind of escape hatch where you will need to step out of the "safety" of the programming language sandbox and reach into Javascript.

As difficult as I make this sound in my head, this already happens even within my current workflow. Although I build react components, sometimes I have had to use the window object to run some custom JS script that's outside of the paradigm. As long as it is narrow in scope, it should be okay.

2. Compile to JS vs writing pure JS

Wouldn't you always have the burden of a runtime or a long compile time in excess? This has always been in the back of my head but this problem isn't new.

A slew of languages are built on top of the JVM - Scala, Clojure, Kotlin etc. but they seem to be thriving. No one set out to build another JVM - that is a solved problem but they can still optimize the "frontend" of the language with better syntax and grammar while retaining the safety of the underlying technology.

The current trend of compile to JS languages are following the same pattern. Yes there is an additional compile step and there is usually a runtime but by giving you a specific paradigm of programming, these languages are capable of providing elegant syntaxes and great developer experience. Having a compiler isn't necessarily a bad thing, especially if it's really friendly like in the case of Elm.

One of Elm’s goals is to change our relationship with compilers. Compilers should be assistants, not adversaries.

The additional runtime is necessary but can help improve performance and remain minimal. For example, immutability data structures can be optimized by implicit sharing. So when you duplicate the same array a few times in a compile to JS language, it still stores that data in the same memory location until it is actually changed. Even when it does, it can still share parts of the structure that haven't changed, thereby improving performance. This does require a runtime library in most cases, but projects like Purescript focus on avoiding the runtime altogether and projects like Rescript focus on blazing fast compilers.

The Elm appeal

The big appeal with Elm seems to be how it's designed for webapps and everything works within the same ecosystem - formatting, packages, templating. Especially templating, because in JS, we unfortunately reach to JSX for templating. Or something very unique to the framework like Svelte or Vue. I detest investing any time in learning templating because I feel like this skill doesn't transfer. We have been around the block with mustache, handlebars and JSX and everything does the same but in a slightly weird way. Like how there are no else statements in Mustache because they are "logic-less". You have to invert your "if selection" instead.

That's one of the main reasons I like Elm - it has been thought out and writing your UI is the same syntax as you would call functions in the language itself. That's powerful. And I'm impressed if someone has put so much thought into this small annoying piece of the development workflow, it really sounds like a well thought-out, UX driven language. I've listened to podcasts where people talk about Evan conducting user interviews on what people found most difficult in using Elm in the early days. That really speaks to me because I love iterating based on user feedback and used to conduct user interviews myself in a past life.

The only hesitation in going all-in on Elm is how the community reacts to the development model. It appears there's one bad article amidst several good indications but overall people don't seem impressed with how the team responds to criticism and provides updates.

The last thing I want to do is introduce a language to a team at work and have it constantly change in major ways or not push fixes for clearly known bugs for a very long time. I understand and accept how open source works. In fact, I also understand the whole BDFL and wanting to keep the language strictly within certain parameters - especially after showing so much evidence as to why that's a good thing. However, there is something nice about knowing when features and fixes will land, even if it's a year or two down the line. That's the kind of thing you can sell at your workplace and try to get everyone onboard.

The Typescript situation

Need to call out how Typescript is skyrocketing in its adoption and popularity as these projects fight for a similar space, they are all fundamentally different. Typescript adds type annotations to JS and that's a great thing but these languages add a different kind of value. Their syntaxes vary from Javascript and they pull in a lot of inspiration from places like Haskell. Some of them enforce functional programming constructs whereas Typescript adds niceties to JS. The advantages are that it's super easy to adopt but the downside is that you still don't get a lot of guarantees on TS codebases.

Having authored exclusively in TS for past couple of years, I think I need an upgrade. I am grateful that it's such an exciting time to be in this space and we have so many good options available to choose from.

Built with passion...

React

Used mainly for the JSX templating, client-side libraries and job secruity.

Gatsby

To enable static site generation and optimize page load performance.

GraphQL

For data-fetching from multiple sources.

Contentful

CMS to store all data that is powering this website except for blogs, which are markdown files.

Netlify

For static site hosting, handling form submissions and having CI/CD integrated with Github.

Images

From unsplash when they are not my own.

..and other fun technologies. All code is hosted on Github as a private repository. Development is done on VS-Code. If you are interested, take a look at my preferred dev machine setup. Fueled by coffee and lo-fi beats. Current active version is v2.12.1.

</VR>