I am a big advocate of learning multiple programming languages. That's mostly because I tend to get bored with the languages I use the most. It also teaches me new and interesting ways to approach programming.
This article is part of another series about writing a "guess the number" game in different programming languages. In this game, the computer picks a number between one and 100 and asks you to guess it. The program loops until you make a correct guess.
Learning a new language
Venturing into a new language always feels awkward—I feel like I am losing time since it would be much quicker to use the tools I know and use all the time. Luckily, at the start, I am also very enthusiastic about learning something new, and this helps me overcome the initial pain. And once I learn a new perspective or a solution that I would never have thought of, things become interesting! Learning new languages also helps me backport new techniques to my old and tested tools.
When I start learning a new language, I usually look for a tutorial that introduces me to its syntax. Once I have a feeling for the syntax, I start working on a program I am familiar with and look for examples that will adapt to my needs.
What is Racket?
Racket is a programming language in the Scheme family, which is a dialect of Lisp. Lisp is also a family of languages, which can make it hard to decide which "dialect" to start with when you want to learn Lisp. All of the implementations have various degrees of compatibility, and this plethora of options might turn away newbies. I think that is a pity because these languages are really fun and stimulating!
Starting with Racket makes sense because it is very mature and versatile, and the community is very active. Since Racket is a Lisp-like language, a major characteristic is that it uses the prefix notation and a lot of parentheses. Functions and operators are applied to a list of operands by prefixing them:
(function-name operand operand ...) (+ 2 3) ↳ Returns 5 (list 1 2 3 5) ↳ Returns a list containing 1, 2, 3, and 5 (define x 1) ↳ Defines a variable called x with value of 1 (define (f x y) (* x x)) ↳ Defines a function called f with two parameters called x and y that returns their product.
This is basically all there is to know about Racket syntax; the rest is learning the functions from the documentation, which is very thorough. There are other aspects of the syntax, like keyword arguments and quoting, but you do not need them for this example.
Mastering Racket might be difficult, and its syntax might look weird (especially if you are used to languages like Python), but I find it very fun to use. A big bonus is Racket's programming environment, DrRacket, which is very supportive, especially when you are getting started with the language.
The major Linux distributions offer packaged versions of Racket, so installation should be easy.
Guess the number game in Racket
Here is a version of the "guess the number" program written in Racket:
#lang racket (define (inquire-user number) (display "Insert a number: ") (define guess (string->number (read-line))) (cond [(> number guess) (displayln "Too low") (inquire-user number)] [(< number guess) (displayln "Too high") (inquire-user number)] [else (displayln "Correct!")])) (displayln "Guess a number between 1 and 100") (inquire-user (random 1 101))
Save this listing to a file called
guess.rkt and run it:
$ racket guess.rkt
Here is some example output:
Guess a number between 1 and 100 Insert a number: 90 Too high Insert a number: 50 Too high Insert a number: 20 Too high Insert a number: 10 Too low Insert a number: 12 Too low Insert a number: 13 Too low Insert a number: 14 Too low Insert a number: 15 Correct!
Understanding the program
I'll go through the program line by line. The first line declares the language the listing is written into:
#lang racket. This might seem strange, but Racket is very good at writing interpreters for new domain-specific languages. Do not panic, though! You can use Racket as it is because it is very rich in tools.
Now for the next line.
(define ...) is used to declare new variables or functions. Here, it defines a new function called
inquire-user that accepts the parameter
number parameter is the random number that the user will have to guess. The rest of the code inside the parentheses of the
define procedure is the body of the
inquire-user function. Notice that the function name contains a dash; this is Racket's idiomatic style for writing a long variable name.
This function recursively calls itself to repeat the question until the user guesses the right number. Note that I am not using loops; I feel that Racket programmers do not like loops and only use recursive functions. This approach is idiomatic to Racket, but if you prefer, loops are an option.
The first step of the
inquire-user function asks the user to insert a number by writing that string to the console. Then it defines a variable called
guess that contains whatever the user entered. The
read-line function returns the user input as a string. The string is then converted to a number with the
string->number function. After the variable definition, the
cond function accepts a series of conditions. If a condition is satisfied, it executes the code inside that condition. These conditions,
(> number guess) and
(< number guess), are followed by two functions: a
displayln that gives clues to the user and a
inquire-user call. The function calls itself again when the user does not guess the right number. The
else clause executes when the two conditions are not met, i.e., the user enters the correct number. The program's guts are this
However, the function still needs to be called! First, the program asks the user to guess a number between 1 and 100, and then it calls the
inquire-user function with a random number. The random number is generated with the
random function. You need to inform the function that you want to generate a number between 1 and 100, but the
random function generates integer numbers up to
max-1, so I used 101.
Learning new languages is fun! I am a big advocate of programming languages polyglotism because it brings new, interesting approaches and insights to programming. Racket is a great opportunity to start learning how to program with a Lisp-like language. I suggest you give it a try.