Welcome to Part V of my VI-part series about , an exciting and fascinating new programming language. Eve How Eve unifies your entire programming stack I. When logic programming meets CQRS II. Throwing off our scope chains III. Smalltalk and protein programming IV. The rock-solid foundation for Eve’s big vision V. Why Eve will be perfect for realtime apps VI. There’s a lot more to be done and a lot more to figure out, but fortunately we have a sound underlying foundation which we get to leverage to make sure things don’t get too far off the rails. It’s nice knowing that as long as we can resolve our semantics back to X, that we can maintain the properties of X. It’s a very tough thing to accomplish, but the results seem to have turned out so far :) — , one of the founders of Eve. Chris Granger In this post, I’ll try to unpack Chris’s statement by listing various areas of programming where I think Eve can fundamentally improve things, thanks to the properties of its core building blocks. Declarative programming Databases typically have query language semantics. In a SQL query, you say data you want to search for, not the query planner should go about looking for it. declarative SELECT what how But application-layer languages typically don’t have declarative semantics. As remarks in its querying : Datomic docs [D]eclarative programming is very powerful, and it is a shame that it has been relegated to the database servers and not available to application programmers. Languages always offer support for declarative constructs, like getting a filtered view of an array: some But usually it’s not baked into the fundamental building blocks of the language; e.g. you can’t get a filtered view of your variables: With Eve, you get to read your application-layer state declaratively, because you get to use the same operation that works for your database layer . search at every layer of your stack Validating data Database data Think about what your application’s database looks like right now. It probably has various data-validation issues sprinkled through it that you aren’t aware of, right? At the time that your program inserted the offending data, either it had a bug, or else it was running a previous version of the code with a different idea about what’s valid. Then when you fixed the bug or updated your program logic, you didn’t have an easy way to clean out every little inconsistency that might have remained. So you said, “screw it, I’ll just fix any bug reports if and when I get them”. Application state There’s an analogous problem at the application layer: how confident are you that your is always correct? Even if you have plenty of _assert_s, it’s hard for them to police your whole program. state Eve’s solution With Eve, you just write a little block of code and you get a global data-validation rule, like this: witheve.com The key is that this block doesn’t have to be invoked by another block of code; ! That’s why Eve has a better foundation for data validation than traditional databases and programming languages. it gets invoked by the invalid data it’s watching for Types and schemas Types and schemas are really just constraints that pieces of data are expected to obey. That means we can build type systems and schemas in Eve by writing data-validation blocks like the one above. Well, you and I probably won’t do it that way, but that’s the foundation on which a variety of higher-level libraries will be built. Dependency tracking Say your program has a variable , and at various points it also needs to know the value of rounded to the nearest hundred: x x Well, you probably don’t want to give its own variable because you don’t mean it to be a separate degree of freedom in your program state; you mean it to be a fixed of . So instead, you might write it as a function: nearestHundred dependency x That’s fine for a simple , but how about if were a CPU-heavy computation? Then you’d want to compute it the fewest possible number of times — i.e. compute it once, then cache the result until changes. If your language or framework helps you do that automatically, that’s called . Math.round getNearestHundred x dependency tracking Dependency tracking is similar to , but we can’t memoize because it’s not a — it depends on but it doesn’t take as an argument. memoization getNearestHundred pure function x x There are basically two ways to deal with -like situations: nearestHundred Become purists and never let functions access any program state except for their arguments. So becomes , and so on everywhere in our code. This is what purely-functional languages like make you do. functional programming getNearestHundred() getNearestHundred(x) Elm Use a dependency-tracking framework. This is what the JavaScript library is best known for, although it’s also been done by , , and others. MobX Meteor Knockout Derivable ( is an awkward middle ground between #1 and #2: you break chunks of state away from your UI views and quarantine them in a functional-programming-only zone.) Redux In , I pointed out that a block in Eve is similar to a expression in MobX. Intuitively, both are similar to a spreadsheet formula: Part I bind computed @computed function B1() {return (Math.round(A1) / 100) * 100} With Eve, you get to enjoy language-level dependency tracking, using anywhere in your code the same way you’d use cell anywhere in a spreadsheet. nearestHundred B1 Runtime debugging Watch expressions How often do you bother to use watch expressions for runtime debugging? It’s usually not worth the effort because state is so . tightly coupled to scope chains In Eve, you also don’t need watch expressions, because a section already a watch expression. If you want to use a block for debugging, all you have to do is add a or section to write to the database. search is search commit bind @view Hot reloading Hot reloading is typically a luxury that has to be painstakingly hacked into most languages and frameworks. But Eve shipped it on day zero, thanks to the language’s hot-reloading-friendly building blocks. In the editor, each block of code can be activated or deactivated with a checkmark, and everything magically adjusts. Serializable state The entire state of a running Eve program is easily serializable into a file. Your users can attach a “state file” to their bug report and you can reproduce their exact state: https://www.youtube.com/watch?v=TWAMr72VaaU Smarter UI inspector tools A web browser’s inspector tool does an admirable job of showing you the state of the UI, but it doesn’t understand how your code is related to that state. Eve understands the UI looks the way it does. why The demo video already shows impressive GUI features for jumping to relevant blocks of code when inspecting a UI. …and more In addition to Eve’s improvements on existing debugging tools, we can expect the Eve community to conceive of better debugging tools than we’ve ever had. In fact, I dare to imagine that Eve will make console prints obsolete. By the way, you know what debugging feature Eve have? Stack traces. doesn’t “Focusing on the machine and ignoring the human factors of software engineering have led us down a difficult road.” — witheve.com Unit testing In traditional unit testing, it’s often hard to fake an entire scope-chain-based state. Also, it’s sometimes hard to isolate a modular unit to test. With Eve, you can always test individual blocks of code and get a clear picture of their data flow. Performance optimization If you’ve ever used a CPU profiler to figure out how to optimize a loop somewhere, then you know it’s a pain to understand which level of the call stack is the real culprit. Say function A calls function B, which calls function C. If A is using a lot of CPU, that doesn’t necessarily mean that A is badly written; it could also be B or C. Eve doesn’t have a call stack; blocks of code can’t directly invoke other blocks of code. So if something is slow, you can easily isolate which block of code is responsible. And if you’ve ever used a memory profiler to improve memory leaks… well, traditional memory leaks are impossible in Eve! There’s no way for obsolete state to get trapped in a gnarly chain of closures, so no memory profiler needed. Ask yourself, how many memory leaks have you ever dealt with? And how many times have you ever had a bug involving inserting a ton of records into a database? Ok great, because the only way your Eve program can hog tons of memory is if you’re purposely committing tons of records into a local database. Distributed data and computation It’s hard to manage the chaos of things happening in parallel, whether it’s data or computation. The website for , the original -based language, explains the problem: Bloom Dedalus Much of the pain in traditional distributed programming comes from this mismatch: programmers are expected to bridge from an ordered programming model into a disordered reality that executes their code. Eve is an “orderless language”. Eve’s only ordering guarantee is At each timestep, all code blocks (each with one or more / / sections) read in that timestep’s snapshot of the world, and they all write to the next timestep’s snapshot of the world. Kind of like . synchronization of blocks. search bind commit Smalltalk and protein programming Eve has the potential to make distributed data and computation more accessible: Writing simple Eve code to manage complex data transactions at scale, the kind that require locking multiple distant shards. Using Eve to spread a computationally-intensive task across a multi-core CPU or a massive server farm in the cloud, by writing the same code you’d write for a single core machine. The Eve team calls this vision the “ ”. world-scale computer **Next post:** . Why Eve will be perfect for realtime apps VI
Share Your Thoughts