Adobe Tech Blog
Published in

Adobe Tech Blog

Traits from Rust for Javascript: Using Ferrum.js to implement custom protocols

A while back, we released ferrum.js, a relatively small javascript library that “brings features from rust to JavaScript” in a way that is supposed to feel native to js developers. When we first started to write the library we began by trying to answer two key questions; the first of which is a bit provocative I admit: Why is there no good library for working with es6 iterators that integrates well with javascript syntax?

Associated video!

We decided to tackle the problem head on: by writing just such a library!

The second question we had to address, turned out to be more complex; “How can we implement a function like equals() or hash() correctly in javascript?" Here’s how we tackled that one, too.

How to (badly) implement equals

It seems like there are a lot of implementations of these kinds of functions; lodash has one for instance. For hash() there is object-hash, which I contributed to myself a while ago! In principle, implementing a function like equals is relatively easy:

All these implementations have a drawback though: They can’t support any types they don’t know about; like this one for instance. They have to add an if clause for every single type they want to support; this gets tedious very quickly.

Using ferrum.js to get it right

So, in order to implement equals() correctly, we need to support all the types your users might want to create; the function needs to be extensible!

Here is where ferrum.js comes in; it provides a helper class called Trait (one of the features borrowed from rust — see Rust Traits) to define extension points for functions like equals().

Ferrum already provides implementations of eq() for all standard types (Array, Map, Number, Date, etc.), so you just have to implement an equality function for your new type.

Internally, the library uses ES6 Symbols to find the implementation; this is the recommended way to implement generic interfaces in JavaScript. All ferrum does is wrap this in order to provide a more convenient interface to handle a lot of edge cases.

The Iterator Protocol uses Symbols in this way to implement ES6 iterators. You can even wrap existing protocols; for instance, the Sequence Trait is just a wrapper around the iterator protocol, created to make use of the advanced edge case handling of ferrum. One example: The Sequence Trait can support plain Objects, while the Iterator Protocol cannot.

Ferrum is also designed to be null/undefined safe; many functions explicitly handle null/undefined as a special edge case. Traits can even be implemented for null and/or undefined; our equals() implementation above on the other hand would simply crash. Ferrum even provides the typesafe module to safely deal with null/undefined values.

This was one of our main motivations when creating ferrum; while Rust has been designed to be safe and avoid a lot of those edge cases, JavaScript has historically had a lot of them. Ferrum is designed to take as much of the edge case load of the developer…anything that fits that description should probably be part of the Ferrum ecosystem — make JavaScript a bit safer.

What’s next?

Ferrum is currently under active development. One upcoming big feature (again, borrowed from rust) is documentation testing. Ever found that the examples in your documentation were full of bugs? This allows you test your documentation!

Other features expected to be released this year as a part of ferrum:

  • A Hash trait, and Hash tables supporting arbitrary keys.
  • A Ord trait and ordered maps supporting arbitrary keys.
  • Support for rxjs Observables and Asynchronous Iterators; all using the familiar Ferrum Sequence api!

--

--

--

News, updates, and thoughts related to Adobe, developers, and technology.

Recommended from Medium

The trade-off between query performance & data consistency when working with connected data in…

A user schema defined in user.js file

Building CORS anywhere using Vercel

Scroll Into View If Needed

Easy Command Line Scripts With Node

Dynamic Feature Flags with ConfigCat

Binary search and two pointers

Polling in Angular 8

Union find

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Karolin Varner

Karolin Varner

Software Engineer for Adobe. Coding in Rust, C++, Javascript.

More from Medium

PipyJS — A functional style JavaScript engine for programming Pipy

Create a library package with npm

Creating either CommonJS or ES6 modules for Node.js packages using Typescript

Interfaces In TypeScript