Racket FAQ Listing

Introductory Note

Why do you talk about Racket and Scheme?
Racket is a fork of Scheme, the simple language at the core of this course for many years. Scheme was created primarily as an experiment in understanding how programming languages work. Racket retains its basic favor, but it also adds many, many features that make the language useful in the 21st century. It also changes a few details that make it more useful to modern programmers.

We use Racket in this course because it is more modern, has better tools, and has a thriving community doing cool work. But there are so many valuable references from the Scheme world that it's hard to talk about Racket in this course without referring to Scheme.

Questions about Specific Details of Racket

Where did the names of the procedures car, cdr, and cons come from?
These names date to the first implementation of Lisp, on an IBM 704. A word on the 704 consisted of two parts, the address register and the decrement register. car and cdr were macros for accessing the contents of the address register and the contents of the decrement register, respectively.

Scheme modernized many things about Lisp, but kept these names for reasons both of culture and convenience. You can read more about them, including the convenience reasons and even the IBM 704 macro code for the car and cdr macros, at the Wikipedia page for car and cdr.

Racket modernizes Scheme in many ways, including by adopting Common Lisp's names for these fundamental procedures: first and rest.

cons is the sort of abbreviation many programmers love. It is the procedure for constructing lists. More specifically, cons allocates a single two-address cell, which we usually just call a cons cell. In this sense, cons is an inverse of car and cdr.

Are Racket identifiers case-sensitive?
Yes. However, we rarely use embedded capitals when naming things things in Racket. Instead, we use punctuation characters, especially the hyphen. Instead of LastElement, we would say last-element.

Does Racket provide operators for programming with side effects?
Yes. However, side effects are not part of the functional style of programming, so we do not reach them until much later in the course. We have seen and used one operator with side effects at the top level: define, which binds a name to a value. Because define expressions are evaluated for their side effects, Dr. Racket does not print or return a value for them. Later, we will see set!, which gives us the ability to change the value of an existing binding, and begin, which gives us the ability to sequence expressions. Finally, input/output procedures such as read, write, and print have side effects, too.

The list is Racket's basic aggregate data type. Can we make multidimensional lists?
Yes. A list can be a list of any values, including other lists. We will take advantage of this flexibility often, with lists containing other lists of arbitrary length.

Is there a list of all of Racket's primitive procedures?
I do not know of a simple list of all the procedures defined in Racket's base language. However, the index to the Racket language reference includes all the procedure and symbol names in the language. Racket is a large language, so this list is quite long. For this course, we can often use Chapter 6 of Revised Report on the Algorithmic Language Scheme, as a quick reference. All, or nearly all, of those functions exist in racket, too.

How can I tell if a procedure is primitive or not?
This can be tough when reading lecture notes, because sometimes I use a function we defined in class previously. Other times, we write our own functions to define the behavior of a built-in Racket function.

To determine if a procedure is a Racket primitive, you can search for it in The Racket Guide, using the search box at the top of every page.

You have another way to determine if a procedure is built into Racket: evaluate the name of the procedure in Dr. Racket! If you have not defined a procedure with that name, and the name evaluates to a compiled #<procedure:...>, then the procedure must be a Racket primitive.
> first
#<procedure:first>
If it causes an error because the name is not bound to a value, then it's not.
> foo
... foo: undefined;
  cannot reference an identifier before its definition

Questions about Racket as a Programming Language

Are Racket procedures defined in libraries, as in Java?
Not the primitives; they come as a standard part of the language interpreter, just like Java primitives do. Other functions are defined in modules and imported. An example that we wee early in the course is rackunit, for unit testing.

Programmers also create their own libraries of procedures and load them into the Racket environment. This is exactly what we do when we write Racket programs.

Programming language researchers have long been working on module systems that allow programmers to share libraries of procedures more easily. Racket provides a well-developed, full-featured module system.

What is the lambda calculus?
From an on-line introduction to the lambda calculus at Monash University:
The lambda calculus is a formal mathematical system devised by Alonzo Church to investigate functions, function application, and recursion. It has influenced many programming languages but none more so than the functional programming languages. Lisp was the first of these although only the "pure" Lisp sublanguage can be called a true functional language. Haskell, Miranda, and ML are more recent examples. Lambda calculus also provides the meta-language for formal definitions in denotational semantics. It has a good claim to be the prototype programming language.

The lambda calculus is in many ways the prototype for all programming languages. Like the Turing machine, it is capable of implementing any computable function. Unlike the Turing machine, it focuses on the transformation rules that implement a function, rather than the underlying machine implementation. Hence it lies closer to the level of software than the Turing machine.

You can read a lot more about the lambda calculus at the Monash University site. You shouldn't be surprised later in the course when we use and interpret a subset of Scheme that is remarkably similar to Church's calculus.

What was the original purpose of Scheme?
Steele and Sussman "discovered" Scheme in an effort to design a minimal programminmg language. From Steele's foreword to Scheme and the Art of Programming:
The original Scheme ... was a Swiss army knife. Hewing close to the spirit of Alonzo Church's lambda calculus, it had just one of anything if it had one at all.

Because Scheme is minimal whereas many of the languages you know well are decidely not (Python, Java, C++), it gives us a way to talk about the trade-offs between small and large languages. Because Scheme is minimal, it leaves us a lot of freedom to talk about most every language feature, what they are useful for, how to implement them, and what trade-offs they impose on us. Because Scheme is minimal, it is small enough for us to master it well enough to implement language interpreters in it.

Questions about Racket in the World

Why use Racket to study programming languages?
If Scheme has one niche to fill in the universe, it is as a tool for studying languages. Scheme defines only a minimal number of features, providing the atoms out of which we can build and understand the molecules that are programming language features. Racket extends Scheme but retains the features that make it a perfect vehicle for studying programming languages.

One of the reasons that Racket works so well for studying languages is that symbols and lists are two of its primary data types. In any language, once you move past the surface syntax, a program can be thought of as a tree of symbols and values. Trees are easily represented as lists of lists in Racket, and symbols are first-order values.

Finally, as we will learn soon, programs are recursively defined data structures, and using a functional programming style exposes this in the interpreters we write. Even more, functional programming takes advantage of the recursive nature of programs to produce small, simple, and relatively easy to understand interpreters.

What can Racket do as a programming language?
Anything that any other "general-purpose" language can do.

This is true in a theoretical sense, because Racket — and even Scheme — is "universal": any computable function can be computed in it.

But Racket is universal in a practical sense, too. People use Racket to write business data processing software, network control software, AI programs, and even computer games.

The Racket team eats its own dog food: Racket and all of its tools, including Dr. Racket, are written in Racket, even the web server that supports https://racket-lang.org/.

Of course, like any language, it is better suited for some tasks than for others. Of course, the beauty of Racket is that you can extend it to include any feature that you want, or you can rather easily write an interpreter for a more suitable task-specific language. That is The Racket Way.

Is Scheme used for any "real world" programming?
Yes, there are deployed, operational, "real" Scheme programs working out in the world.
  • Several virtual rides at Disney World are controlled by programs written in Chez Scheme, which is the compiler that powers Racket.
  • Boeing and the U.S. Air Force use Racket programs to control large, expensive telescope arrays.
But. If your question is meant to imply that use in "real" applications is necessary before you consider the language worthy of the effort to learn, then my tongue-in-cheek answer becomes, "I don't care". Not every language or skill you learn is directly applicable to your job tomorrow. Our goal at the university is for you to learn ideas that last for a while. No one can predict with any certainty what language — or even kind of language — you will be using in two, five, or ten, years. But I can tell you what principles will underlie their design, implementation, and use.

Learning Racket will help you to learn those principles. It will also help you to learn functional languages, and languages with functional features, more easily later. Practice learning a new language is worth the effort if only because it makes learning the next one easier! (Of course, if none of the tools and languages that you learn as an undergraduate are used in the "real world", then you may have cause to complain...)

Then again, if you believe Paul Graham, you should be using Racket or some other Lisp precisely because it is the most powerful language around.

Why have I never heard of Racket or Scheme before? Will it last?
You have lived a short life. Appreciate the opportunity to see the beauty of Racket before heading off into a world filled with Curly Brace People.

Racket forked Scheme. Scheme forked Lisp. Lisp dates to 1958. The first compiler was written in 1962. Scheme dates to the fall of 1975. The code and tool base of Racket date to the mid-1990s. Lisp evolves and survives.