CS152
Chris Pollett
Nov 15, 2021
(define my-class (lambda (construct-arg1 ...) (let ((my-field1 val1) ; it is also legal to nest define's in Scheme (my-field2 val2) ...) (lambda (msg . args) (cond ((eqv? msg msg1) ;do-some-action )... ))))
(define my-instance (my-class construct-val1 ...))
(my-instance msg1 msg1-args)
Which of the following statements is true?
(* (+ 2 3) (- 4 3) )it uses applicative order evaluation. That is, it evaluates all of its arguments before evaluating the procedure in an S-expression.
(define double (lambda (x) (+ x x)))
;Applicative order (double (* 3 4)) =>(double 12) =>(+ 12 12) =>24
;Normal order (double (* 3 4)) =>(+ (* 3 4) (* 3 4)) =>(+ 12 (* 3 4)) =>(+ 12 12) =>24In this case normal order evaluation causes us to do extra work.
(define switch (lambda (x a b c) (cond ((< x 0) a) ((= x 0) b) ((> x 0) c))))
;Applicative order (switch -1 (+ 1 2) (+ 2 3) (+ 3 4)) => (switch -1 3 (+ 2 3) (+ 3 4)) => (switch -1 3 5 (+ 3 4)) => (switch -1 3 5 7) => (cond ((< -1 0) 3) ((= -1 0) 5) ((> -1 0) 7)) => (cond (#t 3) ((= -1 0) 5) ((> -1 0) 7)) => 3
;Normal order (switch -1 (+ 1 2) (+ 2 3) (+ 3 4)) => (cond ((< -1 0) (+ 1 2)) ((= -1 0) (+ 2 3)) ((> -1 0) (+ 3 4))) => (cond (#t (+ 1 2)) ((= -1 0) (+ 2 3)) ((> -1 0) (+ 3 4))) => (+ 1 2) => 3
(define-syntax nil! (syntax-rules () ((_ x) ; _ is abbreviating the name of the macro nil! ; so this says if see pattern (nil! x) ; replace with next line. ; Here we only have one pattern, legal to have several (set! x '()))))
(define (f-nil! x) (set! x '()))
(define a 1) ;Value: a (f-nil! a) ;Value: 1 a ;Value: 1 ; the value of a does not change ; as value was changed only in scope of f-nil! function (nil! a) ;Value: 1 a ;Value: () ; a becomes '()
(define-syntax my-delay (syntax-rules () ((my-delay expr) (lambda () expr))))
(define (my-force promise) (promise))
(delay (+ 5 6)) ;return a promise (let ((delayed (delay (+ 5 6)))) (force delayed)) ; returns 11
(define-syntax cons-stream (syntax-rules () ((cons-stream x y) (cons x (delay y))))) (define head car) (define (tail stream) (force (cdr stream))) (define empty-stream? null?) (define the-empty-stream '())
(define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define nat-nums (integers-starting-from 1))
We will talk some more about evaluation order on Wednesday, for the rest of today I will talk about various built-in functions in Scheme:
(string->symbol "hi") outputs hi symbol (symbol->string 'hi) outputs "hi" string
(let ((x 2) (y 3)) (let* ((x 11) (z (+ x y))) ; 11 + 3 = 14 (* z x))) ; 11 * 14 = 154
(letrec ((even? (lambda (n) (if (zero? n) #t (odd? (- n 1))))) (odd? (lambda (n) (if (zero? n) #f (even? (- n 1)))))) (even? 86)) ; #t
(do ((<variable1> <init1> <step1>) ...) (<test> <expression> ...) <command> ...)For example,
do ((vec (make-vector 5)) (i 0 (+ i 1))) ((= i 5) vec) (vector-set! vec i i)) ; returns the vector #(0 1 2 3 4)
(let <variable> <bindings> <body>)The bindings are like a usual let expression. body is allowed, as in a normal let, to use these bindings, but it can also use variable as the name of a procedure. variable is bound to the procedure whose parameter list consists of the names from bindings and whose code is given by body. See the next slide for an example of using a named let.
(define (tokenize l delim) (let loop ((t '()) (l l)) (if (pair? l) ; checks if dotted pair (let ((c (car l))) (if (char=? c delim) (cons (reverse t) (loop '() (cdr l))) (loop (cons (car l) t) (cdr l)))) (if (null? t) '() (list (reverse t)))))) (define (string-split s delim) (map list->string (tokenize (string->list s) delim))) ; map takes a function f and a list (e1 e2 ... en) and computes ; ((f e1) (f e2) ... (f en)) (string-split "hi there" #\space) ; returns ("hi" "there")