Welcome to Part I of my VI-part series about Eve, an exciting and fascinating new programming language.
- I. How Eve unifies your entire programming stack
- II. When logic programming meets CQRS
- III. Throwing off our scope chains
- IV. Smalltalk and protein programming
- V. The rock-solid foundation for Eve’s big vision
- VI. Why Eve will be perfect for realtime apps
Eve is the culmination of years of research and development by the visionary team who previously founded Light Table. Version 0.2 of Eve launched last month and made a big splash on Hacker News, which is how I first heard about it.
This latest version of Eve makes for some very cool live demos, such as “Flappy Eve”:
Scrolling through the flappy.eve demo for the first time, a few striking features jump out:
- The IDE looks like a WYSIWYG blog editor. Eve code is designed to be embedded within Markdown-formatted prose; it’s literate programming to the max.
- The syntax is unfamiliar, but still looks clean and approachable — mostly it just looks sparse. Part of me can’t help thinking, “I see all these bracketed parts, but where’s the actual code?”
So that was my first impression. Here’s my impression after spending hours browsing the examples, pondering over the docs, and watching tech talk videos: Wow!
Eve is a cornucopia of solutions to problems I hadn’t even realized we had. It’s like I’ve been raised in a society of bicyclists, and after seeing a motorized vehicle for the first time, I’m suddenly understanding the limitations of a pedal-based architecture.
After having been exposed to Eve, I can retroactively diagnose various problems in the architecture of mainstream programming stacks. In this series, I’ll try to explain what all these problems are and how Eve solves them.
Problem: Layers doing the same thing differently
Your software stack has many layers. The following three layers are usually the “core system” doing the heavy lifting:
- Database layer
- Remote API layer
- Application layer
But there are also plenty of other layers that the core system talks to:
- Rendering layers
- I/O event layers
- Configuration layers
- Logging layers
At a high level, these layers all do the same thing: they process data. They read input values, they compute other values, they mutate internal state, and they output values to pass to other layers. But, when you zoom into each layer, you see countless differences that obscure the fact that they’re all fundamentally about data processing.
Different data models
You have one or more online database systems. Their data models look like SQL tables, document collections, key-value maps and/or graphs.
You have a remote API that models data as chunks of JSON or XML, or maybe as a GraphQL graph.
You have a running application that models in-memory data structures and variables in a scope chain.
To operate on the database layer, you can send various kinds of SQL or NoSQL queries.
To operate on the API layer, you can query for data via HTTP GET and update data via HTTP POST and friends. If it’s a GraphQL API, you operate with GQL queries and mutations.
To operate on the application layer, you can look up variables from the scope chain, and you can traverse or mutate in-memory data structures.
For each layer of your stack, there are different data models and operations:
Since each layer is different, it creates friction and room for error. You have to reason separately about each one’s properties and guarantees, and use separate programming patterns for each. And you have to write a lot of “glue code”.
Solution: A uniform data-processing language
Eve has a single low-level data model and a single set of operations which you can use across every layer of your stack.
Uniform data model
In Eve, data (a.k.a. state) lives in a set of databases. Different layers of your stack might correspond to different databases, e.g.:
- In-memory application data lives in the
- The browser’s DOM tree lives in the
- User I/O events live in the
Each database contains records. A record is a key-value mapping that can store primitive values as well as references to other records. Records have a simple bracketed syntax:
There are no tables or collections for holding records within a database, just databases containing linked structures of records.
Uniform set of operations
It’s also a uniform set of operations. The three operations
bind make up the entire functionality of Eve:
searchqueries for data, similar to SQL’s
commitmutates the state of your data, similar to SQL’s
bindwrites special “deduced values”, which are like SQL’s materialized views or MobX’s computed values. I’ll say lots more about the awesomeness of
bindlater in this series.
It’s amazing that we can control different layers of the stack by using this uniform set of operations on Eve’s uniform data model. For example, here’s how we render a
<div> into the DOM:
Since the DOM tree lives in the
@browser database, rendering a
<div> just means
commiting a record with
Now, for each layer of your stack, there’s only one data model and set of operations:
Since each layer is the same, there’s less friction and room for error. You can reason more easily about properties and guarantees, and use similar programming patterns for each. And you don’t need to “glue” anything together, because everything’s already connected.
The Eve team invented a uniform data model and uniform set of operations that can operate across your entire application stack. To accomplish that feat, they had to identify a higher abstraction that the rest of us didn’t realize was possible.
To wrap your head around this achievement, it helps if you’ve already put in the effort to understand another abstraction leap that debuted this year: GraphQL.
It takes people a while to understand that GraphQL isn’t a database or a server, but rather a graph query language (or “GraphQL” if you will). The point of GraphQL is to change the client’s view of an API from a small rigid set of REST endpoints to a unified linked-data structure that accepts arbitrary graph queries.
Like GraphQL, Eve also isn’t a database backend or a server; it’s a language at a higher level of abstraction than we’re used to. Consider the example code from a section of Eve’s home page titled “A simple model: the world as data”:
When you run that
search @slack block, you’re communicating with the third-party Slack application, which of course has its own internal database. But you get to pretend that everything is part of the Eve data universe — just like GraphQL lets you pretend that arbitrary API calls are part of a big graph universe.
So if you like what GraphQL is doing for the API layer, but just wish someone would do the same thing for all the other layers in one fell swoop… say hello to Eve.
II. When logic programming meets CQRS