The Future of Programming: WebAssembly & Life After JavaScript

Share this article

Recently we heard that the web platform is getting a new browser-native compile target called WebAssembly (see What is WebAssembly: The Dawn of a New Era for details). Wasm makes the web platform a more attractive compile target for other languages. That leaves us wondering what might come after JavaScript.

JavaScript has some great features, but I sincerely hope we move on as soon as possible. JavaScript is great and it taught us a lot, but programming will evolve. There will be life after JavaScript.

I’m not a fan of C++ (I’m a recovered user and abuser of C++), but I am a fan of many things built with it, including the Unreal Engine, which runs great when compiled to JavaScript. There’s no good reason to write everything in JavaScript forever. It’s time to look to the future.

I’ve been using and really enjoying CoffeeScript from time to time, which helped inspire a lot of the new ES6 features. CoffeeScript feels much simpler than JavaScript. It has a more concise syntax, yet adds a lot of expressive capability that did not exist in ES5. Of course, I’d simplify CoffeeScript even more by ridding it of the poisonous class keyword. I like to fiddle with Haskell, too. But these languages represent the present.

So what could we do next?

Whatever catches fire after JS, I hope it has these features:

  • Built-in immutable data structures and immutability by default.
  • Literal forms for objects, collections, and primitive types.
  • A better default number type for most use cases.
  • Custom structural types, including good support for low-level binary types (bonus if we get definable literal syntax).
  • Lambdas with closures.
  • Functional utility belt built-in. Similar to the RxJS Observable API.
  • Native support for object and factory composition. Something like built-in stamps.
  • Realtime guarantees for low-latency processing & precision scheduling for apps like gaming, music & video production, DSP, scientific applications, synchronization of distributed systems, etc…
  • Minimal syntax, similar to Ruby, Python, or CoffeeScript. Now that I’ve had a chance to get comfortable without curly braces and semicolons everywhere, I feel a lot less confined by syntax.

First-class Support for Reactive Programming

Baked into the language, a simple, consistent API around all of these:

  • Streams.
  • Continuous data sources (UI inputs, time, vector images, etc…).
  • Collections including arrays and objects.

This API should be used the same way regardless of whether data flows through the functions one value at a time (i.e. iterables / generators + yield), in response to emitted events (e.g. Node-style streams), or continuous data sources such as audio, electrical signals, UI inputs, sensors, even time-independent things like vector graphics, etc…

A built-in API like this could wrap all types, which has the potential to simplify the syntax, as well.

For a really insightful perspective about how all this reactive stuff works, check out A General Theory of Reactivity.

Better Tooling

Unreal Engine 4 Blueprint Unreal Engine 4 Blueprint

  • A fantastic visual IDE for easily modeling and visualizing reactive relationships in the system. Think NoFlo with a much better UX.
  • Time-travel debugging (example with JavaScript) enabled by immutable data structures. Time-travel debugging lets you easily shuttle back and forth in the history of your live, running program.
  • Compile to JS & wasm great support for browsers and Node.
  • Better analysis tools both static and runtime / dynamic. Specifically designed to help make programs more predictable by analyzing reactive dependency graphs. These could create great visual reports, too, including complexity reports, and marble diagrams to help you further understand and predict the behavior of your program.

Marble diagram for .merge() Marble diagram for .merge()

Visual IDEs Will be the Norm

Those familiar with flow-based/dataflow programming will rightly tell you that it’s nothing new. Visual programming tools have been around for decades, and have so far been unable to replace text-based programming.

What will push this over the edge is a radical rethinking of how to model programs visually that will reduce the visual clutter and wiring overhead that plagues most flow-based programming solutions.

Most of the innovation in this space is not happening in programming environments at all. Instead, it’s happening in production applications where data flow modeling is the primary task. Nowhere is this better illustrated than in audio production apps.

Audio production apps typically route raw audio through a network of effects processors. In programming terms, you could think of an effects processor as a functional map: a pure function called for each element in a list, where those elements correspond to an audio sample slice.

Most audio apps model this process visually by simulating the real machines and cables in skeuomorphic fashion. A skeuomorphic user interface is one that attempts to emulate the user interface of the original object being modeled in software.

The problem with skeuomorphic design is that it faithfully reproduces most of the user interface clutter and inefficiencies of the original. In data intensive applications such as audio production, that clutter looks remarkably familiar to programmers: The wires look a bit like spaghetti — something all good developers know we should avoid.

BayAreaModularMeet — George P. Macklin — (CC BY-SA 2.0) BayAreaModularMeet — George P. Macklin — (CC BY-SA 2.0)

But recently, software such as Ableton Live and Renoise have found clever ways to rid themselves of wire clutter completely using channels and chains.

An Ableton Live effects channel. Data flows left to right. An Ableton Live effects channel. Data flows left to right.

In other words, data flows through channels, and each channel consists of a chain of effects. No wires are needed, because the effects are applied in sequence.

Renoise channels, each with an effects chain. Data flows top to bottom. Renoise channels, each with an effects chain. Data flows top to bottom.

In code, a channel might look something like this:

const channel = input => {  
  return input  
  .filter()  
  .gain()  
  .limit();  
};

export default channel;

If you think about this carefully, it becomes clear that you could do a lot more than audio & Digital Signal Processing (DSP) with this model. For example, you could use it to visually model routes and middleware in Express, where routes are represented by channels, and middleware is represented by effects:

A hypothetical Renoise-inspired UI to program routes. A hypothetical Renoise-inspired UI to program routes.

Of course, this implies that each effect in the chain needs to act on inputs with a shared API. That’s where functional and reactive programming concepts shine. It’s easy to provide a unified API over any type of collection, including a stream of network requests. In functional programming, those wrapping APIs are called functors. In plain English, a functor is something that can be mapped over.

If this sounds a bit like science fiction, take a look at Treeline. It does something very similar today. Take a look at this POST /signup route modeled in Treeline. It encrypts the user’s password, then creates the user model, then responds with status 200 OK. Each of those steps could be thought of as a channel effect:

Treeline: Data flows top to bottom. Treeline: Data flows top to bottom.

Genetic Programming

Genetic programming is the process of simulating nature’s evolution system by producing populations of candidate programs and filtering out the programs that don’t pass the tests. The candidates that do pass the tests survive and form the basis of the next generation.

Genetic programming offers the possibility of continual, automated improvement on hot code and critical algorithms. There is real potential to point a genetic programming algorithm at a git repository and automatically push new generations of software to production when the population improves on prior deployed versions.

AI-Assisted Programming

Scott Ingram — Dual Neuron (CC BY-NC 2.0) Scott Ingram — Dual Neuron (CC BY-NC 2.0)

Strong AI is here today. Many AI systems are beating humans at our own games across a variety of categories. One major advantage of AI is that it is capable of analyzing a large variety of alternatives very quickly. AI could examine the code you write, search for potential bugs & vulnerabilities, recognize patterns that could be abstracted, suggest tests that need to be written, or even recognize patterns in genetic programming populations and automatically adjust population and environment parameters to fine tune genetic programming algorithms.

In other words, long term, AI has a very real chance of becoming an invaluable programming tool. In fact, it’s easy to imagine a future where AI can produce programs without any human assistance at all.

Conclusion

Whatever comes next, expect it to be a quantum leap in technology and innovation. The future will be here sooner than you think.

Frequently Asked Questions (FAQs) about WebAssembly and its Future

What is the main difference between JavaScript and WebAssembly?

JavaScript has been the backbone of web development for many years. However, it has its limitations, especially when it comes to performance-intensive applications. WebAssembly, on the other hand, is a binary instruction format that allows code to run at near-native speed by taking advantage of common hardware capabilities. It’s designed to be a low-level virtual machine that runs code at near-native speed, making it ideal for tasks such as games, computer-aided design, video editing, and scientific simulation.

Is WebAssembly set to replace JavaScript?

No, WebAssembly is not designed to replace JavaScript. Instead, it’s meant to work alongside JavaScript, allowing developers to choose the right tool for the job. JavaScript is great for building dynamic websites and applications with complex user interfaces, while WebAssembly is better suited for performance-intensive tasks.

How does WebAssembly improve web performance?

WebAssembly improves web performance by providing a more efficient binary format for the web. This binary format allows the code to be parsed and executed more quickly than JavaScript. Additionally, WebAssembly is designed to be a low-level virtual machine that runs code at near-native speed, which is a significant performance boost for performance-intensive tasks.

Can I use WebAssembly in my current web projects?

Yes, you can use WebAssembly in your current web projects. Most modern browsers support WebAssembly, and there are several tools available that can help you compile your code to WebAssembly.

What languages can be compiled to WebAssembly?

Currently, C, C++, and Rust have the best support for compiling to WebAssembly. However, the goal is to support as many languages as possible in the future. There are also ongoing efforts to add support for other languages like Python, Go, and Java.

What are the security implications of using WebAssembly?

WebAssembly is designed with a strong focus on security. It operates within the same sandbox environment as JavaScript, meaning it has the same access restrictions. Additionally, because it’s a low-level binary format, it’s less susceptible to certain types of attacks that are common with JavaScript.

How does WebAssembly interact with JavaScript?

WebAssembly can interact with JavaScript in several ways. For example, you can call JavaScript functions from WebAssembly, and vice versa. You can also pass data between the two, although this currently requires some manual work.

What is the future of WebAssembly?

The future of WebAssembly looks promising. It’s already supported by all major browsers, and its performance benefits make it an attractive option for web developers. As more languages gain support for compiling to WebAssembly, we can expect to see it used in a wider range of applications.

Are there any limitations to using WebAssembly?

While WebAssembly offers many benefits, it does have some limitations. For example, it currently lacks direct access to the DOM, which means you’ll need to use JavaScript for any DOM manipulation. However, there are ongoing efforts to address this and other limitations.

How can I start learning and using WebAssembly?

There are several resources available for learning WebAssembly. The official WebAssembly website is a great place to start, as it provides a comprehensive overview of the technology. There are also numerous tutorials and guides available online that can help you get started with WebAssembly.

Eric ElliottEric Elliott
View Author

Eric Elliott is the author of Programming JavaScript Applications (O'Reilly) and Learn JavaScript with Eric Elliott. He has contributed to software experiences for Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC, and top recording artists including Usher, Frank Ocean, Metallica, and many more. He spends most of his time in the San Francisco Bay Area with the most beautiful woman in the world.

jameshmodernjs-toolsReactive ProgrammingRxJSstreamswasmWebAssembly
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week