Programming with Scheme:
🔰 1. Introduction to Scheme
Scheme is a functional, minimalist, and elegant programming language designed for clarity
and mathematical reasoning. It is a dialect of Lisp, known for its uniform syntax and support for
symbolic computation.
🔍 Why Scheme?
● Encourages thinking in functions, not instructions.
● Great for understanding recursion, abstraction, and immutability.
● Used in education (e.g., MIT's Structure and Interpretation of Computer Programs).
✅ Key Characteristics:
● Minimal Core: Few constructs but highly expressive.
● Static (Lexical) Scoping: Variable scope is based on code structure, not runtime.
● First-Class Functions: Functions are treated as values—can be passed, returned, and
stored.
● Recursion: Preferred over iteration; essential for list processing and loops.
● Immutability: Avoids side-effects; variables, once bound, do not change (in pure form).
🖥️ 2. The Scheme Interpreter (REPL)
Scheme is typically executed in a REPL (Read-Eval-Print Loop) environment.
💡 Working:
● Read: User enters an expression.
● Eval: Scheme interpreter evaluates it.
● Print: The result is displayed.
🧪 Example:
scheme
CopyEdit
(+ 2 3) ; → 5
(DISPLAY "Hi") ; → Hi
(NEWLINE) ; Creates a newline
● Comments start with ; and are ignored by the interpreter.
➕ 3. Primitive Numeric Functions
Scheme supports basic mathematical operations in prefix notation (operator before operands).
🧠 Theory:
All numeric operators are variadic (accept multiple arguments). Evaluation order of arguments
is unspecified.
✅ Operators and Examples:
Operator Description Example Output
+ Addition (+ 2 4 3) 9
- Subtraction (- 10 3) 7
* Multiplication (* 2 3 4) 24
/ Division (/ 20 4) 5
MODULO Remainder (MODULO 17 2
5)
SQRT Square root (SQRT 25) 5
MAX Maximum (MAX 3 8 8
6)
ROUND Nearest (ROUND 4
integer 3.6)
🛠️ 4. Defining Variables and Functions
Scheme allows binding values and functions using DEFINE.
1️⃣ Binding Names to Values:
scheme
CopyEdit
(DEFINE pi 3.14159)
(DEFINE r 5)
(DEFINE area (* pi (* r r))) ; → 78.53975
2️⃣ Defining Named Functions:
scheme
CopyEdit
(DEFINE (square x) (* x x))
(square 6) ; → 36
This is syntactic sugar for:
scheme
CopyEdit
(DEFINE square (LAMBDA (x) (* x x)))
3️⃣ Anonymous Functions (Lambda):
scheme
CopyEdit
((LAMBDA (x) (* x x)) 4) ; → 16
Use when a function is needed only once, or as an argument to another function.
🔁 5. Control Flow in Scheme
Scheme uses expressions rather than statements. Everything returns a value.
🧪 IF Expression:
Used for binary decisions.
scheme
CopyEdit
(IF condition then-expression else-expression)
Example:
scheme
CopyEdit
(DEFINE (absolute x)
(IF (< x 0)
(- 0 x)
x))
(absolute -5) ; → 5
🧪 COND Expression:
Used for multiple branches.
scheme
CopyEdit
(COND
((< x 0) 'Negative)
((= x 0) 'Zero)
(ELSE 'Positive))
Example:
scheme
CopyEdit
(DEFINE (sign x)
(COND
((< x 0) 'Negative)
((= x 0) 'Zero)
(ELSE 'Positive)))
(sign 2) ; → 'Positive
🔍 6. Predicate Functions
Predicates are functions that return boolean values: #T (true), #F (false), or '() (false in some
dialects).
✅ Common Predicates:
Predicate Description Example Output
= Equals (= 4 4) #T
<> Not equal (<>) #T
< Less than (< 2 4) #T
> Greater (> 4 2) #T
than
ZERO? Is it 0? (ZERO? #T
0)
EVEN? Is it even? (EVEN? #T
4)
ODD? Is it odd? (ODD? #T
3)
📚 7. List Processing
Lists are Scheme’s primary data structure. A list is a sequence enclosed in parentheses: (A B
C).
➤ QUOTE:
Prevents evaluation.
scheme
CopyEdit
(QUOTE (A B C)) ; → (A B C)
'(A B C) ; shorthand
➤ CAR, CDR:
Function Description Example Output
CAR First element (CAR '(X Y X
Z))
CDR All but first element (CDR '(X Y (Y Z)
Z))
➤ CONS:
Creates a new list by prepending an item.
scheme
CopyEdit
(CONS 'A '(B C)) ; → (A B C)
🔁 Example: Second Element
scheme
CopyEdit
(DEFINE (second lst)
(CAR (CDR lst)))
(second '(A B C)) ; → B
🔍 8. Member Check Function (Recursive)
Checks if an atom exists in a list:
scheme
CopyEdit
(DEFINE (member atm lst)
(COND
((NULL? lst) #F)
((EQ? atm (CAR lst)) #T)
(ELSE (member atm (CDR lst)))))
(member 'B '(A B C)) ; → #T
● Uses recursion, essential in functional programming.
● This version is tail-recursive, improving performance.
🧪 9. LET Construct
LET allows defining temporary local variables within a block.
Syntax:
scheme
CopyEdit
(LET ((var1 val1)
(var2 val2))
expression)
Example: Quadratic Formula
scheme
CopyEdit
(DEFINE (quadratic_roots a b c)
(LET ((disc (SQRT (- (* b b) (* 4 a c))))
(denom (* 2 a)))
(LIST (/ (+ (- b) disc) denom)
(/ (- (- b) disc) denom))))
(quadratic_roots 1 5 6) ; → (-2 -3)
🌀 10. Tail Recursion
Theory:
Tail-recursion is a form of recursion where the last operation is the recursive call. Scheme
optimizes such functions to run without growing the call stack.
Example:
scheme
CopyEdit
(DEFINE (factorial n acc)
(IF (= n 0)
acc
(factorial (- n 1) (* n acc))))
(factorial 5 1) ; → 120
This avoids deep recursion and improves efficiency.
🧰 11. Functional Forms
➤ Function Composition
Create a function that combines others.
scheme
CopyEdit
(DEFINE (compose f g)
(LAMBDA (x) (f (g x))))
(DEFINE (inc x) (+ x 1))
(DEFINE (double x) (* x 2))
((compose inc double) 4) ; → 9
➤ Map (Apply to all elements of list)
scheme
CopyEdit
(DEFINE (map fun lst)
(COND
((NULL? lst) '())
(ELSE (CONS (fun (CAR lst)) (map fun (CDR lst))))))
(map (LAMBDA (x) (* x x)) '(2 4 6)) ; → (4 16 36)
📝 Summary of Scheme Features
Feature Description
Functional Paradigm Emphasizes functions and recursion
Minimalist Syntax Parentheses and prefix notation
First-Class Functions Can be passed, returned, and stored
Static Scoping Lexical variable binding
List-Oriented Lists are a core data structure
Tail Recursion Optimized Efficient recursion
LET and LAMBDA Local scoping and anonymous
functions
Higher-Order Functions map, compose for abstraction