Grain started as a passion project with a simple premise: It was 2017 and Philip Blair and Oscar Spencer wanted a high-level language that was easy to use and designed to compile to WebAssembly.
“I said at the time, if you’re going to make the language and have someone care about it, it’s going to be right now and it’s going to be a language for WebAssembly, and so that was the idea,” Spencer told The New Stack. “A buddy and myself, we got together and we said, let’s make this thing target Wasm. I remember we got our first host functions working, being able to call in the browser, so actually have some DOM APIs and make buttons do things and stuff with the language, and we were really excited. And that was just the birth of the project.”
The core team has since expanded — Grain released version 0.6 in March — but the goal remains the same: A high-level language that developers would want to use every day.
“It’s not for like some huge commercial enterprise,” Spencer said. “It’s more, hey we want to have fun just building something that we think is awesome. And so here we are today, we’re still going. The core team has expanded. People think it’s interesting.”
A Modern Day OCaml
“Pattern matching is this incredible, powerful programming language feature that most languages have not had at all.”
– Oscar Spencer, co-creator of Grain
The goal was to create a modern-day OCaml, he said.
“OCaml [was] this fantastic language from the ’90s, with all these amazing different language features … one of the huge features was pattern matching,” he said. “Pattern matching is this incredible, powerful programming language feature that most languages have not had at all.”
Pattern matching in languages like OCaml, Grain and Rust means the compiler will alert the developer if an edge case is missed and a piece of data might break the program, he explained.
“That is such a powerful concept; just because of that you eliminate so many different possible bugs in your programs,” Spencer said. “One of the funny things they say about OCaml is [that] if your code compiles, it’s correct. It might not do what you wanted it to do, but it’s definitely doing what it’s supposed to do based on the code.”
That’s not something you have with JavaScript or Python, he added.
“You write those programs, and it’s broken, you’ve got to go figure out why is the thing broken. And you put in a bunch of log statements and try to debug it and it’s a pain in the butt when you have these other languages that are able to just tell you, ‘Hey, here’s exactly how your code is broken,’” he said.
How Grain Compares to Other Languages
“If you’re coming from JavaScript, you’ll feel comfortable with the syntax.”
Grain will look most familiar to React developers because the syntax of Grain has a lot in common with JavaScript, which Spencer described as sort of a generic C-style syntax.
“If you’re coming from JavaScript, you’ll feel comfortable with the syntax. You’ll feel comfortable with some of the ideas of functional programming because you’ve done things like React, you’ve done things like higher-order components and things like that in React,” he said. “You’ll be sort of comfortable with those concepts and then learn we’re not going to do JavaScript dynamic typing and things like that. It might take you a little bit to adjust, but you’re going to be able to see the benefits very quickly.”
He pointed to JavaScript, a language that was not really designed for functional program until React came out and was based on functional programming concepts. Grain-supported functional programming from the beginning. And while it’s now possible to compile languages such as Python and JavaScript to WebAssembly, that approach will create larger modules than Grain, he said.
Grain will become even more effective with efforts such as WasmGC (WebAssembly Garbage Collection), a proposal to add struct and array heap types, which means support for non-linear memory allocation.
The point of Grain is to remain simple and keep it “super easy” for people to get into WebAssembly.
“As we take on things like WasmGC, for example, we’re going to be able to get even smaller,” Spencer said. “And so now, we’ve got languages like Dart that are able to compile to WebAssembly and take advantage of WasmGC in the browser and have really, really tiny modules, which is freaking sweet to see.”
The point of Grain is to remain simple and keep it “super easy” for people to get into WebAssembly, he said. To that end, they have actually rejected suggestions that would complicate the language. Plus Grain doesn’t have the baggage other languages do because it was designed from inception with WebAssembly in mind. It even has Wasm as a keyword, he added.
“Grain is one of those languages that’s amazing for your business logic. I have a problem that I’m needing to solve and Grain helps you reason about your problems very well,” he said. “It’s very data first… We’ve got things like pattern matching to deal with the different ways that folks are going to interact with the data, handle all of our cases, things like that. So it’s fantastic for that sort of thing.”
It’s less effective at low-level tasks, such as if you wanted to write a cryptography library, he said. It doesn’t micromanage every single byte that’s flowing through a program, as you might with Rust, he noted. It’s not particularly designed to run in the browser, though, despite its WebAssembly heritage. It’s designed to build enterprise software and is a very effective language for coding plugins, he said.
“It’s the same thing when you use Ruby or Python, they have these amazing extensive standard libraries; you feel that you can rapidly prototype code, like you have an idea, you can get it to code really, really quick. That’s the same exact idea with Grain. We can get to code really, really quick,” he said.
A Language Built for WebAssembly
Now, it’s possible to compile many languages to Web Assembly, but when Grain was conceptualized, that was not the case. There was C, and some Rust. Spencer thought compilers and programming languages were cool, so it made sense to him to write a language for WebAssembly.
That said, WebAssembly is a bit different than other kinds of assembly languages, Spencer explained.
“It’s much higher level than most of the assembly languages that you’ve seen,” Spencer said. “It’s typed. That’s something that’s a little bit weirder when it comes to an assembly language. But one of the major things about it is it doesn’t have any kind of stack introspection.”
When dealing with assembly code, something as simple as calling a function works differently. The way it works in traditional assembly languages is that you have some code that exists in memory somewhere, he explained. You can just do a jump in memory and point the CPU’s instructions register to the place that the code is and then the CPU will just execute that code, he said.
“You just jump to different locations where these functions are,” he said. “In WebAssembly, we don’t do that. We just have high-level functions. You just define the functions and you call them. That’s actually pretty different to how traditional assembly languages work.”
“We’re targeting WebAssembly, so we can assume that we’re not going to have stack introspection. Let’s just work with the primitives that we have.”
One of the things that compilers have struggled with is called ‘walking the stack,’ he continued. Compilers have gotten around that by implementing a shadow stack, in which they just keep a copy of everything that’s on the stack and deal with it that way, he said.
“Typically a program is running and you have a bunch of functions that are currently on the call stack, and one of the things compilers can do is they can just write some code that just goes and looks at what’s currently on the stack,” he said. “That’s not something you can do in WebAssembly for a number of reasons,” including security concerns, he added.
Grain embraced that.
“We’re targeting WebAssembly, so we can assume that we’re not going to have stack introspection. Let’s just work with the primitives that we have,” he said. “It gives us a lot simpler compiler design.”
They have opted to try out new WebAssembly features in the language, which he acknowledged has been hard to keep track of, since it is a passion project and not their full time job.
“That’s a lot of the ideas. Let’s just put this stuff straight in, see what happens, take it from there without having to have a bunch of overhead of thinking about all these other targets,” he said. “But of course, the idea is [that] WebAssembly code can run anywhere, right? So we don’t necessarily need to target those other targets. We can just compile native code from Wasm if we really need to do that sort of thing.”
Grain is strongly typed, which is also a little bit weird when it comes to an assembly language, he added.
Component Support Coming
Grain does not natively support components, but is moving in that direction, he said, anticipating that in the next couple of releases, it will offer first class support for components.
The component model is a new specification that “sits on top of the core WebAssembly specification,” he said.
“For a language to support the component model, there’s actually a couple of things that go into that; mostly, [it’s] adhering to what’s known as the controlling models, canonical ABI, an application binary interface,” he said. “Essentially, big picture what the component model does is it defines high-level types for all of the different pieces of data that you might want to pass in between components, or between a host and a component.”
Traditionally, the way that a language might pass a string from one component to another component, is by having a pointer to the bytes that are in memory.

From Grain’s documentation
“The way that you would do this in C is you would just put a null character at the end of the string,” he said. “You would take a look at these bytes and you read all of them until you hit a null byte, and then that’s your string.”
Another language might do this by just having those bytes in memory, and then not be terminated by a null byte and instead just provide the length of the string, he added.
There’s a canonical ABI that defines the encoding of Wasm components, and that’s important to languages being able to communicate with each other, he explained.
“The canonical ABI says, Hey, I’m going to tell you this is how we’re always going to talk about strings: A string is always going to be a pointer to some bytes and a length, so you don’t have to worry about if the string contains null bytes or things like that,” he said. “A big part of language that’s supporting a component model is making sure that they’re able to adhere to this canonical ABI. It doesn’t mean the languages have to go restructure their entire compiler or anything like that. But it does mean at least the API that the modules provide must at least adhere to that interface.”
“If you want to take full services and compile them into [WebAssembly] components and deploy them as individual services, you totally can.”
Languages that use the LVM — the Logical Volume Manager is a device mapper framework that provides logical volume management for the Linux kernel — aren’t going to have to do too much to support components because the LVM will go ahead and translate the C, he said. But for languages like Grain and other non-LVM-based languages, more work has to be done to make that happen.
“Rust, for example, doesn’t natively support components, however through this project called WIT bindgen — WIT is the WebAssembly interface types — you can give it a definition of what the types of this module are going to look like and it can generate all the code to provide the canonical ABI interface. So that way, you can actually talk to another module,” he said. “We’re still super early days. Give it a year or two and most of this will go away, no developer will ever need to think about it. But for now, we do have to think about it to make sure we’re adhering to the ABI, so the components can have that dream of talking to any component.”
That is the low-level look at components, which language writers such as Spencer must consider. From a higher-level view, it is possible to compile larger pieces of software together down into WebAssembly components and compose them as if they are services, he added.
“WebAssembly components actually do blur the line between being a library or being a service, because you have full control over whatever you want to do with it,” he said. “If you want to take full services and compile them into [Wasm] components and deploy them as individual services, you totally can. If you want to take those same exact components and just pull pieces out of them and use them as library code, you can do that too. That’s probably more the way people should think about components, just in these early days.”
Editor’s Note: Mr. Spencer misspoke about the decade in which OCaml was created. His quote has been updated to reflect the correct decade at his request.