Racket has been under active development as a vehicle for programming language research since the mid-1990s, and has accumulated many features over the years. This article describes and demonstrates some of these features. Note that one of Racket's main design goals is to accommodate creating new programming languages, both domain-specific languages and completely new languages. Therefore, some of the following examples are in different languages, but they are all implemented in Racket. Please refer to the main article for more information. The core Racket implementation is highly flexible. Even without using dialects, it can function as a full-featured scripting language, capable of running both with and without windows-native graphical user interface (GUI), and capable of tasks from web server creation to graphics.
Runtime support
Garbage collection, tail calls, space safety Racket can use three different garbage collectors:
Originally, the conservative Boehm garbage collector was used. However, conservative collection is impractical for long-running processes such as a web server—such processes tend to slowly leak memory. Also, there are pathological cases where a conservative collector leaks memory fast enough to make certain programs impossible to run. For example, when traversing an infinite list, a single conservative mistake of retaining a pointer leads to keeping the complete list in memory, quickly overflowing available memory. This collector is often referred to as "CGC" in the Racket community. SenoraGC is an alternative conservative garbage collector that is intended mainly for debugging and memory tracing. The moving memory manager (aka "3m") is a precise garbage collector, and it has been Racket's default collector since 2007. This collector is a generational one, and it supports memory accounting via custodians (see below). The collector is implemented as a C source transformer that is itself written in Racket. Therefore, the build process uses the conservative collector for bootstrapping. Like all implementations in the Scheme family, Racket implements full tail call elimination. Racket takes this further: the language is made fully safe-for-space, via live variable analysis. This complements the precise garbage collector and in some cases, like in the implementation of Lazy Racket, the two features are crucial for proper execution. This is in addition to further compiler optimizations such as lambda lifting and just-in-time compilation.
System interface and scripting Racket's system interface includes asynchronous non-blocking I/O, green threads, synchronization channels, semaphores, sub-processes, and Transmission Control Protocol (TCP) sockets. The following program starts an "echo server" on port 12345.
The combination of dynamic compilation and a rich system interface makes Racket a capable scripting language, similar to Perl or Python. The following example demonstrates walking a directory tree, starting at the current directory. It uses the in-directory function to construct a sequence that walks the tree. The for form binds path to each path in the sequence, and regexp-match? tests these paths against the given regexp pattern.
The next example uses a hash table to record previously seen lines and print only unique ones.
Both of these programs can be run in DrRacket, or on the command line, via the racket executable. Racket ignores an initial shebang line, making it possible to turn such programs to executable scripts. The following script demonstrates this, in addition to using Racket's library for command-line argument parsing:
The script is a grep-like utility, expecting three command-line arguments: a base directory, a filename extension, and a (perl-compatible) regular expression. It scans the base directory for files with the given suffix, and prints lines matching the regexp pattern.
Resource management and sandboxing Racket features the concept of a "custodian": a kind of value that acts as a resource manager. This is often used in network servers, where each connection is dealt with in a new custodian, making it easy to "clean-up" all resources that might have been left open by the handler (e.g., open ports). The following extends the "echo server" example with such a custodian use:
Custodians, combined with the memory accounting feature of the 3m garbage collector, and several added runtime parameters that control more aspects of the runtime, make it possible to create fully safe sandboxed execution contexts. The racket/sandbox library provides this kind of functionality in a simple way. The following example creates a read–eval–print loop (REPL) server on the specified port; connecting to this port will look like a plain Racket REPL, except that the evaluation is subject to the various protection aspects of the sandbox. For example, it is not possible to access the file system from this REPL, create network connection, run subprocesses, or use too much time or memory. (In fact, this REPL is safe enough to be given out publicly.)
Web and network programming The next example implements a web server using the web-server/insta language. Each time a connection is made to the server, the start function is called to get the HTML to send back to the client.
Racket also includes the functions needed to write scrapers and robots. As an example, the following function lists the Google results for a search string.
The library also includes support for protocols other than http:
Graphics Graphic capabilities come in several different flavors that are intended for different audiences. The 2htdp/image library provides convenient functions for constructing images. This library is mainly used by students in How to Design Programs (HtDP) based courses. In the following example, a sierpinski function is defined and called (at the same time) to generate a Sierpinski triangle of depth 8.
… excerpt ends here. Continue reading the full article.
