Note 5
Scheme
Scheme is a dialect of Lisp, the second-oldest programming language that is still widely used today.
Scheme python code
https://github.com/reah/scheme_interpreter/tree/master
Notes : this code does not cover all the built-in function in the Scheme ,just use it to do some simple tasks
Special Forms
A combination that is not a call expression is a special form:
- if expression: ( if <predicate> <consequent> <alternative> )
- Evaluate the predicate expression
- Evaluate either the consequent or alternative
- And and or : ( and <e1> … <e2> ) ,( or <e1> … <e2> )
- Binding symbols : ( define < symbol > <expression> )
- New procedures : ( define (< symbol > <formal parameters> ) < body > )
scm> (define (square x) (* x x))
square
# define abs
scm> (define (abs x)
(if (< x 0)
(-x)
x))
abs
# define recursive function in scheme
scm> (define (sqrt x)
(define (update guess)
(if (=square guess) x)
guess
(update (average guess (/ x guess)))))
(update 1))
sqrt
lambda expressions
lambda expressions evaluate to anonymous procedures.
( lambda (< formal-parameters >) < body>)
# two equivalent expressioms:
scm> (define (plus4 x) (+ x 4))
scm> (define plus4 (lambda (x) (+ x 4)))
Sierpinski’s Triangle
# forward
scm> (fd 100)
# backward
scm> (bk 100)
#turn right by an angle
scm> (rt 90)
#turn left by an angle
scm> (t 90)
# draw a line
(define (line) (fd 50))
# define a repeat function ,k is the repeat times
(define (repeat k fn)
(fn)
(if (> k 1)(repeat (-k 1) fn)))
# define a triangle
(define (tri fn)
(repeat 3 (lambda () (fn) (lt 120))))
# draw a triangle
scm> (tri line)
### sierpinski's triangle
### sierpinski's triangle has some recursive depth d ,and some side length k
(define (sier d k)
(tri (lambda () (if (= d 1) (fd k) (leg d k)))))
(define (leg d k)
(sier (- d 1) (/ k 2)
(penup) (fd k) (pendown))
scm> (rt 90)
scm> (speed 0)
scm> (sier 5 200)
Cond & Begin
The cond special form that behaves like if-elif-else statements in Python.
# python if - elif - else
if x > 10:
print('big')
elif x > 5:
print('medium')
else:
print('small')
# in scheme using cond
(cond ((> x 10) (print 'big))
((> x 5) (print 'medium))
(else (print 'small)))
# or
(print
(cond ((> x 10) 'big)
((> x 5) 'medium)
(else 'small)))
The begin special form combined multiple expressions into one expression
# using two print in Python
if x > 10:
print('big')
print('guy')
else:
print('small')
print('fry')
# using cond and begin
(cond ((> x 10) (begin (print 'big) (print 'guy)))
(else (begin (print 'small) (print 'fry))))
Let expression
The let special form binds symbols to value temporarily ; just for one expression
a = 3
b = 2 + 2
c = math.sqrt(a*a + b*b)
# a and b are still bound here
# using let in scheme
# a and b are not bound down here
(define c (let ((a 3)
(b (+ 2 2)))
(sqrt (+ (* a a) (* b b)))))
Lists in scheme
Lists in scheme are like the Linked list class that we created in Python
- cons: Two-argument procedure that creates a linked list
- car: Procedure that returns the first element of a list
- cdr: Procedure that return the rest of a list
- nil: The empty list
- Scheme lists are written in parentheses with elements separated by spaces.
scm> (cons 1 (cons 2 nil))
(1 2)
scm> (define x (cons 1 (cons 2 nil)))
scm> x
(1 2)
scm> (car x)
1
Symbolic Programming
Symbols normally refer to values , but how do we refer to symbols?
- Quotation is used to refer to symbols directly in Lisp
- Short for (quote a), (quote b): Special form to indicated that the expression itself is the value
- Quotation can also be applied to combinations to form lists.
- 'a is the same as (quote a)
scm> (define a 1)
scm> (define b 2)
# no
scm> (list a b)
(1 2)
scm> (list 'a 'b)
(a b)
scm> (list 'a b)
(a 2)
scm> (list a 'b)
(1 b)
scm> (car (cdr (car (cdr '(1 (2 3) 4)))))
3
Programs as Data
A scheme expression is a scheme list
Scheme programs consist of expressions which can be:
- Primitive expressions : 2 3.3 true + quotient
- Combinations: (quotient 10 2) (not true)
The built-in Scheme list data structure (which is a linked list) can be represent combinations
scm> (list 'quotient 10 2)
(quotient 10 2)
scm> (eval (list 'quotient 10 2))
5
scm> (define (fib n)
(if (<= n 1) n (+ (fib(- n 2)) (fib (- n 1)))))
scm> (define (fib-exp n)
(if (<= n 1) n (list '+ (fib-exp(- n 2)) (fib-exp(- n 1)))))
scm> (fib 4)
3
scm> (fib-exp 4)
(+ (+ 0 1) (+ 1 (+ 0 1)))
scm> (eval (fib-exp 4))
3
Quasiquotation
There are two ways to quote an expression
- Quote: '(a b) => (a b)
- Quasiquotation: `(a b) => (a b)
There are different because parts of a quasiquotation ca be unquoted with
(define b 4)
Quote : '(a ,(+ b 1)) => (a (unquote (+ b 1)
Quasiquote : `(a ,(+ b 1)) => (a 5)
Quasiquotation is particularly convenient for generating Scheme expressions.
(define (make-add-procedure n) `(lambda (d) (+ d ,n)))
(make-add-procedure 2) => (lambda (d) (+ d 2))
Example - While Statements
(define (sum-while intial-x condition add-to-total update-x)
;(sum-while 1 '(< (* x x) 50) 'x '(+ x 1)
`(begin
(define (f x total)
(if ,condition
(f ,update-x (+ total ,add-to-total))
total))
(f ,initial-x 0)))
scm> (eval (sum-while 2 '(< x 10) '(* x x) '(+ x 2)))
120
scm> (sum-while 2 '(< x 10) '(* x x) '(+ x 2))
(begin (define (f x total) (if (< x 10) (f (+ x 2) (+ total (* x x))) total)) (f 2 0))
Some exercises
Mull It Over
Some one evaluated (define * +). Now ( * evaluates to 5 instead of 6. Let’s fix it .
Important: Answer all questions on this page without call the built-in multiplication procedure.
- (a) Implement mulxy ,which multiplies integers x and y; Hint: (- 2) evaluates to -2.
scm> ;;multiply x by y (without using * operator
;;(mulxy 3 4) -> 12 ; 12 = 3 + 3 + 3 + 3
;;(mulxy (- 3) (- 4)); 12 = - (-3 + -3 + -3 + -3)
scm> (define (mulxy x y)
(cond ((< y 0) (- mulxy(x (- y))))
((= y 0) 0)
(else (+ x (mulxy x (- y 1))))))
scm> (mulxy 3 4)
12
scm> (mulxy -3 4)
-12
- (b) Implement mul-expr, which takes an expression e that contains only call to * and numbers.It returns the normal value of e under a Scheme interpreter with an unmodified * operator that multiplies .You may call the mul procedure defined below and map in the scheme is similar as the python.
# this code has not been tested
;; Multiply together a list of numbers
;; (mul '(2 3 4 2)) -> 48
(define (mul s) (reduce mulxy s))
;; Evaluate an expression with only calls to * and numbers
;; (mul-expr '(* (* 1 2) (* 3(* 4 1 1) 2))) -> 48
(define (mul-expr e)
(if (number? e) e
(mul (map mul-expr (cdr e)))))
hw
(define (filter-lst fn lst)
'YOUR-CODE-HERE
(cond ((null? lst) '())
((fn (car lst)) (cons (car lst)(filter-lst fn (cdr lst))))
(else (filter-lst fn (cdr lst))))
)
;;; Tests
(define (even? x)
(= (modulo x 2) 0))
(filter-lst even? '(0 1 1 2 3 5 8))
; expect (0 2 8)
(define (interleave first second)
'YOUR-CODE-HERE
(if (or (null? first) (null? second))
(append first second)
(cons (car first)
(cons (car second)
(interleave cdr(first) cdr(second)))))
)
(interleave (list 1 3 5) (list 2 4 6))
; expect (1 2 3 4 5 6)
(interleave (list 1 3 5) nil)
; expect (1 3 5)
(interleave (list 1 3 5) (list 2 4))
; expect (1 2 3 4 5)
(define (accumulate combiner start n term)
'YOUR-CODE-HERE
(if (= n 0)
start
(accumulate combiner (term n) start) (- n 1) term))
)
(define (no-repeats lst)
'YOUR-CODE-HERE
(if (null? lst) lst
(cons (car lst)
(no-repeats (filter (lambda (x) (not (= (car lst) x))) (car lst)))))
)