functional programming
DESCRIPTION
Functional Programming. Universitatea Politehnica Bucuresti 2007-2008 Adina Magda Florea http://turing.cs.pub.ro/fp_08. Lecture No. 2. S-expressions Data types Defining variables and procedures Special forms Local variables Control constructs Objects and pointers. 1. S-expressions. - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/1.jpg)
Functional ProgrammingFunctional Programming
Universitatea Politehnica Bucuresti2007-2008
Adina Magda Florea
http://turing.cs.pub.ro/fp_08
![Page 2: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/2.jpg)
Lecture No. 2
S-expressions Data types Defining variables and procedures Special forms Local variables Control constructs Objects and pointers
![Page 3: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/3.jpg)
1. S-expressions
In Scheme, there's no distinction between expressions and statements
They're all "expressions" – s-expressions Scheme expressions combine the features of
expressions and statements. S-expressions return values However, they can also have side effects
![Page 4: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/4.jpg)
2. Data types in Scheme Simple types: booleans, numbers, characters, and
symbolsBooleans #t for true and #f or () for false boolean? - checks if its argument is booleanNumbers integers (eg, 42), rationals (22/7), reals (3.1416), or
complex (2+3i) Predicates: number? complex? real? rational? integer? eqv? =, <, <=, >, >= self-evaluating
![Page 5: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/5.jpg)
Simple types: Characters
Characters Character data - represented by prefixing the character with #\
char?
(char? #\c) => #t(char? 1) => #f(char? #\;) => #t
char=?, char<?, char<=?, char>?, char>=?
(char=? #\a #\a) => #t(char<? #\a #\b) => #t(char>=? #\a #\b) => #f To make the comparisons case-insensitive, use char-ci (=?...)
self-evaluating
![Page 6: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/6.jpg)
Simple types: Symbols
Symbols(symbol? 'xyz) => #t(symbol? 42) => #f (eqv? 'Calorie 'calorie) => #t (define xyz 9) xyz => 9 We can use the form set! (pronounced "set-bang") to
change the value held by a variable:(set! xyz #\c) xyz => #\c
- are identifiers- are evaluated(unless quote is used)
mutation procedure
Note on type
You should not use assignments a lot in Scheme programs.It's usually a sign of bad style
![Page 7: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/7.jpg)
Structured types: Strings
Strings"Hello, World!" => "Hello, World!"
(string #\h #\e #\l #\l #\o) => "hello"
(define greeting "Hello; Hello!")
(string-ref greeting 0) => #\H New strings can be created by appending other
strings:(string-append "E " "Pluribus " "Unum") => "E
Pluribus Unum"
![Page 8: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/8.jpg)
Structured types: Strings
Make a string of a specified length, and fill it with the desired characters later.
(define a-3-char-long-string (make-string 3)) string? Strings obtained as a result of calls to string,
make-string, and string-append are mutable.(define hello (string #\H #\e #\l #\l #\o))
hello => "Hello"
(string-set! hello 1 #\a) hello => "Hallo"
![Page 9: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/9.jpg)
Structured types: Vectors
Vectors(vector 0 1 2 3 4) => #(0 1 2 3 4)(define v (make-vector 5))(set! v #(1 2 3 4 6))v => #5(1 2 3 4 6)(vector? #(1 2 3)) => #t(vector-ref #(1 2 3) 0) => 1(vector-ref #(1 2 3) 3) =>
vector-ref: index 3 out of range [0, 2] for vector: #3(1 2 3)
(vector-set! v 1 10)v => #5(1 10 3 4 6)
![Page 10: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/10.jpg)
Structured types: Dotted pairs A dotted pair is a compound value made by
combining any two arbitrary values into an ordered couple.
(cons 1 #t) => (1 . #t)(define x (cons 1 #t))(car x) => 1(cdr x) => #t(set-car! x 2)(set-cdr! x #f)x => (2 . #f)(define y (cons (cons 1 2) 3))y => ((1 . 2) . 3)
(car (car y)) => 1(cdr (car y)) => 2(caar y) => 1(cdar y) => 2
![Page 11: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/11.jpg)
Structured types: Lists The abbreviation for a dotted pair of the form
(1 . (2 . (3 . (4 . ())))) is (1 2 3 4) This special kind of nested dotted pair is called a
list (cons 1 (cons 2 (cons 3 (cons 4 '()))))(list 1 2 3 4) => (1 2 3 4)(define y (list 1 2 3 4))(list-ref y 0) => 1(list-ref y 3) => 4(list-tail y 1) => (2 3 4)(list-tail y 3) => (4)
![Page 12: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/12.jpg)
Structured types: Lists The predicates pair?, list?, and null? check if their
argument is a dotted pair, list, or the empty list, (pair? '(1 . 2)) => #t(pair? '(1 2)) => #t(pair? '()) => #f(list? '()) => #t(null? '()) => #t(list? '(1 2)) => #t(list? '(1 . 2)) => #f(null? '(1 2)) => #f(null? '(1 . 2)) => #f
![Page 13: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/13.jpg)
Structured types: Lists List of pairs:
car field hold the pointers to the object
cdr field link the pairs together into a "spine."
A list is really just a sequence of pairs, ending with a null pointer.
A null pointer is a list, too - it's a sequence of zero pairs ending in a null pointer.
An object can easily be in many lists at once, because a list is really just a spine of pairs that holds pointers to the items in the list.
pairfoo
pair pair
22 13 15
pairbar
pair
![Page 14: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/14.jpg)
Lists and quote quote takes exactly one argument, and
returns a data structure whose printed representation is the same as what you typed in as the argument to quote.
Scheme does not evaluate the argument to quote as an expression - it just gives you a pointer to a data structure.
For example, the expression(define foo (quote (1 2 3)))defines (and binds) a variable foo, and initializes
its binding with (a pointer to) a three-element list.
![Page 15: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/15.jpg)
Lists and quote
(define (foo) '(1 2 3)) The list (1 2 3) may be created when we
define the procedure foo, and each time we call it, it may return a pointer to that same list.
For this reason, it's an error to modify a data structure returned from a quote form.
If we want the procedure foo to return a new list (1 2 3) every time, we can write
(define (foo) (list 1 2 3))
![Page 16: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/16.jpg)
Some list procedureslength(define (my-length lis) (cond ((null? lis) 0) (else (+ 1 (my-length (cdr lis))))))
append(define (my-append lis1 lis2) (cond ((null? lis1) lis2) (else (cons (car lis1) (my-append (cdr lis1) lis2)))))
(my-append '(a b c) '(x y)) => (a b c x y)(my-append '((a b) c (d e)) '(x (y z) t)) => ((a b) c (d e) x (y z) t)
![Page 17: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/17.jpg)
Some list procedures append concatenates the lists it is given. It only concatenates the top-level structure, however - it
doesn't "flatten" nested structures. append doesn't modify any of its arguments, but the
result of append generally shares structure with the last list it's given.
It effectively conses the elements of the other lists onto the last list to create the result list.
It's therefore dangerous to make a "new" list with append and then modify the "old" list.
This is one of the reasons side effects are discouraged in Scheme.
![Page 18: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/18.jpg)
Some list proceduresCopying lists
There are two common senses of copying, shallow copying, and deep copying.
Shallow copy
(define (pair-copy pr)
(cons (car pr) (cdr pr)))
![Page 19: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/19.jpg)
Some list proceduresCopying lists
Deep copy
(define (pair-tree-deep-copy thing)
(if (not (pair? thing))
thing
(cons (pair-tree-deep-copy (car thing))
(pair-tree-deep-copy (cdr thing)))))
![Page 20: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/20.jpg)
Some list proceduresCopying lists
(define (list-copy lis)
(cond ((null? lis) '())
(else (cons (car lis) (list-copy (cdr lis))))
![Page 21: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/21.jpg)
Structured types: Procedures
Primitives and procedures The variable denoting a Scheme primitive or a
defined procedure holds that procedure
cons => #<primitive:cons>
car => #<primitive:car>
list-sum => #<procedure:list-sum> When you write a procedure that modifies its
arguments, rather than just returning a value, it's good style to give it a name that ends with !
e.g. reverse vs reverse!
![Page 22: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/22.jpg)
Non-distructive reverse
(define (my-reverse lis)
(cond ((null? lis) ())
(else
(append (my-reverse (cdr lis))
(list (car lis))))))
(define m '(a b c))
(my-reverse m) => (c b a)
m => (a b c)
![Page 23: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/23.jpg)
Distructive reverse; returns the last element of a list; to be used in my-reverse!(define (all-but-last lis) (cond ((null? lis) ()) ((null? (cdr lis)) ()) (else (cons (car lis) (all-but-last (cdr lis))))))
;my-reverse! distroys the initial list by reversing it(define (my-reverse! lis) (let ((l ()) (len (length lis))) (cond ((null? lis) ()) (else (set! l (list-ref lis (- len 1)))
(set-cdr! lis (my-reverse! (all-but-last lis))) (set-car! lis l) lis))))
(all-but-last '(a b c)) => (a b)(define m '(a b c))(my-reverse! m) => (c b a)m => (c b a)
![Page 24: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/24.jpg)
Mind that …; my-rev! seems to destroy the initial list but in fact it does not(define (my-rev! lis) (cond ((null? lis) ()) (else (set! lis (append (my-rev! (cdr lis))
(list (car lis)))) lis)))
(define m '(a b c))(my-rev! m) => (c b a)m => (a b c)
![Page 25: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/25.jpg)
Ports
Yet another data type is the port. A port is the conduit through which input
and output is performed. Ports are usually associated with files and
consoles.
![Page 26: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/26.jpg)
3. Defining variables and procedures
Defining a variable : (define my-variable 5) - tells Scheme to allocate
space for my-variable, and initialize that storage with the value 5. In Scheme, you always give a variable an initial value, so
there's no such thing as an uninitialized variable or an unininitialized variable error.
Scheme values are always pointers to objects e.g., when we use the literal 5, Scheme interprets that as
meaning a pointer to the object 5. Numbers are objects you can have pointers to, just
like any other kind of data structure.
![Page 27: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/27.jpg)
Defining variables
The define expression does three things: It declares to Scheme that we're going to have a
variable named foo in the current scope. It tells Scheme to actually allocate storage for the
variable. The storage is called a binding. It tells Scheme what initial value to put in the
storage. You can not use set! on a variable that has
not been defined
![Page 28: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/28.jpg)
Defining procedures
Defining a procedure: Use the special form lambda to defined an
un-named procedure(lambda (x) (+ x 2)) ((lambda (x) (+ x 2)) 5) => 7
Named procedures: use a variable to hold the procedure value:(define add2 (lambda (x) (+ x 2)))(add2 4) => 6(add2 9) => 11
![Page 29: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/29.jpg)
Defining procedures
Defining a procedure: Or just use define and indicate name and parameters (define (two-times x) (+ x x)) When you define a procedure, you're really defining
a variable whose value happens to be a (pointer to a) procedure.
You can define a procedure with 0 parameters (define (foo) 15) Mind the difference (define foo 15)
![Page 30: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/30.jpg)
Defining procedures
Variable number of arguments: Some procedures can be called at different times with
different numbers of arguments. To do this, the lambda parameter list is replaced by a single
symbol. This symbol acts as a variable that is bound to the list of the
arguments that the procedure is called on. The lambda parameter list can be:
a list of the form (x ...) a symbol a dotted pair of the form (x ... . z); in the dotted-pair case, all the
variables before the dot are bound to the corresponding arguments in the procedure call, with the single variable after the dot picking up all the remaining arguments as one list.
![Page 31: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/31.jpg)
4. Special forms
Special forms: A kind of procedure but behaves differently Procedure calls and special forms are syntactically
similar but semantically different Examples:
set! - isn't a procedure, because its first argument is not really an expression to be evaluated in the normal way, to get a value to pass as an argument. It's the name of a place to put a value
define treats its first argument specially--the name of a variable or procedure isn't an expression that is evaluated and passed to define - it's just a name, and you're telling define to allocate some storage and use that name for it.
![Page 32: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/32.jpg)
Special forms
Other special forms we'll see include control constructs: if, cond, and case, etc., and
logical operators and and or; forms for defining local variables: let and its
variants letrec and let*; looping constructs: named let and do; quote, which let you write complex data
structures as textual literals in your code, and lambda, which creates new procedures
![Page 33: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/33.jpg)
5. Local variables
forms for defining local variables: let and its variants letrec and let*;
![Page 34: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/34.jpg)
6. Control constructs
control constructs: if, cond, and case, etc., and logical operators and and or;
![Page 35: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/35.jpg)
7. Objects and pointers
Conceptually, all Scheme objects are allocated on the heap, and referred to via pointers.
A procedure takes pointers to the arguments and returns a pointer to the value computer and returned by the procedure
This makes things simpler
![Page 36: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/36.jpg)
Objects and pointers
• An implementation is free to optimize away the pointers if it doesn't affect the programmer's view of things
• Most implementations actually do this
![Page 37: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/37.jpg)
Objects and pointers
• Objects on the heap
![Page 38: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/38.jpg)
Objects and pointers
• Reclaiming the memory
![Page 39: Functional Programming](https://reader036.vdocuments.site/reader036/viewer/2022062315/568151cd550346895dc008b9/html5/thumbnails/39.jpg)
Objects and pointers
• Dymanic typing