I’ve wanted to talk about Smile for a long time now.
Smile is a programming language. A decade ago when I named it, it stood for “Syntax Makes Interpreting Lisp Easier,” but don’t tell anybody there’s a Lisp in there, because it doesn’t look, act, or feel like Lisp.
So let’s start at the beginning.
Smile is a programming language.
It is built on extremely solid theoretical foundations, on a cross between the untyped lambda calculus and a message-passing model. The core of the language is built on very simple concepts, rigorously applied at every level to build mathematically-provable abstractions. It’s a language that is designed to make computer scientists giggle with glee at its elegance and simplicity.
It is also a programming language designed for practical use. Real use. By real programmers. Who need to get real things done. It comes out-of-the-box with strong support for strings and files and regular expressions and crunching and slicing and dicing data so that you can solve real problems with it in just a few lines of code. The language syntax is simple and easy to learn, for common problems it reads a lot like languages you already know, a little Python here, a little Ruby there, a little JavaScript over there. That’s by design: You don’t want to waste your time learning another language’s bizarre idiosyncracies. Hello, World shouldn’t take you ages to divine; it should be obvious to any moderately-capable programmer what every character in it does:
#include "stdio" Stdout print "Hello, World.\n"
But maybe it’s a better introductory program if we go one farther and count from one to ten:
#include "stdio" 1..10 each |n| Stdout print-line n
Or just spell that out in a hacky kind of way?
#include "stdio" `[1 2 3 4 5 6 7 8 9 10] each |n| Stdout print-line n
Or maybe we go more elegant and do it using a recursive function instead:
#include "stdio" f = |n| { Stdout print-line n if n <= 10 then [f n+1] } [f 1]
Or maybe we go off the deep end and use the Y combinator!
#include "stdio" [(Fn y |f| |n| { Stdout print-line n if n <= 10 then [f n+1] }) 1]
Okay, maybe not. But you could, and this begins to hint at why Smile is special. It’s a playground where a theoretical computer scientist can be just as happy as B. Corporate Programmer and J. Random Hacker. It’s a place where simple problems become trivial and where hard problems become a lot easier.
Smile is a philosophy. It’s a way of thinking about programming, a way of thinking about problem solving. And it’s built on a very specific set of ten core principles:
- Symbolic computation is the true future of computation.
- A good language must be good at building complex data structures and processing text, first and foremost.
- Metacircular programming and domain-specific languages are critical and invaluable for all problems.
- A good programming language must be built on a minimized handful of core forms for mathematical elegance.
- Lambda calculus and the genius of Lisp are a better foundational model for computation than Turing Machines.
- Object-orientation is a critical conceptual model and must be deeply integrated at the outset into everything.
- A few simple syntax rules can hide the most complicated underlying concepts.
- “Ordinary programmers” will not use new languages that look too different from “mainstream” languages.
- A good language must be readily extensible to meet future needs without changing the language spec or having to release a new compiler or interpreter.
- Fewer keystrokes is better, except when the result is harder to understand.
Fifteen years ago, I started with those ten principles in my head, and set out to design a language that fit them. I set out to build a better Lisp than Lisp and a better Smalltalk than Smalltalk, and there were long periods where I was pretty sure I never would. After dozens and dozens of redesigns, restarts, tweaks, and discoveries, I finally found the last piece of the puzzle about a year ago, and at long last, I had my language. It looks a little like things you know, but it isn’t anything you know. It owes a lot to Lisp and Smalltalk, but it doesn’t look, feel, or execute like Lisp or Smalltalk. It’s simple and clean and has a few core axioms that run deep and wide through it that can be reapplied at every level to build big abstractions quickly. It steals bits and pieces of every one of dozens and dozens of languages, each where those bits fit with the overall philosophy — a little C here, a little Ruby and Python there, a little JavaScript, Self, Perl, Ada, heck, even VB contributed a few bits.
Smile has the mathematical elegance of a handful of core forms. Its code and data share a singular representation, and it has quote and eval and all the implications those carry. It has just enough syntax to make it friendly and easy. It uses objects like objects were meant to be used. It has powerful methods that can slice-and-dice data eight ways from Sunday. Trees are natural tools for solving problems in it, and so are strings. And even with all that, everything somehow manages to fit together and look “just right” when you read it.
The result is one of the most beautiful things I’ve ever built, and I’ve built a lot of stuff. Smile is elegant in a way no language I’ve ever used before is. The current interpreter is kinda schlocky, but it works, it’s correct, it’s faster than I expected, and can be made to go a lot faster. Fifteen years ago, I set out to build a better Lisp than Lisp and a better Smalltalk than Smalltalk, and it blows my mind to think that I might have actually done it.
So stay tuned. I think this is the part where it starts to get good.