Scheme Essentials

Basic Syntax

 1; Comments start with semicolon
 2
 3;; Variables
 4(define x 42)
 5(define pi 3.14159)
 6
 7;; Functions
 8(define (square x)
 9  (* x x))
10
11(define (factorial n)
12  (if (<= n 1)
13      1
14      (* n (factorial (- n 1)))))
15
16;; Lambda
17(lambda (x) (* x x))
18((lambda (x) (* x x)) 5) ; => 25
19
20;; Let bindings
21(let ((x 10)
22      (y 20))
23  (+ x y))  ; => 30
24
25;; Let* (sequential bindings)
26(let* ((x 10)
27       (y (+ x 5)))
28  y)  ; => 15
29
30;; Letrec (recursive bindings)
31(letrec ((even? (lambda (n)
32                  (if (= n 0)
33                      #t
34                      (odd? (- n 1)))))
35         (odd? (lambda (n)
36                 (if (= n 0)
37                     #f
38                     (even? (- n 1))))))
39  (even? 10))  ; => #t

Data Structures

Lists

 1;; Create lists
 2'(1 2 3 4)
 3(list 1 2 3 4)
 4(cons 1 (cons 2 (cons 3 '())))
 5
 6;; Access elements
 7(car '(1 2 3))    ; => 1
 8(cdr '(1 2 3))    ; => (2 3)
 9(cadr '(1 2 3))   ; => 2 (car of cdr)
10(caddr '(1 2 3 4)) ; => 3
11
12;; List operations
13(append '(1 2) '(3 4))  ; => (1 2 3 4)
14(reverse '(1 2 3))      ; => (3 2 1)
15(length '(1 2 3))       ; => 3
16(member 2 '(1 2 3))     ; => (2 3)
17
18;; List predicates
19(null? '())       ; => #t
20(pair? '(1 2))    ; => #t
21(list? '(1 2 3))  ; => #t

Vectors

 1;; Create vector
 2(vector 1 2 3 4)
 3#(1 2 3 4)
 4
 5;; Access elements
 6(vector-ref #(1 2 3) 1)  ; => 2
 7
 8;; Modify (if mutable)
 9(define v (vector 1 2 3))
10(vector-set! v 1 99)
11v  ; => #(1 99 3)
12
13;; Length
14(vector-length #(1 2 3))  ; => 3

Control Flow

Conditionals

 1;; if
 2(if (> x 10)
 3    "Greater"
 4    "Not greater")
 5
 6;; cond
 7(cond
 8  ((< x 0) "Negative")
 9  ((= x 0) "Zero")
10  ((> x 0) "Positive")
11  (else "Unknown"))
12
13;; case
14(case (day-of-week)
15  ((monday tuesday wednesday thursday friday) "Weekday")
16  ((saturday sunday) "Weekend")
17  (else "Unknown"))
18
19;; and, or
20(and (> x 0) (< x 100))
21(or (= x 0) (= x 1))

Recursion

 1;; Factorial
 2(define (factorial n)
 3  (if (<= n 1)
 4      1
 5      (* n (factorial (- n 1)))))
 6
 7;; Tail-recursive factorial
 8(define (factorial-tail n)
 9  (define (iter n acc)
10    (if (<= n 1)
11        acc
12        (iter (- n 1) (* n acc))))
13  (iter n 1))
14
15;; List sum
16(define (sum lst)
17  (if (null? lst)
18      0
19      (+ (car lst) (sum (cdr lst)))))
20
21;; List length
22(define (my-length lst)
23  (if (null? lst)
24      0
25      (+ 1 (my-length (cdr lst)))))

Higher-Order Functions

 1;; map
 2(map square '(1 2 3 4))  ; => (1 4 9 16)
 3(map + '(1 2 3) '(10 20 30))  ; => (11 22 33)
 4
 5;; filter
 6(filter even? '(1 2 3 4 5 6))  ; => (2 4 6)
 7
 8;; fold (reduce)
 9(foldl + 0 '(1 2 3 4 5))  ; => 15
10(foldr cons '() '(1 2 3))  ; => (1 2 3)
11
12;; apply
13(apply + '(1 2 3))  ; => 6

Macros (Syntax Rules)

 1;; Simple macro
 2(define-syntax when
 3  (syntax-rules ()
 4    ((when test body ...)
 5     (if test
 6         (begin body ...)))))
 7
 8(when (> 5 3)
 9  (display "True")
10  (newline))
11
12;; Unless macro
13(define-syntax unless
14  (syntax-rules ()
15    ((unless test body ...)
16     (if (not test)
17         (begin body ...)))))
18
19;; While loop macro
20(define-syntax while
21  (syntax-rules ()
22    ((while test body ...)
23     (let loop ()
24       (when test
25         body ...
26         (loop))))))

Continuations

 1;; call/cc (call-with-current-continuation)
 2(define (return-from-middle)
 3  (call/cc
 4    (lambda (return)
 5      (display "Before")
 6      (newline)
 7      (return 42)  ; Early return
 8      (display "After")  ; Never executed
 9      (newline))))
10
11;; Non-local exit
12(define (search-list lst target)
13  (call/cc
14    (lambda (return)
15      (for-each
16        (lambda (item)
17          (when (equal? item target)
18            (return item)))
19        lst)
20      #f)))

Practical Examples

List Processing

 1;; Quicksort
 2(define (quicksort lst)
 3  (if (null? lst)
 4      '()
 5      (let ((pivot (car lst))
 6            (rest (cdr lst)))
 7        (append
 8          (quicksort (filter (lambda (x) (< x pivot)) rest))
 9          (list pivot)
10          (quicksort (filter (lambda (x) (>= x pivot)) rest))))))
11
12;; Flatten list
13(define (flatten lst)
14  (cond
15    ((null? lst) '())
16    ((pair? (car lst))
17     (append (flatten (car lst))
18             (flatten (cdr lst))))
19    (else
20     (cons (car lst) (flatten (cdr lst))))))
21
22;; Remove duplicates
23(define (remove-duplicates lst)
24  (cond
25    ((null? lst) '())
26    ((member (car lst) (cdr lst))
27     (remove-duplicates (cdr lst)))
28    (else
29     (cons (car lst) (remove-duplicates (cdr lst))))))

File I/O

 1;; Read file
 2(define (read-file filename)
 3  (call-with-input-file filename
 4    (lambda (port)
 5      (let loop ((line (read-line port))
 6                 (result '()))
 7        (if (eof-object? line)
 8            (reverse result)
 9            (loop (read-line port)
10                  (cons line result)))))))
11
12;; Write file
13(define (write-file filename content)
14  (call-with-output-file filename
15    (lambda (port)
16      (display content port))))

String Operations

 1;; String concatenation
 2(string-append "Hello" " " "World")
 3
 4;; String to list
 5(string->list "Hello")  ; => (#\H #\e #\l #\l #\o)
 6
 7;; List to string
 8(list->string '(#\H #\i))  ; => "Hi"
 9
10;; Substring
11(substring "Hello World" 0 5)  ; => "Hello"
12
13;; String length
14(string-length "Hello")  ; => 5

Racket-Specific Features

 1#lang racket
 2
 3;; Require modules
 4(require racket/list)
 5(require racket/string)
 6
 7;; Struct (like record)
 8(struct point (x y) #:transparent)
 9
10(define p (point 3 4))
11(point-x p)  ; => 3
12(point-y p)  ; => 4
13
14;; Pattern matching
15(match '(1 2 3)
16  [(list a b c) (+ a b c)])  ; => 6
17
18(match 5
19  [0 "zero"]
20  [1 "one"]
21  [n (format "number: ~a" n)])  ; => "number: 5"
22
23;; For loops
24(for ([i (in-range 5)])
25  (displayln i))
26
27(for/list ([i (in-range 5)])
28  (* i i))  ; => (0 1 4 9 16)
29
30(for/sum ([i (in-range 1 6)])
31  i)  ; => 15

Further Reading

Related Snippets