Racket is probably the finest example of a modern day lisp bar none. It encompasses a range of features that support various programming paradigms and caters to many developers needs in 2023. Let’s take a look at a quick feature list…
Built in package manager called raco
Supports for gradual static typing that is actually checked by the compiler
It can create an executable
Great documentation both in the form of a technical reference and a friendlier guide
Built in cross platform gui in its standard library that’s easy to use
An installer for Windows, Mac (including M1), and Linux
A Discourse Forum for asking questions and showing off projects
Active Discord for asking questions and geeking out about the language
In addition to these expected modern features, Racket offers a plethora of others that make it stand out among modern programming languages.
Great for young and beginner programmers
Racket excels as a programming language for young learners and beginners. John Carmack mentions how his 10 year old son enjoyed The Quick Introduction to Racket with Pictures, and even went on to create a game using the language. Racket's simplicity also extends its usefulness in teaching programming to Academics in the humanities with a killer feature we will get to later.
As Racket is a type of Lisp, specifically a Scheme, it benefits from all the advantages a Scheme has. Lisp languages have straightforward syntax, with everything wrapped in parenthesis, which means beginners aren't burdened by complex syntactical elements such as decorators, list comprehensions, or a plethora of keywords. This simplicity is further enhanced by its built-in IDE called DrRacket.
DrRacket is simple to get started with and doesn’t require any setup as it comes with Racket when you install the language. It can be launched from the command line by typing the word drracket
and can be searched for in the Windows Start Menu with the same word. Once open, you can just create a file, type some code, and hit the green arrow button to run it. All the code is syntax highlighted automatically so there is no need to figure out how to install plugins to support the language. The repl on the bottom of the program will print out helpful error messages when you make mistakes, and when you hover over variables, arrows are drawn to the places in your code where the variables are used. Here’s what John Carmack has to say about it.
One of the non-obvious things that I think is beneficial with DrRacket is that it has an approachable complexity level. Dropping a newbie into Eclipse or MonoDevelop makes them feel like they are walking around in a byzantine museum, afraid to touch things, while DrRacket feels closer to old-school personal computers where you felt like you were in command of the machine.
As someone who knows how to program, even I get frustrated with the setup that is required before I can even start programming in some languages. Will the basic nature of DrRacket eventually fuel your desire to move to VS Code or Emacs? Maybe, or maybe not. DrRacket has a Debugger and Macrostepper built in that keep it being useful long after you might have switched to a “big boy” editor. Did I mention all of its capabilities are cross platform? No more trying to teach a beginner programming course and having to setup a development environment differently depending on whether you have a laptop with Windows, Mac, or Linux. There are other reasons why Racket is a good language for beginners and non programmers but probably the most useful one comes from Racket’s standout feature.
Designing languages
As with other Lisps, Racket possesses powerful macro capabilities, but Racket's macros are a tier above. Using the #lang syntax
, Racket allows you to create domain-specific languages (DSLs) or entirely new languages. This point requires some clarity. What I’ve been calling Racket so far is actually called GNU/Racket…. I’m kidding. But in all seriousness, Racket is made up of two components. There is Racket the language, which is a Scheme with all the parenthesis you’d expect, and there is Racket the Language Platform/Virtual Machine, on which new languages can be built and run. Because of this distinction Racket is unique in thaat you have to tell the Virtul Machine what language the source code of the file you're working on is in. This is by design as Racket supports a wide variety of languages including the Scheme Racket. For most people #lang racket will be the most common language you use, but there are many others.
As an example, Alexis King’s Languages in an Afternoon talk showcases how, in just a few weeks, she developed a language called Tulip using Racket's language building capabilities.
Tulip, with its drastically different syntax from Racket, was implemented by leveraging Racket's tooling, such as syntax highlighting and jump-to-definition, that are provided by DrRacket. This seamless integration is possible because any language built on top of Racket ultimately transpiles to Racket. Since DrRacket understands Racket code, it can also comprehend any language built upon it. In a way due to the unique nature of Lisp, by transpiling your language into Racket you’ve effectively created an abstract syntax tree for your language without even trying. Which has a lot of the same benefits that Tree-sitter gives when it comes to “understanding” a language through a grammar so that it can do syntax highlighting and complex find and replace queries.
Furthermore, building on the Racket Virtual Machine grants access to a robust standard library without the need to develop essential components from scratch. Whether you need an XML parser or a package manager for your language, Racket's infrastructure has you covered. When creating a new programming language, there are a lot of things a modern language needs to have in its standard library for it to be considered “useful”, which older languages have had the luxury of decades to add. This is not unlike the issues seen when creating a new operating system that is anything more than a toy.
A great example of what a modern standard library might look like in a new Programming language is the Crystal Programming Language, which has been around for less than 9 years. Implementing TCP sockets, JSON/XML/YAML parsing, UUID, OAuth modules, as well as all the standard features to interface with an Operating System is a lot to ask for a new language, especially if it’s being developed by one person, as they usually are in the beginning. But since you can call Racket code from your new language, you can leverage Racket’s standard library without having to make your own, simplifying the process.
Racket's language building capabilities extend beyond just DSLs. Scribble, a documentation language built on top of Racket, allows you to embed executable code directly into your text. When executed, this code generates HTML, PDF, or Markdown files, seamlessly integrating code samples into your documentation. Take a look at this example using Scribble.
#lang scribble/base
@title{On the Cookie-Eating Habits of Mice}
If you give a mouse @(number->string (+ 1 2)) cookies, he's going to ask for a
glass of milk.
And the rendered webpage…
As demonstrated, by simply changing the first line to #lang scribble/base
, Racket understands that you are writing in Scribble, and the code is executed and displayed in the desired output format. DrRacket has the ability to recognize scribble files and besides providing syntax highlighting, also adds two buttons next to the run button called Scribble PDF and Scribble HTML which allow you to create the respective file formats with one click without having to drop to the command line.
Scribble is also the file format for which the entire Racket Ecosystem’s documentation is built upon, so it’s had thousands of hours put into figuring out what is needed to support that use case.
But Scribble isn’t just for Racket Documentation. Since the creators of Racket have to write a lot of academic papers, there are other versions of scribble including #lang scribble/acmart
which automatically formats scribble text for publications to the Association of Computing Machinery, as well as many others.
But what if you’re an author who dabbles in programming and want to use Racket to write text that can be output to multiple formats a la pandoc. Racket has a solution for you too. Using the #lang pollen
, you can write code in the pollen language, and then run it through a template for your desired output, and pollen will convert your text from a list of X-expressions to the desired format. You can also define variables for character names and other story elements within your code, which can then be substituted automatically when rendering your "book" as an HTML page. In Pollen The book is the program.
In my short story Rigor Mortis I have a file called pollen.rkt
which is a convention in the language. In it I can set up global variables which I can use throughout my story. I can associate certain html tags to code like headline
for the html element h2, I can create quick two letter variables like “mc” for main character “b1” for boy 1, and then sprinkle the variables throughout my story.
When I render my pollen files, a html page is created and every instance of ◊|mc|
gets substituted for the name “Cody”. Code wrapped in ◊|em|{}
gets italicized, ◊|b2|
becomes Zach etc, etc.
Later on, if I decide Cody is really a Jeff, then I just change one line in the pollen.rkt
where (define mc "Cody")
is defined and Pollen does the rest. No tedious find and replace necessary, and no mistakes. There is another advantage of using code as data, a concept all Lispers are familiar with. Since Pollen is compiled, any variable or function I write and use in my code is handled like Racket code. This means if I try to use variables that aren’t defined, Racket will tell me what the error is, and what variable I’m using that hasn’t been defined. This ensures any changes I make always work if the page renders.
But maybe you’re not interested in writing, and are just a beginner programmer working through the How to Design Programs book. You could start with the Beginning Student language, tailored for novice computer science students.
The Beginning Student language is a small version of Racket that is tailored for beginning computer science students.
Then you can move on from the Beginning Student language to…
Beginning Student with List Abbreviations: An extension to Beginning Student that prints lists with list instead of cons, and accepts quasiquoted input.
Intermediate Student: language adds local bindings and higher-order functions.
Intermediate Student with Lambda: A language that adds anonymous functions.
Advanced Student: A language that adds mutable state.
And then to full fledged Racket. With each language another pair of training wheels is taken off, and more of the standard library and advanced features becomes available. These languages sacrifice some of their speed to add extra checking for common mistakes made by beginner programmers. This allows programmers to learn how to do things the right way with helpful error messages that explain errors in simpler terms, to give them a feel for the language before they make the jump to the full language.
This isn’t to say you have to do this before jumping right into #lang racket
, but Scheme has always had roots in pedagogy, and these languages emphasize Rackets commitment to those roots.
Getting stuff done 💪
In Racket you can quickly prototype new software ideas. With a cross platform GUI you can write a new file browser because the one on your computer blows.
You can make quick prototypes of a special purpose meme making software, because Racket makes it easy.
You can write a typed and untyped version of Conways game of life to dip your toes into Static vs Dynamic typing.
As well as anything else you use a general purpose programming language to do. But maybe you hate parenthesis and love Java. Well, the #lang profj is for you.
#lang profj/full
class Example {
static String result = null;
public static void Main(String[] args) {
result = "Hi";
}
}
After looking at the above example, maybe you realize that what you really want is a lispy Haskell. Well then why not try Hackett?
#lang hackett
(data (Maybe a)
Nothing
(Just a))
(def x : Integer
(let ([y 3]
[z 7])
{y + z}))
(class (Show a)
[show : {a -> String}])
(instance (forall [a] (Show a) => (Show (Maybe a)))
[show (λ* [[(Just x)] {"(Just " ++ (show x) ++ ")"}]
[[Nothing ] "Nothing"])])
Or maybe you need a lazily evaluated version of Racket because you are working with a large stream of infinite data, well lazy racket is for you. And if no other programming language in the world fits your need, you can always make your own!
I hope this article has demonstrated some of the reasons why Racket is an awesome language that you should try. It’s got a lot of features programmers expect in the modern day, and is quite easy to get into. If you use Racket let me know what you think of it, and if you’ve created a cool new language using it, drop a comment down below!
Call To Action 📣
If you made it this far thanks for reading! If you are new welcome! I like to talk about technology, niche programming languages, AI, and low-level coding. I’ve recently started a Twitter and would love for you to check it out. I also have a Mastodon if that is more your jam. If you liked the article, consider liking and subscribing. And if you haven’t why not check out another article of mine! Thank you for your valuable time.
If I wanted to just use Chez Scheme in DrRacket, how would I do that?
It's a trick question, there is no #lang, and #lang r6rs does something completely different.
Then there's several major issues with prominent figures of the community. Felleisen has allegedly abused people for decades, Butterick is suing over Github Copilot, arguably the most significant productivity software ever created. On top of that, there's a large prominence of authors that are present one year, gone the next, presumably from using Racket for school/university projects and then leaving once they start working on real software at their jobs after they graduate. Understandable, but doesn't leave a good impression for any organization that might be interested in using Racket professionally. Only example I can think of is Hacker News, which serves a few kb of text and can't yet manage the apparently complex world of pagination. Of plain text.
So, I think the landscape for Racket is a bit more bleak than represented here.