Let’s make stacker, a programming language that functions as a stack-based calculator.
Our language maintains a stack of arguments, which starts out empty. Each line of the program puts a new argument on the stack. If it’s a number, it’s simply pushed onto the top of the stack. But if it’s an operator — either + or * — the top two arguments from the stack are popped off, and replaced with the result of applying the operator (meaning arg1 + arg2 or arg1 * arg2). So this sample program means 3 * (8 + 4), and when it runs, the result is:
The stack is implemented with a , the basic data structure of Racket. By convention, the top of our stack will correspond to the left side of a Racket list. Let’s visualize how the stack changes after each instruction, using the rules described above:
1 2 3 4 5 6 7
36 ; top value of (list 36)
Easy, right? (If this seems like a weird way to do math, it’s called Reverse Polish Notation and has a long history in calculating machines.)
Though stacker is simple, it will give us a gentle introduction to Racket, including a tour of its language-making workflow. Every language project will follow the same basic steps.
It will also get us thinking about the idea of a “little language” made for a specialized purpose — also known as a or . We can make general-purpose languages with Racket (and, in a later chapter, we will). But languages don’t have to do everything. DSLs are valuable because they can be tailored to the problem at hand.
Some general programming experience is assumed.
No experience with Racket, Scheme, or Lisp is assumed.
Install Racket and the beautiful-racket package as described in Setup.
Make sure your Racket installation works — paste the stacker sample program into a DrRacket window and run it:
If all is well, the result will be: