Racket Essentials: A Guide to Programming in Racket, Study notes of Latin

Racket Reference documents the fine points of the syntax of strings. The display procedure directly writes the characters of a string to the ...

Typology: Study notes

2021/2022

Uploaded on 08/05/2022

jacqueline_nel
jacqueline_nel 🇧🇪

4.4

(242)

3.2K documents

1 / 380

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
The Racket Guide
Version 6.9
Matthew Flatt,
Robert Bruce Findler,
and PLT
May 1, 2017
This guide is intended for programmers who are new to Racket or new to some part of
Racket. It assumes programming experience, so if you are new to programming, consider
instead reading How to Design Programs. If you want an especially quick introduction to
Racket, start with Quick: An Introduction to Racket with Pictures.
Chapter 2 provides a brief introduction to Racket. From Chapter 3 on, this guide dives into
details—covering much of the Racket toolbox, but leaving precise details to The Racket
Reference and other reference manuals. The source of this
manual is available
on GitHub.
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42
pf43
pf44
pf45
pf46
pf47
pf48
pf49
pf4a
pf4b
pf4c
pf4d
pf4e
pf4f
pf50
pf51
pf52
pf53
pf54
pf55
pf56
pf57
pf58
pf59
pf5a
pf5b
pf5c
pf5d
pf5e
pf5f
pf60
pf61
pf62
pf63
pf64

Partial preview of the text

Download Racket Essentials: A Guide to Programming in Racket and more Study notes Latin in PDF only on Docsity!

The Racket Guide

Version 6.

Matthew Flatt,

Robert Bruce Findler,

and PLT

May 1, 2017

This guide is intended for programmers who are new to Racket or new to some part of Racket. It assumes programming experience, so if you are new to programming, consider instead reading How to Design Programs. If you want an especially quick introduction to Racket, start with Quick: An Introduction to Racket with Pictures.

Chapter 2 provides a brief introduction to Racket. From Chapter 3 on, this guide dives into details—covering much of the Racket toolbox, but leaving precise details to The Racket Reference and other reference manuals. The source of this manual is available on GitHub.

Contents

1 Welcome to Racket

Depending on how you look at it, Racket is

  • a programming language—a dialect of Lisp and a descendant of Scheme; See §23 “Dialects of Racket and Scheme” for more information on other dialects of Lisp and how they relate to Racket.
  • a family of programming languages—variants of Racket, and more; or
  • a set of tools—for using a family of programming languages.

Where there is no room for confusion, we use simply Racket.

Racket’s main tools are

  • racket, the core compiler, interpreter, and run-time system;
  • DrRacket, the programming environment; and
  • raco, a command-line tool for executing Racket commands that install packages, build libraries, and more.

Most likely, you’ll want to explore the Racket language using DrRacket, especially at the beginning. If you prefer, you can also work with the command-line racket interpreter and your favorite text editor; see also §24 “Command-Line Tools and Your Editor of Choice”. The rest of this guide presents the language mostly independent of your choice of editor.

If you’re using DrRacket, you’ll need to choose the proper language, because DrRacket accommodates many different variants of Racket, as well as other languages. Assuming that you’ve never used DrRacket before, start it up, type the line

#lang racket

in DrRacket’s top text area, and then click the Run button that’s above the text area. Dr- Racket then understands that you mean to work in the normal variant of Racket (as opposed to the smaller racket/base or many other possibilities). §23.1 “More Rackets” describes some of the other possibilities.

If you’ve used DrRacket before with something other than a program that starts #lang, DrRacket will remember the last language that you used, instead of inferring the language from the #lang line. In that case, use the Language|Choose Language... menu item. In the dialog that appears, select the first item, which tells DrRacket to use the language that is declared in a source program via #lang. Put the #lang line above in the top text area, still.

1.1 Interacting with Racket

DrRacket’s bottom text area and the racket command-line program (when started with no options) both act as a kind of calculator. You type a Racket expression, hit the Return key, and the answer is printed. In the terminology of Racket, this kind of calculator is called a read-eval-print loop or REPL.

A number by itself is an expression, and the answer is just the number:

5 5

A string is also an expression that evaluates to itself. A string is written with double quotes at the start and end of the string:

"Hello, world!" "Hello, world!"

Racket uses parentheses to wrap larger expressions—almost any kind of expression, other than simple constants. For example, a function call is written: open parenthesis, function name, argument expression, and closing parenthesis. The following expression calls the built-in function substring with the arguments "the boy out of the country", 4 , and 7 :

(substring "the boy out of the country" 4 7) "boy"

1.2 Definitions and Interactions

You can define your own functions that work like substring by using the define form, like this:

(define (extract str) (substring str 4 7))

(extract "the boy out of the country") "boy" (extract "the country out of the boy") "cou"

Although you can evaluate the define form in the REPL, definitions are normally a part of a program that you want to keep and use later. So, in DrRacket, you’d normally put the definition in the top text area—called the definitions area—along with the #lang prefix:

  • With Unix or Mac OS, you can turn the program file into an executable script by inserting the line See §21.2 “Scripts” for more information on script files.

#! /usr/bin/env racket at the very beginning of the file. Also, change the file permissions to executable using chmod +x xfilenamey on the command line. The script works as long as racket is in the user’s executable search path. Alternately, use a full path to racket after #! (with a space between #! and the path), in which case the user’s executable search path does not matter.

1.4 A Note to Readers with Lisp/Scheme Experience

If you already know something about Scheme or Lisp, you might be tempted to put just

(define (extract str) (substring str 4 7))

into "extract.rktl" and run racket with

(load "extract.rktl") (extract "the dog out") "dog"

That will work, because racket is willing to imitate a traditional Lisp environment, but we strongly recommend against using load or writing programs outside of a module.

Writing definitions outside of a module leads to bad error messages, bad performance, and awkward scripting to combine and run programs. The problems are not specific to racket; they’re fundamental limitations of the traditional top-level environment, which Scheme and Lisp implementations have historically fought with ad hoc command-line flags, compiler directives, and build tools. The module system is designed to avoid these problems, so start with #lang, and you’ll be happier with Racket in the long run.

2 Racket Essentials

This chapter provides a quick introduction to Racket as background for the rest of the guide. Readers with some Racket experience can safely skip to §3 “Built-In Datatypes”.

2.1 Simple Values

Racket values include numbers, booleans, strings, and byte strings. In DrRacket and doc- umentation examples (when you read the documentation in color), value expressions are shown in green.

Numbers are written in the usual way, including fractions and imaginary numbers: §3.2 “Numbers” (later in this guide) explains more about numbers.

1/2 6.02e+ 1+2i 9999999999999999999999

Booleans are #t for true and #f for false. In conditionals, however, all non-#f values are treated as true. §3.1 “Booleans” (later in this guide) explains more about booleans.

Strings are written between doublequotes. Within a string, backslash is an escaping char- acter; for example, a backslash followed by a doublequote includes a literal doublequote in the string. Except for an unescaped doublequote or backslash, any Unicode character can appear in a string constant. §3.4 “Strings (Unicode)” (later in this guide) explains more about strings.

"Hello, world!" "Benjamin "Bugsy" Siegel" "λx:(μα.αÑα).xx"

When a constant is evaluated in the REPL, it typically prints the same as its input syntax. In some cases, the printed form is a normalized version of the input syntax. In documen- tation and in DrRacket’s REPL, results are printed in blue instead of green to highlight the difference between an input expression and a printed result.

Examples:

"Bugs \u0022Figaro\u0022 Bunny" "Bugs "Figaro" Bunny"

value, though the printed form is necessarily less complete than the printed form of a number or string.

Examples:

piece #<procedure:piece> substring #<procedure:substring>

A function definition can include multiple expressions for the function’s body. In that case, only the value of the last expression is returned when the function is called. The other expressions are evaluated only for some side-effect, such as printing.

Examples:

(define (bake flavor) (printf "pre-heating oven...\n") (string-append flavor " pie"))

(bake "apple") pre-heating oven... "apple pie"

Racket programmers prefer to avoid side-effects, so a definition usually has just one expres- sion in its body. It’s important, though, to understand that multiple expressions are allowed in a definition body, because it explains why the following nobake function fails to include its argument in its result:

(define (nobake flavor) string-append flavor "jello")

(nobake "green") "jello"

Within nobake, there are no parentheses around string-append flavor "jello", so they are three separate expressions instead of one function-call expression. The expressions string-append and flavor are evaluated, but the results are never used. Instead, the result of the function is just the result of the final expression, "jello".

2.2.2 An Aside on Indenting Code

Line breaks and indentation are not significant for parsing Racket programs, but most Racket programmers use a standard set of conventions to make code more readable. For example, the body of a definition is typically indented under the first line of the definition. Identifiers

are written immediately after an open parenthesis with no extra space, and closing parenthe- ses never go on their own line.

DrRacket automatically indents according to the standard style when you type En- ter in a program or REPL expression. For example, if you hit Enter after typing (define (greet name), then DrRacket automatically inserts two spaces for the next line. If you change a region of code, you can select it in DrRacket and hit Tab, and DrRacket will re-indent the code (without inserting any line breaks). Editors like Emacs offer a Racket or Scheme mode with similar indentation support.

Re-indenting not only makes the code easier to read, it gives you extra feedback that your parentheses match in the way that you intended. For example, if you leave out a closing parenthesis after the last argument to a function, automatic indentation starts the next line under the first argument, instead of under the define keyword:

(define (halfbake flavor (string-append flavor " creme brulee")))

In this case, indentation helps highlight the mistake. In other cases, where the indentation may be normal while an open parenthesis has no matching close parenthesis, both racket and DrRacket use the source’s indentation to suggest where a parenthesis might be missing.

2.2.3 Identifiers

Racket’s syntax for identifiers is especially liberal. Excluding the special characters §4.2 “Identifiers and Binding” (later in this guide) explains more about identifiers.

( ) [ ] { } " , ' ` ; # | \

and except for the sequences of characters that make number constants, almost any sequence of non-whitespace characters forms an xidy. For example substring is an identifier. Also, string-append and a+b are identifiers, as opposed to arithmetic expressions. Here are several more examples:

Hfuhruhurr integer? pass/fail john-jacob-jingleheimer-schmidt a-b-c+1-2-

2.2.4 Function Calls (Procedure Applications)

We have already seen many function calls, which are called procedure applications in more traditional terminology. The syntax of a function call is §4.3 “Function Calls” (later in this guide) explains more about function (^17) calls.

2.2.5 Conditionals with if, and, or, and cond

The next simplest kind of expression is an if conditional:

( if xexpry xexpry xexpry ) §4.7 “Conditionals” (later in this guide) explains more about conditionals.

The first xexpry is always evaluated. If it produces a non-#f value, then the second xexpry is evaluated for the result of the whole if expression, otherwise the third xexpry is evaluated for the result.

Example:

(if (> 2 3) "bigger" "smaller") "smaller"

(define (reply s) (if (equal? "hello" (substring s 0 5)) "hi!" "huh?"))

(reply "hello racket") "hi!" (reply "λx:(μα.αÑα).xx") "huh?"

Complex conditionals can be formed by nesting if expressions. For example, you could make the reply function work when given non-strings:

(define (reply s) (if (string? s) (if (equal? "hello" (substring s 0 5)) "hi!" "huh?") "huh?"))

Instead of duplicating the "huh?" case, this function is better written as

(define (reply s) (if (if (string? s) (equal? "hello" (substring s 0 5)) #f) "hi!" "huh?"))

but these kinds of nested ifs are difficult to read. Racket provides more readable shortcuts through the and and or forms, which work with any number of expressions: §4.7.2 “Combining Tests: and and or” (later in this guide) explains more about and and or.

( and xexpry* ) ( or xexpry* )

The and form short-circuits: it stops and returns #f when an expression produces #f, other- wise it keeps going. The or form similarly short-circuits when it encounters a true result.

Examples:

(define (reply s) (if (and (string? s) (>= (string-length s) 5) (equal? "hello" (substring s 0 5))) "hi!" "huh?"))

(reply "hello racket") "hi!" (reply 17) "huh?"

Another common pattern of nested ifs involves a sequence of tests, each with its own result:

(define (reply-more s) (if (equal? "hello" (substring s 0 5)) "hi!" (if (equal? "goodbye" (substring s 0 7)) "bye!" (if (equal? "?" (substring s (- (string-length s) 1))) "I don't know" "huh?"))))

The shorthand for a sequence of tests is the cond form: §4.7.3 “Chaining Tests: cond” (later in this guide) explains more about cond.

( cond {[ xexpry xexpry* ]}* )

A cond form contains a sequence of clauses between square brackets. In each clause, the first xexpry is a test expression. If it produces true, then the clause’s remaining xexprys are evaluated, and the last one in the clause provides the answer for the entire cond expression; the rest of the clauses are ignored. If the test xexpry produces #f, then the clause’s remaining xexprys are ignored, and evaluation continues with the next clause. The last clause can use else as a synonym for a #t test expression.

Using cond, the reply-more function can be more clearly written as follows: