440 likes | 574 Vues
CS 480/680 – Comparative Languages. Introduction to Scheme. “And now for something completely different…†– Monty Python. Functional Languages. Scheme is a functional language. It belongs to a class of languages that differ from imperative languages in a number of ways:
E N D
CS 480/680 – Comparative Languages Introduction to Scheme “And now for something completely different…” – Monty Python
Functional 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
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
Forms 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
Substitution Model The basic rule: To evaluate a Scheme expression: • Evaluate its operands • Evaluate the operator • Apply the operator to the evaluated operands Intro to Scheme
Warning!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
Example expression eval • Example: (+ 3 (* 4 5) ) Intro to Scheme
operator Example expression eval • Example: (+3 (* 4 5) ) Intro to Scheme
operator operand 1 Example expression eval • Example: (+3 (* 4 5) ) Intro to Scheme
operator operand 1 operand 2 Example expression eval • Example: (+3 (* 4 5)) Intro to Scheme
Example 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
Primitive 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
Another 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
Evaluation with variables • An assignment provides an association between a symbol (variable) and its value (definex 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
Variable evaluation example • (definex 3) • Then evaluate x • look up value of x • x has value 3 (due to define) • result: 3 Intro to Scheme
Simple 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
Special forms • N.B. There are a few special formswhich do not evaluate in the way we’ve described. • define is one of them (definex 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
Special forms • Another example: (definex (+ 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
Basic 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
More types • Procedures (lambda) • Booleans (#t and #f) Intro to Scheme
Symbols • 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
Arbitrary 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
1 2 Dotted 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) Intro to Scheme
car 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
3 1 4 2 Dotted 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) Intro to Scheme
Scheme 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
Lists • ’(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
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
car 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
Quote 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
Equivalence • (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
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
Vectors • 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
Conversion 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
Problems • 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) Intro to Scheme
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>)