Concepts of Programming Languages

Scheme

Instructor: Stefan Mitsch

Lisp and Scheme

  • Lisp (LISt Processor)
  • Influential programming language from the 1950s
  • Originally motivated by logic / AI applications
  • Pioneered many PL concepts:
    • automatic garbage collection
    • first-class, higher-order, nested functions
    • read-eval-print loop including runtime compilation with "eval"
    • sophisticated macro system
    • multiple dispatch / multi-methods

Lisp and Scheme

  • Dialects: Common Lisp, Scheme, Clojure, Racket
  • We will use Scheme
  • Sample Scheme function to find the length of a list
    
    ; This (recursive) function calculates the length of a linked list.
    (define (length l) 
      (if (equal? l ()) 
        0 
        (+ 1 (length (cdr l)))))
                  
  • Lots of Infuriating & Silly Parentheses

Scheme Resources

Running Scheme

  • Use repl.it
    • Warning: No support for rational numbers, such as 1/2
  • Use homebrew
    • brew search scheme
    • brew search chicken

Literals in Scheme

  • Number literal
    5
  • String literal
    "hello world"
  • Symbol
    'helloworld

Arithmetic in Scheme

  • Arithmetic expressions use prefix notation
    
    ; (1 + 2) * 3 would be written in Scheme as follows
    (* (+ 1 2) 3)
                  
  • Parentheses are required for each operator
    • Operator precedence not necessary!
  • Try out
    
    (+ 10 5 2)
    (- 10 5 2)
                  

Operator Terminology

  • Prefix notation: operator before arguments
    
    + 1 2
                  
  • Infix notation: operator between arguments
    
    1 + 2
                  
  • Postfix notation: operator after arguments
    
    1 2 +
                  

Functions

  • Define a function square with parameter n
    
    (define (square n) (* n n))
                  
  • Invoke the square function
    
    (square 5)
                  
  • Invoke the square function twice
    
    (square (square 5))
                  

Defining Functions

  • General form is
    
    (define (f param_1 param_2 ... param_m) 
      e_1 e_2 ... e_n)
                  
  • Takes m arguments
  • Body of function is a sequence of expressions
  • e_1, e_2, ..., e_n-1 evaluated for side effect
  • e_n is evaluated and its result is returned
  • No return keyword, no statements, just expressions
  • begin like C comma operator, but not needed
    
    (define (f param_1 param_2 ... param_m) 
      (begin e_1 e_2 ... e_n))
                  

Invoking Functions

  • Invoke function f with m arguments
    
    (f e_1 e_2 ... e_m-1)
                  
  • Parentheses are required
    
    (square 5)
                  
  • Try in Scheme REPL
    
    square 5
                  

Evaluation Order

  • Expression (f M N) is evaluated by
    1. Evaluating expression M to value U
    2. Evaluating expression N to value V
    3. Invoking function f with values U and V
  • define is a special form, not a function, so it does not obey this convention

Booleans and Conditionals

  • = operator tests number equality
    
    (define (zero n) (= n 0))
                  
  • Boolean values are #t and #f
  • if is a non-strict special form
    
    (define (safe-divide m n) 
      (if (= n 0) 
          "divide by zero"
          (/ m n)))
                  

Recursive Functions

  • Recursive functions are common in Scheme
  • Factorial using conditional expressions
    
    (define (fact n) 
      (if (<= n 1) 
          1 
          (* n (fact (- n 1)))))
                  
  • Recall C factorial using conditional expressions
    
    int fact (int n) {
      return (n <= 1) ? 1 : n * fact (n - 1);
    }
                  

Cons Cells

  • A cons cell is a pair of two pieces of data
  • Pair of numbers
    
    (cons 1 2)
                  
  • Pair of strings
    
    (cons "hello" "world")
                  
  • Pair of a number and a string
    
    (cons 1 "world")
                  
  • car and cdr functions extract components
    
    (car (cons 1 "world"))
    (cdr (cons 1 "world"))
                  

Cons Cells For Linked Lists

Linked List  with four elements: 11, 21, 31, 41
  • Cons cells (pairs) are used to represent linked lists
  • car position for elements
  • cdr position for next cons cell

Cons Cells For Linked Lists

  • Linked lists built up using () and cons
  • Empty list
    
    ()
                  
  • Singleton list containing 41 only
    
    (cons 41 ())
                  
  • List containing 11, 21, 31, 41
    
    (cons 11 (cons 21 (cons 31 (cons 41 ()))))
                  

A More Complex Example

  • Lists can be heterogeneous

Syntactic Sugar For Lists

  • quote special form prevents evaluation
    
    (quote (3))
    (quote (1 2 3))
                  
  • ' is shorthand for quote
    
    '(3)
    '(1 2 3)
                  
  • list function evaluates args, puts results in a list
    
    (list 3)
    (list 1 2 3)
    (list 1 2 (+ 1 2))
                  

Equality Testing For Lists

  • eq? for pointer equality
    
    (eq? (cons 1 (cons 2 (cons 3 ()))) '(1 2 3))
                  
  • equal? for structural equality
    
    (equal? (cons 1 (cons 2 (cons 3 ()))) '(1 2 3))
                  
  • Pointer equality compares two pointers
  • Structural equality traverses two structures

Recursive Functions On Lists

  • Compute length of linked list recursively
    
    (define (length l) 
      (if (equal? l ()) 
        0 
        (+ 1 (length (cdr l)))))
    
    (length '(5 6 7 8 9))
                  
  • Or in Java
    
    class Node {
      int item;
      Node next;
    }
    
    static int length (Node data) {
      return (data == null) ? 0 : 1 + length (data.next)
    }
                  

Recursive Functions On Lists

  • Compute length of linked list recursively
    
    (length '(5 6 7))
    --> (if (equal? '(5 6 7) '()) 0 (+ 1 (length (cdr '(5 6 7)))))
    --> (+ 1 (length (cdr '(5 6 7))))
    --> (+ 1 (length '(6 7)))
    --> (+ 1 (+ 1 (length '(7))))
    --> (+ 1 (+ 1 (+ 1 (length '()))))
    --> (+ 1 (+ 1 (+ 1 0)))
    --> (+ 1 (+ 1 1))
    --> (+ 1 2)
    --> 3
                  

Dynamic Types


(symbol? 'x)
(number? 1)
(boolean? #t)
(string? "x")
(procedure? (lambda (x) (+ x 1)))
          

(pair? '(1 . 2))
(pair? '(1))
; (pair? '())
; (list? '(1 . 2))
(list? '(1))
(list? '())
          
  • List only has one structure type: the pair.
  • A non-empty list is just a special type of pair, with a terminal

S-Expressions

  • Pairs are a kind of Symbolic-Expression (S-Exp)
  • S-Exps also include non-structured values, including numbers, booleans, strings, symbols and '().
  • Parsing a scheme program results in an S-Exp, which is then sent to eval for evaluation.
  • (quote exp) causes exp to be parsed without evaluation, resulting in an S-Exp.

Read-Eval-Print Loop (REPL)

  • Quoting delays evaluation
    
    (+ 1 2)
    '(+ 1 2)
    (cons '+ '(1 2))
    (car '(+ 1 2))
                  
  • eval function evaluates an expression
    
    (eval (cons '+ '(1 2)))
    (define (add-all l) (eval (append '(+) l)))
    (add-all '(1 2 3))
                  
  • read function reads an expression
    
    (read)
    (eval (read))
    (eval (append '(+) (read)))