# Racket

## Overview

Racket is a functional programming language in the Scheme family of languages which descend from LISP. It features:

• Dynamic typing.
• First class functions and lambdas.
• Prefix notation.
• Lists, vectors and hashes built in.
• A powerful macro system.
• Lots of parenthesis!

## Running Code

• The Command Line

The racket command can be used as an interactive shell:

$racket > (+ 1 2) 3 > (displayln "Hello World") Hello World  The racket command can also be used to run a Racket program in a file: $ racket -f hello.rkt
Hello from a file


• The IDE

Racket also comes with an IDE called DrRacket. It can be launched with:


drracket


The IDE looks something like this:

If it asks for a language, just choose "Racket".

The top portion is a code window where function definitions can be placed. The bottom portion is an interactive shell for calling functions and evaluating expressions.

• On cs, racket is installed and can be run as above.

Racket can also be easily installed on your own computer.

## S-Expressions

Racket is a homoiconic language which means that everything in the language is represented the same way.

All code and data are represented with S-expressions. An S-expression is defined as:

1. An atom.
2. A number of S-expressions inside of parenthesis separated by spaces.

The use of S-expressions greatly simplify the grammar of Racket. Every language construct is represented the exact same way.

It also allows for meta-programming where a program can process program code in some way. Because code and data are stored the same way, this is easier than in most languages.

## Atoms

Atoms in Racket are the single entities that can comprise S-expressions. There are several atoms in Racket:

• Numbers

Racket has typical integer and floating point numbers. There are also ratios which provide an exact fractional type.


> (/ 3 4)
3/4

> (/ 6 8)
3/4

> (/ 3.0 4.0)
0.75

Racket also allows numbers of arbitrary precision.

• Booleans

The values #t and #f are atoms representing true and false respectively.

• Characters

Characters do not use single-quotes. The ' is used for something else. Instead they are preceded by the #\ characters:


> #\A
#\A
> (char->integer #\A)
65


• Strings

Strings are an atomic type, they aren't lists of characters. They are given between double-quoted strings:


> "Name"
"Name"


• Symbols

Symbols are data types that are not present in langauges like C and Java. They are names that can be referenced inside of a program, but don't have a value associated with them. A symbol is a name that begins with the single quote character:


> 'symbol
'symbol

Symbols are always equal to themselves, but nothing else. They are useful in the same way that enums are in other languages.

## Naming Conventions

Racket allows more flexibility in naming variables and symbols than most languages. Names can consist of:
• Any letter character.
• Any digit (they can start with a digit, but can't be all digits).
• The characters * + ! / - _ . < > and ?
There are some conventions that are typically used:
• Hyphens are typically used to separate words, rather than underscroes.
• ? is used to end functions that return true or false.
• ! is used to mark functions that have side-effects.

## Basic I/O

Printing to the screen is accomplished with the display function. Like all Racket code, a function call is written as an S-expression. We can write hello world as:


; hello world program
(display "Hello Word!")


Comments in Racket begin with a semi-colon.

There is also the displayln function which ends with a new line.

For input, there is the read function which reads from stdin. It returns the value as if it was entered into the interpreter.

We can write a program to read in a name and greet it as follows:


(display "Hello ")
(display name)


This also illustrates the "define" expression which binds a value to a name.

Racket also has a "printf function. Racket's printf takes "~a" to print a value, and "~n" to print a newline:


(printf "Hello ~a!~n" name)


## Arithmetic and Functions

Racket arithmetic is done using prefix function notation:


> (+ 1 2)
> (+ 1 2 3 4 5)
> (* 5 (+ 1 2))
> (/ (* 10 5) (+ 1 1))


Comparisons are done this way as well:


> (< 3 5)
#t
> (= 5 4)
#f
> (and (<= 3 5) (= 6 6))
#t

There are a number of arithmetic and logical functions:
• or
• not
• even?
• odd?
• sqrt
• modulo
• log
• random
• bitwise-and
• bitwise-or
• bitwise-xor
• bitwise-not

## Variables

Racket supports named values in a few different ways. The define function binds a name to a value:


(define x 10)


The name can then be used in following code:


(begin
(define x 10)
(displayln x))


## If Expressions

If expressions are given as S-expressions. The first atom is the symbol "if". Next is a test expression, the then expression and lastly the else expression.

Some examples:


> (if (even? 4) 1 2)
> (if (< 3 4) (displayln "Yes") (displayln "No"))


There is also a "when" expression which is like the if, but without the else portion:


> (when (< 3 4) (displayln "Yes"))


If the condition is not true, the expression evaluates to nothing. This is what the displayln function returns anyway.

There is also the "cond" expression which can be used like a switch:


(cond ((< x 0) (displayln "Negative"))
((> x 0) (displayln "Positive"))
((= x 0) (displayln "Zero")))


The cond form has multiple pairs of tests and results. If the test is "else" it is used as a default case.

Note that these are all expressions and not statements which allow them to be nested in other expressions:


(define x (if (< y 0) 1 0))
(displayln (if (< x 0) "Negative" "Positive"))


## Defining Functions

As a functional language, Racket programs typically consist of function definitions. A function, like a variable, is defined with the "define" expression:


(define (name arg1 arg2 ... ) expression)


For example, we can write an add function as:


(define (add a b) (+ a b))


Code does not have to be on one line (Racket does not count whitespace). The add function could also be written as:


(+ a b))


How could we write an absolute value function?


(define (abs x)
(if (< x 0)
(- x)
x))


How could we write a recursive factorial function?


(define (fact x)
(if (= x 0)
1
(* x (fact (- x 1)))))


## String and Character Functions

 Function Meaning (string? s) Returns whether or not s is a string. (make-string num char) Creates a string with num charcters set to char. (string char1 char2 char3 ...) Creates a string composed of the characters that are passed in. (string-length s) Returns the length of the string s. (string-ref s i) Returns the character at s[i]. (substring s start end) Returns the substring of s from start to end. (string-append s1 s2 s3 ...) Append all of the arguments together in one string. (string=? s1 s2 s3 ...) Test if all arguments are equal. (string, >= exist as well). (string-upcase s) Return an upper-case version of s. (string-downcase s) Return an lower-case version of s.

## Begin Operations

The S-expressions associated with a function, or if expression must all be single S-expressions. How then can we have multiple lines of code executed in a function?

The answer is the "begin" expression which is given as:


(begin expr1 expr2 expr3)


begin evaluates all of the expressions it is given, one by one. The value of the begin expression is the value of the last expression in the list.

Examples:


(begin (display "Hello") (display " there ") (displayln "person"))


begin can be used to insert calls to other functions, such as display, into other expressions. begin is used in the following program to solve the collatz conjecture:


; solves the collatz conjecture

; return one step in the sequence
(define (collatz-step n)
(if (even? n)
(/ n 2)
(+ 1 (* 3 n))))

; recurse over all numbers
(define (collatz n)
(if (= n 1)
(displayln "All done!")
(begin
(display "N = ")
(displayln n)
(collatz (collatz-step n)))))

; get input and run it
(displayln "Enter a positive number:")


How can we write a guess the number game?


(define (get-guess)

(define (round correct)
(define g (get-guess))
(cond ((= g correct) (printf "Correct!~n"))
((> g correct) (begin (printf "Too High!~n")
(round correct)))
((< g correct) (begin (printf "Too Low!~n")
(round correct)))))

(round (+ (random 100) 1))


## Lists

Lists are the most common data structure in Racket. They are defined as S-expressions:


> (1 2 3)


However, Racket tries to evaluate all S-expressions leading to an error:


application: not a procedure;
expected a procedure that can be applied to arguments
given: 1


To tell Racket to not evaluate the list, we use the quote function.


> (quote (1 2 3))
(1 2 3)


There is a shortcut for this:


> '(1 2 3)
(1 2 3)


Some common list functions:

• (empty? list) ; returns whether the list is empty
• (length list) ; returns the number of elements
• (first list) ; returns the first item in a list
• (rest list) ; returns all but the first item
• (cons item list) ; adds item to the front of list
• (append list1 list2 ...) ; joins lists together
• (reverse list) ; reverses
• (sort list comp) ; sorts
• (build-list n f) ; creates a list of (0 .. N-1) with f applied to them
• (member value list) ; resturns the sublist starting at value, or #f if value is not in list

How could we implement the length function using empty? and rest.


(define (length ls)
(if (empty? ls)
0
(+ 1 (length (rest ls)))))


How could we write a function to sum all of the elements in a list?


(define (sum ls)
(if (empty? ls)
0
(+ (first ls) (sum (rest ls)))))


## Lambda Functions

A lambda function is one that is created without a name, on the fly. This is done with the "lambda" keyword:


(lambda (arg1 arg2 ...) expression)


We can create a function an call it in one S-expression:


((lambda (x) (* x x)) 5)


This is useful when we want to pass a function to another as we will see below.

Racket also allows the "λ" character itself to be used in code:


((λ (x) (* x x)) 5)


It can be entered in Dr Racket with Control-\

## Higher Order Functions

Functional languages make extensive use of higher-order functions. These are functions that take a function as a parameter or return a function as a result.

A simple higher-order function in Racket is for-each. This function takes two parameters, a function, and a list. It then applies the function to each element of the list. For example, to print a list of strings:


(for-each display '("A" "B" "C" "D" "E\n"))


for-each could be implemented as:


(define (for-each f ls)
(when (not (empty? ls))
(begin (f (first ls))
(for-each f (rest ls)))))


Higher order functions are more commonly used than loops in functional programming.

## Folding

A more complex, though common, operation is to do something with a list keeping track of some accumulation. This is done in the the function we wrote to sum a list, and would be used in finding the product or max of a list. We can extract this out into a function traditionally called fold:


(define (fold f accum ls)
(if (empty? ls)
accum
(fold f (f (first ls) accum) (rest ls))))


This function takes three parameters: a function to apply across the list, the accumulated value, and the list to apply to. It works by checking if the list is empty, if so it returns the accumulated value. Otherwise, it recurses by calling itself with the same function, applying the function to the first item, and passing the rest of the list.

We can use this to sum a list of integers as follows:


(fold + 0 '(1 2 3 4 5 6 7 8 9 10))


Here we fold "+" across the list with an initial value of 0.

We can also use it to find factorials:


(fold * 1 '(1 2 3 4 5 6))


Lambda functions go well with higher order functions. For example, to find the max of a list of numbers we can write:


(fold (lambda (a b) (if (> a b) a b)) 0 '(13 5 25 17 8))


The "fold" function is actually included in Racket as "foldl" and "foldr" which work the same, but in different directions. This example demonstrates the difference:


(foldr string-append "" '("A" "B" "C"))
(foldl string-append "" '("A" "B" "C"))


Imagine we have a list of boolean values. How could we use fold and lambda to determine if all of them are true?


(foldl (λ (a b) (and a b)) #t values)


If any of them are true?

(foldl (λ (a b) (or a b)) #f values)


## Mapping

Another powerful higher-order function is "map". map takes a function and a list, and applies that function to each element returning a new list:


(map (lambda (x) (* x x)) '(1 2 3 4 5 6 7 8 9 10))

How can we use map to compute the lengths of a list of strings all at once?

(map string-length '("Alice" "Bob" "Claire"))


How can we implement the map function?


(define (map f ls)
(if (empty? ls)
'()
(cons (f (first ls)) (map f (rest ls)))))


## Filtering

Another powerful function is filter. This is used for selecting only a subset of a list based on some criteria. For example to get all even numbers from a list:


(filter even? '(1 2 3 4 5 6 7 8 9 10))


How could we use filter to get only strings of length at least 3 from a list?





Filter can also be used to implement the quick sort algorithm:


(define (qsort ls)
(if (empty? ls)
'()
(append (qsort (filter (lambda (x) (< x (first ls))) (rest ls)))
(list (first ls))
(qsort (filter (lambda (x) (>= x (first ls))) (rest ls))))))


How can we implement the filter function?


(define (filter pred ls)
(if (empty? ls)
'()
(if (pred (first ls))
(cons (first ls) (filter pred (rest ls)))
(filter pred (rest ls)))))


## More on Quoting

Recall that if we want a list of data, we need to quote it:


'(1 2 3 4 5)


When we quote a list, the entire thing is treated as data. Sometimes this is not what we want. For example, if we tried to get a list where each item was calculated:


(define x 10)

'((* x 1) (* x 2) (* x 3) (* x 4) (* x 5))

Then the entire list is treated as data. To have the individual items evaluated, we need to unquote them with the , symbol:

(,(* x 1) ,(* x 2) ,(* x 3) ,(* x 4) ,(* x 5))


For this to work, we also must use  as a quote symbol instead of '. This one allows unquoting whereas ' does not.

This gives us the list (10 20 30 40 50) as expected.

Another thing that we can do with quoted lists is use them to store code that can be evaluated later. For example, if we have the code:


(define p '(displayln "Hello!"))

Then we essentially are storing a line of code inside of a variable. If we want to evaluate that code at some later point in time, we can do so with the eval function:

(eval p)


This allows a lot of flexibility as code can be stored indefinitely, passed to a function etc.

## Macros

A macro is like a function, except that the parameters are not evaluated before the call. This allows us to define new language constructs.

Consdier the "assert" function in many languages. In C and C++, it works as follows:


#include <iostream>

int main() {
int x;
cin >> x;
assert(x > 0);

// do something with x
return 0;
}

When run, the assert will test if x is greater than 0. If so, nothing happens, if not, an error is produced:

a.out: x.cpp:10: int main(): Assertion x > 0' failed.


Notice that the text of the assertion x > 0' appears in the message. Below is an attempt to write a assert function in Racket:


(define (assert c)
(when (not c)
(display "Assertion ")
(display c)
(displayln "' failed.")
(raise 'AssertionError)))


However, when we run this the message is not as helpful:


> (assert (< 4 3))
Assertion #f' failed.
uncaught exception: 'AssertionError
>


It's not possible to write a function that displays the text that is passed to it. For that we need a macro. In Racket, these are introduced with the define-syntax-rule form:


(define-syntax-rule (assert c)
(when (not c)
(display "Assertion ")
(display #'c)
(displayln "' failed.")
(raise 'AssertionError)))


Now the parameter "c" is passed in as code, not as a computed value. In the (not c) expression, c is evaluated, however, by using #'c, we get the textual value for display.

Now our error message is much better:


Assertion .#<syntax:11:8 (< 4 3)>' failed.
uncaught exception: 'AssertionError


As another example, we can give Racket a while loop with the following macro:


(define-syntax-rule (while condition body)
(begin
(define (loop)
(when condition
(begin
body
(loop))))
(loop)))


This macro takes two arguments: the condition and the body. Because it is a macro, both are passed in as code that gets evaluated by the macro itself. This allows the body to be re-evaluated each iteration which is essential.

It can be used as follows:


(define x 0)
(while (<= x 10)
(begin
(displayln x)
(set! x (+ x 1))))


Macros allow for the language to be extended. Many Racket "functions" that we have used are actually written as macros.