Simple Values

Numbers

``````1
3.14
1/2
6.02e+23
1+2i
9999999999999999999999
``````

Boolean

• #t for true
• #f for false

In conditionals, however, all non-#f values are treated as true.

Strings

``````"Hello, world!"
"Benjamin \"Bugsy\" Siegel"
"λx:(μα.α→α).xx"
``````
``````> 1.0000
1.0
> "Bugs \u0022Figaro\u0022 Bunny"
"Bugs \"Figaro\" Bunny"
``````

Simple Definitions and Expressions

A program module is written as

``````#lang ‹langname› ‹topform›*
``````

Definitions

``````( define ‹id› ‹expr› )
( define ( ‹id› ‹id›* ) ‹expr›+ )
``````
``````(define pie 3)             ; defines pie to be 3

(define (piece str)        ; defines piece as a function
(substring str 0 pie))   ;  of one argument

> pie
3
> (piece "key lime")
"key"
``````

Definitions

Multi-expression but with side effect:

``````(define (bake flavor)
(printf "preheating oven...\n")
(string-append flavor " pie"))

> (bake "apple")
preheating oven...
"apple pie"
``````

Single expression without side effect

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

> (nobake "green")
"jello"
``````

Identifiers

Excluding the special characters:

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

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

Function Calls

Procedure applications in more traditional terminology

``````> (string-append "rope" "twine" "yarn")  ; append strings
"ropetwineyarn"
> (substring "corduroys" 0 4)            ; extract a substring
"cord"
> (string-length "shoelace")             ; get a string's length
8
> (string? "Ceci n'est pas une string.") ; recognize strings
#t
> (string? 1)
#f
> (sqrt 16)                              ; find a square root
4
> (sqrt -16)
0+4i
> (+ 1 2)                                ; add numbers
3
> (- 2 1)                                ; subtract numbers
1
> (< 2 1)                                ; compare numbers
#f
> (>= 2 1)
#t
> (number? "c'est une number")           ; recognize numbers
#f
> (number? 1)
#t
> (equal? 6 "half dozen")                ; compare anything
#f
> (equal? 6 6)
#t
> (equal? "half dozen" "half dozen")
#t
``````

Function Calls

``````( ‹expr› ‹expr›* )
``````
``````(define (double v)
((if (string? v) string-append +) v v))

> (double "mnah")
"mnahmnah"
> (double 5)
10
``````

Conditionals: if

``````( if ‹expr› ‹expr› ‹expr› )
``````
``````> (if (> 2 3)
"bigger"
"smaller")

"smaller"

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

"hi!"
"huh?"
``````

Conditionals: if

Nesting if expressions

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

Conditionals: and/or

``````( and ‹expr›* )
( or ‹expr›* )
``````
``````(define (reply s)
(if (and (string? s)
(>= (string-length s) 5)
(equal? "hello" (substring s 0 5)))
"hi!"
"huh?"))

"hi!"
"huh?"
``````

Conditionals: cond

``````( cond {[ ‹expr› ‹expr›* ]}* )
``````
``````(define (reply-more s)
(cond
[(equal? "hello" (substring s 0 5))
"hi!"]
[(equal? "goodbye" (substring s 0 7))
"bye!"]
[(equal? "?" (substring s (- (string-length s) 1)))
"I don't know"]
[else "huh?"]))

"hi!"
"bye!"
"I don't know"
> (reply-more "mine is lime green")
"huh?"
``````

Anonymous Functions with lambda

``````( lambda ( ‹id›* ) ‹expr›+ )
``````
``````> (lambda (s) (string-append s "!"))
#<procedure>
> (twice (lambda (s) (string-append s "!"))
"hello")
"hello!!"
> (twice (lambda (s) (string-append s "?!"))
"hello")
"hello?!?!"
``````

Anonymous Functions with lambda

Function that generates function

``````> (lambda (s) (string-append s "!"))
#<procedure>
> (twice (lambda (s) (string-append s "!"))
"hello")
"hello!!"
> (twice (lambda (s) (string-append s "?!"))
"hello")
"hello?!?!"
``````
``````> (define louder (make-add-suffix "!"))
> (twice less-sure "really")
"really??"
> (twice louder "really")
"really!!"
``````

Anonymous Functions with lambda

‹expr› could be a lambda form

``````(define (louder s)
(string-append s "!"))

(define louder
(lambda (s)
(string-append s "!")))

> louder
#<procedure:louder>
``````

Local Binding: define

``````( define ( ‹id› ‹id›* ) ‹definition›* ‹expr›+ )
( lambda ( ‹id›* ) ‹definition›* ‹expr›+ )
``````
``````(define (converse s)
(define (starts? s2) ; local to converse
(define len2 (string-length s2))  ; local to starts?
(and (>= (string-length s) len2)
(equal? s2 (substring s 0 len2))))
(cond
[(starts? "hello") "hi!"]
[(starts? "goodbye") "bye!"]
[else "huh?"]))

> (converse "hello!")
"hi!"
> (converse "urp")
"huh?"
> starts? ; outside of converse, so...
starts?: undefined;
cannot reference an identifier before its definition
in module: top-level
``````

Local Binding: let/let*

``````( let ( {[ ‹id› ‹expr› ]}* ) ‹expr›+ )
``````
``````> (let ([x (random 4)]
[o (random 4)])
(cond
[(> x o) "X wins"]
[(> o x) "O wins"]
[else "cat's game"]))

"O wins"

> (let* ([x (random 4)]
[o (random 4)]
[diff (number->string (abs (- x o)))])
(cond
[(> x o) (string-append "X wins by " diff)]
[(> o x) (string-append "O wins by " diff)]
[else "cat's game"]))

"X wins by 2"
``````

Lists, Iteration, and Recursion

``````> (list "red" "green" "blue")
'("red" "green" "blue")
> (list 1 2 3 4 5)
'(1 2 3 4 5)
``````
``````> (length (list "hop" "skip" "jump"))        ; count the elements
3
> (list-ref (list "hop" "skip" "jump") 0)    ; extract by position
"hop"
> (list-ref (list "hop" "skip" "jump") 1)
"skip"
> (append (list "hop" "skip") (list "jump")) ; combine lists
'("hop" "skip" "jump")
> (reverse (list "hop" "skip" "jump"))       ; reverse order
'("jump" "skip" "hop")
> (member "fall" (list "hop" "skip" "jump")) ; check for an element
#f
``````

Predefined List Loops: map

``````> (map sqrt (list 1 4 9 16))
'(1 2 3 4)
> (map (lambda (i)
(string-append i "!"))
(list "peanuts" "popcorn" "crackerjack"))
'("peanuts!" "popcorn!" "crackerjack!")

> (map (lambda (s n) (substring s 0 n))
(list "peanuts" "popcorn" "crackerjack")
(list 6 3 7))
'("peanut" "pop" "cracker")
``````

Predefined List Loops: andmap/ormap

``````> (andmap string? (list "a" "b" "c"))
#t
> (andmap string? (list "a" "b" 6))
#f
> (ormap number? (list "a" "b" 6))
#t
``````

Predefined List Loops: filter

``````> (filter string? (list "a" "b" 6))
'("a" "b")
> (filter positive? (list 1 -2 6 7 0))
'(1 6 7)
``````

Predefined List Loops: filter

``````> (foldl (lambda (elem v)
(+ v (* elem elem)))
0
'(1 2 3))
14
``````

List Iteration from Scratch

first/rest/cons/empty/empty?

``````> (first (list 1 2 3))
1
> (rest (list 1 2 3))
'(2 3)

> empty
'()

> (empty? empty)
#t
#f
> (cons? empty)
#f
#t
``````

List Iteration from Scratch

create your own length and map

``````(define (my-length lst)
(cond
[(empty? lst) 0]
[else (+ 1 (my-length (rest lst)))]))

> (my-length empty)
0
> (my-length (list "a" "b" "c"))
3

(define (my-map f lst)
(cond
[(empty? lst) empty]
[else (cons (f (first lst))
(my-map f (rest lst)))]))

> (my-map string-upcase (list "ready" "set" "go"))
``````

Tail Recursion

Problem: my-length takes O(n) space

Solution: define local function to store len

``````(define (my-length lst)
; local function iter:
(define (iter lst len)
(cond
[(empty? lst) len]
[else (iter (rest lst) (+ len 1))]))
; body of my-length calls iter:
(iter lst 0))
``````

Recursion versus Iteration

Tail call optimization

Pairs, Lists, and Racket Syntax

Result of `cons` is actually a pair.

``````> (cons 1 2)
'(1 . 2)
> (cons "banana" "split")
'("banana" . "split")
``````

Pairs, Lists, and Racket Syntax

• `cons?` is same as `pair?`
• `first` is same as `car`
• `rest` is same as `cdr`
``````> (car (cons 1 2))
1
> (cdr (cons 1 2))
2
> (pair? empty)
#f
> (pair? (cons 1 2))
#t
> (pair? (list 1 2 3))
#t
``````

Pairs, Lists, and Racket Syntax

Some cases that (might) confuse you:

``````> (cons (list 2 3) 1)
'((2 3) . 1)

> (cons 1 (list 2 3))
'(1 2 3)
``````

Non-list pairs are used intentionally, sometimes.

Pairs, Lists, and Racket Syntax

``````> (cons 0 (cons 1 2))
'(0 1 . 2)
``````

Use the dot notation unless the dot is immediately followed by an open parenthesis.

• ‘(0 . (1 . 2)) becomes ‘(0 1 . 2)
• ‘(1 . (2 . (3 . ()))) becomes ‘(1 2 3).

Quoting Pairs

• If an element of a list is itself a list, no quote mark is printed for the inner list.
• `quote` form can express the same way that the list prints.
``````> (list (list 1) (list 2 3) (list 4))
'((1) (2 3) (4))
> (quote ("red" "green" "blue"))
'("red" "green" "blue")
> (quote ((1) (2 3) (4)))
'((1) (2 3) (4))
> (quote ())
'()
``````

Quoting Pairs

`quote` form works with the dot notation, too.

``````> (quote (1 . 2))
'(1 . 2)
> (quote (0 . (1 . 2)))
'(0 1 . 2)
``````

Lists of any kind can be nested.

``````> (list (list 1 2 3) 5 (list "a" "b" "c"))
'((1 2 3) 5 ("a" "b" "c"))
> (quote ((1 2 3) 5 ("a" "b" "c")))
'((1 2 3) 5 ("a" "b" "c"))
``````

Symbols with quote

A value prints like a quoted identifier is a symbol.

``````> (quote jane-doe)
'jane-doe

> map
#<procedure:map>
> (quote map)
'map
> (symbol? (quote map))
#t
> (symbol? map)
#f
> (procedure? map)
#t
> (string->symbol "map")
'map
> (symbol->string (quote map))
"map"
``````

Symbols with quote

quote for a list automatically applies itself to nested lists.

``````> (car (quote (road map)))
> (symbol? (car (quote (road map))))
#t
``````

Symbols with quote

quote form has no effect on a literal expression

``````> (quote 42)
42
> (quote "on the record")
"on the record"
``````

Abbreviating quote with '

``````> '(1 2 3)
'(1 2 3)
> '((1 2 3) road ("a" "b" "c"))
'((1 2 3) road ("a" "b" "c"))
``````

Abbreviating quote with '

A ' expands to a quote form in quite a literal way.

``````> (car ''road)
'quote
'quote
``````> (+ 1 . (2))