introduction to scheme cs 480/680 – comparative languages “and now for something completely...
TRANSCRIPT
Introduction to SchemeIntroduction to Scheme
CS 480/680 – Comparative LanguagesCS 480/680 – Comparative Languages
“And now for something completely different…”
– Monty Python
“And now for something completely different…”
– Monty Python
Intro to Scheme 2
Functional LanguagesFunctional Languages Scheme is a functional language. It belongs to a class
of languages that differ from imperative languages in a number of ways:
• Elegant, concise, syntax (and specification).
• Definition of functions is paramount – Order is not that important!
• No iteration! -- Use of recursion instead.
• Data is generally weakly/dynamically typed.
Intro to Scheme 3
Why Scheme?Why Scheme? Very simple syntax (the E-BNF specification is
only 8 pages – see the last slides) Lisp is the standard for functional languages,
Scheme is a rising star Many efforts to make it a teachable language
• Cal-Tech, MIT, etc.
DR-Scheme
Intro to Scheme 4
Forms and EvaluationForms and Evaluation The basic scheme construct is called a form
• (function argument1 argument2 argument3…)
(+ 2 5) » 7 (+ 3 4 5) » 12 (/ 22 7) » 22/7 (number? 5) » #t (boolean? 5) » #f (boolean? #5) » #t (eqv? 42 42) » #t (eqv? 42 42.0) » #f (= 42 42.0) » #t
(= 42 #x2A) » #t (expt 4 2) » 16 (expt 4 1/2) » 2 (max 1 3 5 7) » 7 (min 1 3 5 7) » 1 (abs -2) » 2 (abs -2 5) abs: expects 1 argument, given 2: -2 5
Intro to Scheme 5
Substitution ModelSubstitution Model
The basic rule:
To evaluate a Scheme expression:
1. Evaluate its operands
2. Evaluate the operator
3. Apply the operator to the evaluated operands
Intro to Scheme 6
Warning!Warning! Boredom ahead!Boredom ahead!
We will walk through evaluations
• in painful, excruciating detail
Not the most exciting part of course
but necessary to give a precise
model
Intro to Scheme 9
Example expression evalExample expression eval Example: (+ 3 (* 4 5) )
operator
operand 1
Intro to Scheme 10
Example expression evalExample expression eval
Example: (+ 3 (* 4 5) )
operator
operand 1
operand 2
Intro to Scheme 11
Example expression evalExample expression eval
Example: (+ 3 (* 4 5))• evaluate 3 • evaluate (* 4 5)
evaluate 4 evaluate 5 evaluate * apply * to 4, 5 20
• evaluate +• apply + to 3, 20 23
Intro to Scheme 12
Primitive expressionsPrimitive expressions
Numbers evaluate to themselves• 105 105
Primitive procedures• +, -, *, /, abs …
• evaluate to the corresponding internal procedure
• e.g. "+" evaluates to the procedure that adds numbers together
Can write this as: + +• or as: + [primitive procedure +]
• write this out explicitly for now
Intro to Scheme 13
Another exampleAnother example
(+ 3 (- 4 (* 5 (expt 2 2))))• evaluate 3 3• evaluate (- 4 (* 5 (expt 2 2)))
evaluate 4 4 evaluate (* 5 (expt 2 2))
– evaluate 5 5– evaluate (expt 2 2)
» evaluate 2 2, evaluate 2 2, expt expt» apply expt to 2, 2 4
– evaluate * *– apply * to 5, 4 20
apply - to 4, 20 -16
• apply + to 3, -16 -13
Intro to Scheme 14
Evaluation with variablesEvaluation with variables
An assignment provides an association between a symbol (variable) and its value
(define x 3) Here x is the variable, 3 is the value
To evaluate a variable: look up the value associated with the variable and replace the variable with its value
Intro to Scheme 15
Variable evaluation exampleVariable evaluation example (define x 3) Then evaluate x
• look up value of x• x has value 3 (due to define)• result: 3
Intro to Scheme 16
Simple expression evaluationSimple expression evaluation Assignment and evaluation
(define x 3)(define y 4) evaluate (+ x y)
evaluate x 3 evaluate y 4 evaluate + [primitive procedure +] apply + to 3, 4 7
Intro to Scheme 17
Special formsSpecial forms
N.B. There are a few special forms which do not evaluate in the way we’ve described.
define is one of them(define x 3)
• We do not evaluate x before applying define to x and 3
• Instead, we evaluate the second operand (3 3) make an association between it and the first operand
(x)
Intro to Scheme 18
Special formsSpecial forms
Another example: (define x (+ 2 3)) Evaluate (+ 2 3)
• evaluate 2 2
• evaluate 3 3
• evaluate + [primitive procedure +]
• apply + to 2, 3 5
Make association between x and 5• details of how association is made aren't important
Intro to Scheme 19
Basic Data TypesBasic Data Types Numbers: 3, -3, 22/7, 3+2i, #xF3A, #o721,
#b110110, 3.1416 (= 42 #x2A) » #t Single characters: #\c, #\newline, #\tab, #\space
• (char? #\c), (char=? #\c #\b), (char<=? #\c #\b)
Strings: “Hello World”• (string #\h #\i)• (string-ref “Hello” 1) » #\e• (string-append “E” “Pluribus” “Unum”) » “E Pluribus Unum”
Intro to Scheme 21
SymbolsSymbols Symbols have two parts, a name and a value
• Similar to variables in other languages, but beware of the many differences!
• We’ll see a lot more about the differences later.• (define xyz 9)
xyz » 9 (symbol? xyz) » #f (symbol? ’xyz) » #t (set! xyz 8) (set! qrs 7) set!: cannot set undefined identifier: qrs
Intro to Scheme 22
Arbitrary Data StructuresArbitrary Data Structures What is the simplest data structure that you can
use to create any other data structure, including dynamically sized structures?
What is the smallest component of this structure?
Intro to Scheme 23
Dotted PairsDotted Pairs Scheme uses pairs for many, many things
• Programs (forms)• Arguments• Data structures
A pair is a two-cell node. Each cell contains a pointer to a value or another pair.
A node with two pointers is called a dotted pair• (cons 1 2) » (1 . 2)• ’(1 . 2) » (1 . 2) 21
Intro to Scheme 24
car and cdrcar and cdr You access the two parts of a dotted pair with
the accessors car and cdr:• (define x (cons 1 2))
(car x) » 1 (cdr x) » 2
(pair? a) returns true if a is a dotted pair • (pair? (cons 3 4)) » #t• (pair? 3) » #f
Intro to Scheme 25
Dotted pairs can be nestedDotted pairs can be nested (define x (cons (cons 1 2) (cons 3 4)) (define x ‘((1 . 2) . (3 . 4)))
• (car x) » (1 . 2)• (cdr x) » (3 . 4)
4321
Intro to Scheme 26
Scheme shorthandScheme shorthand (cons 1 (cons 2 (cons 3 (cons 4 5))))
» (1 2 3 4 . 5)
(1 2 3 4 . 5) is an abbreviation for (1 . (2 . (3 . (4 . 5))))
1 2 3 4 5
Intro to Scheme 27
ListsLists ’(1 2 3 4)
» (1 2 3 4)
(1 2 3 4) is an abbreviation for (1 . (2 . (3 . (4 . ()))))
Just like a standard linked list• An empty list, ’(), is essentially a null pointer
This is often how parameters are passed, etc.
This special construct of nested dotted pairs is called a list
1 2 3 4
Intro to Scheme 28
List()List()
(list 1 2 3 4 5)
Is the same as…
(cons 1 (cons 2 (cons 3 (cons 4 cons 5 nil))))
Both produce:
(1 . (2 . (3 . (4 . (5 . ())))))
Or, as scheme would print it…
(1 2 3 4 5)
Intro to Scheme 29
car and cdrcar and cdr The car of a list is a value The cdr of a list is a list Special names: cadr, cddr, cdar, etc.
• (define x ’(1 2 3 4 5) (car x) » 1 (cdr x) » (2 3 4 5) (cadr x) » 2 (cddr x) » (3 4 5)
Intro to Scheme 30
Quote and ListsQuote and Lists ‘(item1, item2, item3, …) is
syntactic sugar for (list ‘item1 ‘item2 ‘item3 …)
‘(1 2 3 4 5) »(1 2 3 4 5) ‘(a b c d e) »(a b c d e) ‘(1 2 3 4 5) procedure application:
expected procedure, given: 1; arguments were: 2 3 4 5
Intro to Scheme 31
EquivalenceEquivalence (eq? item item) checks for object
equivalence. Are the two variables bound/pointing to the same object?
(define l '(a b c))
(eq? l '(a b c)) » #f
(define a l)
(eq? a l) » #t
(define a 3)
(eq? a 3) » #t
Intro to Scheme 32
Equivalence (2)Equivalence (2) Equal? Recursively performes eq? on each
entry in a list, etc.
Most types have their own equality operations• (char=? #\c #\b)• (= 3 3.0), etc.
(define l '(a b c))
(equal? l '(a b c)) » #t
Intro to Scheme 33
VectorsVectors Scheme’s answer to arrays are called vectors Not used as much as lists (define x (vector 1 2 3 4 5))x » #(1 2 3 4 5)
(vector-ref x 3) » 4 (vector-set! x 2 1) x » #(1 2 1 4 5)
Intro to Scheme 34
Conversion between data typesConversion between data types (char->integer #\d) » 100 (integer->char 50) » #\2 (string->list “hi!”) » (#\h #\i #\!) (number->string 23) » “23” (string->number “20”) » 20 (string->number “bob”) » #f (string->number “23” 16) » 35 (symbol->string xyz) » “xyz” (string->symbol “xyz”) » xyz
All these data types are special cases of Scheme S-expressions
Intro to Scheme 35
ProblemsProblems Draw the linked list structure that would result
from each of the following expressions:
(cons (cons (cons a b) c (cons d e)) f)
(cons (cons (cons (cons a b) c) d) ())
’(a b c (d e (f . g)))
’(1 2 3 (4 . 5) . 6)
7.1.1 Lexical structure
This section describes how individual tokens (identifiers, numbers, etc.) are formed from sequences of characters. The following sections describe how expressions and programs are formed from sequences of tokens.
<Intertoken space> may occur on either side of any token, but not within a token.
Tokens which require implicit termination (identifiers, numbers, characters, and dot) may be terminated by any <delimiter>, but not necessarily by anything else.
The following five characters are reserved for future extensions to the language: [ ] { } |
<token> --> <identifier> | <boolean> | <number> | <character> | <string> | ( | ) | #( | ' | ` | , | ,@ | .<delimiter> --> <whitespace> | ( | ) | " | ;<whitespace> --> <space or newline><comment> --> ; <all subsequent characters up to a line break><atmosphere> --> <whitespace> | <comment><intertoken space> --> <atmosphere>*
<identifier> --> <initial> <subsequent>* | <peculiar identifier><initial> --> <letter> | <special initial><letter> --> a | b | c | ... | z
<special initial> --> ! | $ | % | & | * | / | : | < | = | > | ? | ^ | _ | ~<subsequent> --> <initial> | <digit> | <special subsequent><digit> --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9<special subsequent> --> + | - | . | @<peculiar identifier> --> + | - | ...<syntactic keyword> --> <expression keyword> | else | => | define | unquote | unquote-splicing
<expression keyword> --> quote | lambda | if | set! | begin | cond | and | or | case | let | let* | letrec | do | delay | quasiquote
`<variable> => <'any <identifier> that isn't also a <syntactic keyword>>
<boolean> --> #t | #f<character> --> #\ <any character> | #\ <character name><character name> --> space | newline
<string> --> " <string element>* "<string element> --> <any character other than " or \> | \" | \\
<number> --> <num 2>| <num 8> | <num 10>| <num 16>
The following rules for <num R>, <complex R>, <real R>, <ureal R>, <uinteger R>, and <prefix R> should be replicated for R = 2, 8, 10, and 16. There are no rules for <decimal 2>, <decimal 8>, and <decimal 16>, which means that numbers containing decimal points or exponents must be in decimal radix.
<num R> --> <prefix R> <complex R><complex R> --> <real R> | <real R> @ <real R> | <real R> + <ureal R> i | <real R> - <ureal R> i | <real R> + i | <real R> - i | + <ureal R> i | - <ureal R> i | + i | - i<real R> --> <sign> <ureal R><ureal R> --> <uinteger R> | <uinteger R> / <uinteger R> | <decimal R>
<decimal 10> --> <uinteger 10> <suffix> | . <digit 10>+ #* <suffix> | <digit 10>+ . <digit 10>* #* <suffix> | <digit 10>+ #+ . #* <suffix><uinteger R> --> <digit R>+ #*<prefix R> --> <radix R> <exactness> | <exactness> <radix R>
<suffix> --> <empty> | <exponent marker> <sign> <digit 10>+<exponent marker> --> e | s | f | d | l<sign> --> <empty> | + | -<exactness> --> <empty> | #i | #e<radix 2> --> #b<radix 8> --> #o<radix 10> --> <empty> | #d<radix 16> --> #x<digit 2> --> 0 | 1<digit 8> --> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7<digit 10> --> <digit><digit 16> --> <digit 10> | a | b | c | d | e | f
7.1.2 External representations
<Datum> is what the read procedure (section see section 6.6.2 Input) successfully parses. Note that any string that parses as an <expression> will also parse as a <datum>.
<datum> --> <simple datum> | <compound datum><simple datum> --> <boolean> | <number> | <character> | <string> | <symbol><symbol> --> <identifier><compound datum> --> <list> | <vector>
<list> --> (<datum>*) | (<datum>+ . <datum>) | <abbreviation><abbreviation> --> <abbrev prefix> <datum><abbrev prefix> --> ' | ` | , | ,@<vector> --> #(<datum>*)
7.1.3 Expressions
<expression> --> <variable> | <literal> | <procedure call> | <lambda expression> | <conditional> | <assignment> | <derived expression> | <macro use> | <macro block>
<literal> --> <quotation> | <self-evaluating><self-evaluating> --> <boolean> | <number> | <character> | <string><quotation> --> '<datum> | (quote <datum>)<procedure call> --> (<operator> <operand>*)<operator> --> <expression><operand> --> <expression>
<lambda expression> --> (lambda <formals> <body>)<formals> --> (<variable>*) | <variable> | (<variable>+ . <variable>)<body> --> <definition>* <sequence><sequence> --> <command>* <expression><command> --> <expression>
<conditional> --> (if <test> <consequent> <alternate>)<test> --> <expression><consequent> --> <expression><alternate> --> <expression> | <empty>
<assignment> --> (set! <variable> <expression>)
<derived expression> --> (cond <cond clause>+) | (cond <cond clause>* (else <sequence>)) | (case <expression> <case clause>+) | (case <expression> <case clause>* (else <sequence>)) | (and <test>*) | (or <test>*) | (let (<binding spec>*) <body>) | (let <variable> (<binding spec>*) <body>) | (let* (<binding spec>*) <body>) | (letrec (<binding spec>*) <body>) | (begin <sequence>) | (do (<iteration spec>*) (<test> <do result>) <command>*) | (delay <expression>) | <quasiquotation>
<cond clause> --> (<test> <sequence>) | (<test>) | (<test> => <recipient>)<recipient> --> <expression><case clause> --> ((<datum>*) <sequence>)<binding spec> --> (<variable> <expression>)<iteration spec> --> (<variable> <init> <step>)
| (<variable> <init>)<init> --> <expression><step> --> <expression><do result> --> <sequence> | <empty>
<macro use> --> (<keyword> <datum>*)<keyword> --> <identifier>
<macro block> --> (let-syntax (<syntax spec>*) <body>) | (letrec-syntax (<syntax spec>*) <body>)<syntax spec> --> (<keyword> <transformer spec>)
7.1.4 Quasiquotations
The following grammar for quasiquote expressions is not context-free. It is presented as a recipe for generating an infinite number of production rules. Imagine a copy of the following rules for D = 1, 2,3, .... D keeps track of the nesting depth.
<quasiquotation> --> <quasiquotation 1><qq template 0> --> <expression><quasiquotation D> --> `<qq template D> | (quasiquote <qq template D>)<qq template D> --> <simple datum> | <list qq template D> | <vector qq template D> | <unquotation D><list qq template D> --> (<qq template or splice D>*) | (<qq template or splice D>+ . <qq template D>) | '<qq template D> | <quasiquotation D+1>
<vector qq template D> --> #(<qq template or splice D>*)<unquotation D> --> ,<qq template D-1> | (unquote <qq template D-1>)<qq template or splice D> --> <qq template D> | <splicing unquotation D><splicing unquotation D> --> ,@<qq template D-1> | (unquote-splicing <qq template D-1>)
In <quasiquotation>s, a <list qq template D> can sometimes be confused with either an <unquotation D> or a <splicing unquotation D>. The interpretation as an <unquotation> or <splicing unquotation D> takes precedence.
7.1.5 Transformers
<transformer spec> --> (syntax-rules (<identifier>*) <syntax rule>*)<syntax rule> --> (<pattern> <template>)<pattern> --> <pattern identifier> | (<pattern>*) | (<pattern>+ . <pattern>) | (<pattern>* <pattern> <ellipsis>) | #(<pattern>*) | #(<pattern>* <pattern> <ellipsis>) | <pattern datum><pattern datum> --> <string> | <character> | <boolean> | <number><template> --> <pattern identifier> | (<template element>*) | (<template element>+ . <template>) | #(<template element>*) | <template datum><template element> --> <template> | <template> <ellipsis>
<template datum> --> <pattern datum><pattern identifier> --> <any identifier except `...'><ellipsis> --> <the identifier `...'>
7.1.6 Programs and definitions
<program> --> <command or definition>*<command or definition> --> <command> | <definition> | <syntax definition> | (begin <command or definition>+)<definition> --> (define <variable> <expression>) | (define (<variable> <def formals>) <body>) | (begin <definition>*)<def formals> --> <variable>* | <variable>* . <variable><syntax definition> --> (define-syntax <keyword> <transformer spec>)