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
, andcons
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
andcdr
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 thecar
andcdr
macros, at the Wikipedia page forcar
andcdr
.
Racket modernizes Scheme in many ways, including by adopting Common Lisp's names for these fundamental procedures:first
andrest
.
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 acons
cell. In this sense,cons
is an inverse ofcar
andcdr
. - 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 saylast-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. Becausedefine
expressions are evaluated for their side effects, Dr. Racket does not print or return a value for them. Later, we will seeset!
, which gives us the ability to change the value of an existing binding, andbegin
, which gives us the ability to sequence expressions. Finally, input/output procedures such asread
,write
, andprint
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.
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.