Functional Programming Universitatea Politehnica Bucuresti 2007-2008 Adina Magda Florea

Slides:



Advertisements
Similar presentations
1 Scheme and Functional Programming Aaron Bloomfield CS 415 Fall 2005.
Advertisements

Lists in Lisp and Scheme a. Lists are Lisp’s fundamental data structures, but there are others – Arrays, characters, strings, etc. – Common Lisp has moved.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Chapter 3 Functional Programming. Outline Introduction to functional programming Scheme: an untyped functional programming language.
CS 355 – PROGRAMMING LANGUAGES Dr. X. Apply-to-all A functional form that takes a single function as a parameter and yields a list of values obtained.
Lisp – Introduction יעל נצר מערכות נבונות סמסטר ב' תשס"ו.
Lisp. Versions of LISP Lisp is an old language with many variants –LISP is an acronym for List Processing language Lisp is alive and well today Most modern.
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
Catriel Beeri Pls/Winter 2004/5 environment 68  Some details of implementation As part of / extension of type-checking: Each declaration d(x) associated.
The environment of the computation Declarations introduce names that denote entities. At execution-time, entities are bound to values or to locations:
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
SchemeCOP Introduction to Scheme. SchemeCOP Scheme Meta-language for coding interpreters –“ clean ” semantics Scheme = LISP + ALGOL –simple.
SCHEME By: Krista and Brett. What is Scheme? Best known for its functional style of programming One of two main dialects of Lisp Developed in 1975 –MIT.
CS 152: Programming Language Paradigms February 24 Class Meeting Department of Computer Science San Jose State University Spring 2014 Instructor: Ron Mak.
Slide 1 Vitaly Shmatikov CS 345 Introduction to Scheme.
Functional Programming Universitatea Politehnica Bucuresti Adina Magda Florea
1 Lists in Lisp and Scheme. 2 Lists are Lisp’s fundamental data structures. Lists are Lisp’s fundamental data structures. However, it is not the only.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
Introduction to Scheme Lectures on The Scheme Programming Language, 2 nd Ed. R. Kent Dybvig.
Introduction to Scheme CS 480/680 – Comparative Languages “And now for something completely different…” – Monty Python “And now for something completely.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
Basic Semantics Associating meaning with language entities.
Functional Programming Universitatea Politehnica Bucuresti Adina Magda Florea
Objects & Dynamic Dispatch CSE 413 Autumn Plan We’ve learned a great deal about functional and object-oriented programming Now,  Look at semantics.
Functional Programming Universitatea Politehnica Bucuresti Adina Magda Florea
CS220 Programming Principles 프로그래밍의 이해 2002 가을학기 Class 6 한 태숙.
CS535 Programming Languages Chapter - 10 Functional Programming With Lists.
Variables, Environments and Closures. Overview Touch on the notions of variable extent and scope Introduce the notions of lexical scope and dynamic.
Fall 2008Programming Development Techniques 1 Topic 17 Assignment, Local State, and the Environment Model of Evaluation Section 3.1 & 3.2.
1 Scheme (Section 11.2) CSCI 431 Programming Languages Fall 2003.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
Ch Ch jcmt CSE 3302 Programming Languages CSE3302 Programming Languages (n-n-n-notes) Summer 2003 Dr. Carter Tiernan.
Artificial Intelligence and Lisp Lecture 6 LiU Course TDDC65 Autumn Semester,
Functional Programming
CS314 – Section 5 Recitation 9
Abstract Syntax cs7100 (Prasad) L7AST.
CS314 – Section 5 Recitation 10
Data Types In Text: Chapter 6.
Edited by Original material by Eric Grimson
CS 326 Programming Languages, Concepts and Implementation
6.001 SICP Variations on a Scheme
6.001 SICP Object Oriented Programming
Introduction to Scheme
Variables, Environments and Closures
September 4, 1997 Programming Languages (CS 550) Lecture 6 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts.
Data Structures Interview / VIVA Questions and Answers
Lists in Lisp and Scheme
Env. Model Implementation
Variables, Environments and Closures
Lecture 15 (Notes by P. N. Hilfinger and R. Bodik)
The Metacircular Evaluator
FP Foundations, Scheme In Text: Chapter 14.
Dynamic Scoping Lazy Evaluation
The Metacircular Evaluator
Closure Closure binds a first-class function and a lexical environment together This is a complex topic, so we will build up our understanding of it we.
Bindings, Scope, and Extent
The Metacircular Evaluator (Continued)
6.001 SICP Further Variations on a Scheme
Explicit Application of Procedures, and Explicit Evaluation
Lecture #9 מבוא מורחב.
Abstract Syntax cs7100 (Prasad) L7AST.
6.001 SICP Variations on a Scheme
Announcements Quiz 5 HW6 due October 23
6.001 SICP Interpretation Parts of an interpreter
topics interpreters meta-linguistic abstraction eval and apply
CSC 533: Organization of Programming Languages Spring 2005
Lisp.
More Scheme CS 331.
Lists in Lisp and Scheme
Presentation transcript:

Functional Programming Universitatea Politehnica Bucuresti Adina Magda Florea

Lecture No. 3 Objects and pointers Objects on the heap Reclaiming the memory Dynamic typing Lexical scope Procedures

1. Objects and pointers Variables allocated statically (as in the case of global variables) on an activation stack as part of a procedure activation record (as in the case of local variables) dynamically allocated on the heap at run time using an allocation routine (like malloc or new in other pl)

2. Objects on the heap 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 computed and returned by the procedure Procedures always dereference a pointer to a value when they really use the value - you never have to explicitly force the dereferencing.

Objects on the heap (+ 2 3) 5 Most Scheme implementations optimize a lot of pointers. Tagging - the value in each variable actually has a few bits devoted to a type tag

Objects on the heap Numbers - you can't change the state of the object itself. There's no way to side-effect an integer object and make it behave differently. We say that integers are immutable, i.e., you can't mutate (change) them. If integers were actually allocated on the heap and referred to via pointers, and if you could change the integer's value, then that change would be visible through other pointers to the integer.

Objects on the heap Most Scheme objects only have fields that are general-purpose value cells Any field can hold any Scheme value, whether it's a tagged immediate value or a tagged pointer to another heap-allocated object. In most implementations, each heap- allocated object has a hidden "header" field

Objects on the heap Cons cell (pair) (define foo (cons 15 22)) set-car!, set-crd! header pair-id car cdr foo 22 15

3. Reclaiming the memory The Scheme heap is garbage collected The collector will never take back any object that your program holds a pointer to, or might reach via any path of pointer traversals The use of garbage collection supports the abstraction of indefinite extent. All objects conceptually live forever, or at least as long as they might matter to the program. From the point of view of a running program, memory is infinite - it can keep allocating objects indefinitely, without ever reusing their space.

4. Dynamic typing In Scheme, all variables have the same type: "pointer to anything." Scheme is dynamically typed Variables don't have fixed types, but objects do. An object carries its type around with it The language provides type-checking at run time to ensure that you don't perform the wrong operations on objects In dynamically typed systems, types are enforced at runtime.

5. Lexical scope Scheme is a block-structured language with nested scopes. Scheme uses a lexical scope rule. Scheme is statically scoped, rather than dynamically scoped, like Lisp. If nested lets define variables by the same name, then the uses of that name in the body of the inner let will refer to the bindings created by the inner let.

Lexical scope (let ((x 10) ; outer binding of x (a 20)) ; binding of a (foo x) (let ((x (bar)) ; inner binding of x (b (baz x x))) ; binding of b (quux x a) (quux y b)) (baz x a) ; refers to outer x (and a) (baz x b)) ; illegal? inner let variable x shadows the outer one

Lexical scope The set of all bindings that are visible at a given point during program execution is called a binding environment. Top-level binding environment - hash table With local variables, a simple "flat" table isn't sufficient. Each binding contruct introduces a new binding contour - it changes the "shape" of the environment.

Lexical scope At any given point, the environment consists of all of the variable bindings that are visible. This includes all of the bindings in the table for the innermost contour, and all of the bindings in the table for the contours it's nested inside, except those that are shadowed by inner bindings of the same names.

Lexical scope (let ((x 10) (a 20)) (foo x) (let ((x (bar)) (b (baz x x))) (quux x a) (quux y b)) (baz x a) (baz x b)) scope of inner x and b scope of outer x and a

Lexical scope (let ((a-structure (some-procedure))) (let ((a-substructure (get-some-subpart a-structure))) (let ((a-subsubstructure (get-another-subpart a-substructure))) (foo a-substructure)))) (let ((a-structure (some-procedure)) (a-substructure (get-some-subpart a-structure)) (a-subsubstructure (get-another-subpart a-substructure))) (foo a-substructure)) (let* ((a-structure (some-procedure)) (a-substructure (get-some-subpart a-structure)) (a-subsubstructure (get-another-subpart a-substructure))) (foo a-substructure)) scope of all three variables

6. Procedures Scheme procedures are "first class," meaning that they're objects in the language. They can be anonymous, meaning that you can have pointers to procedures that don't have printed names. They can be higher-order, meaning that procedures can operate on procedures.

6.1 Procedures - first-class objects Procedures "first class" objects = you can pass a procedure value as an argument to a procedure, return it as the value of a procedure call, store it in a variable or a field of another object. A procedure pointer is just a value that you can pass around like any other value, like a pair or a boolean.

Procedures - first-class objects A procedure call expression is called a combination. Evaluation of a combination includes evaluation of the argument expressions and application of the procedure to the arguments. Scheme uses a unified namespace = there's only one kind of name for both normal variables and procedures In fact, procedure names are really just variable names, and there's only one kind of variable. A named procedure is really just a first-class procedure object that happens to be referenced from a variable.

Procedures - first-class objects (define (min a b) (if (< a b) a b)) (min 3 5) => 3 (define min +) (min 3 5) => 8

6.2 Lambda expressions (define (double x) (+ x x)) is exactly equivalent to (define double (lambda (x) (+ x x))) In either case, we're creating a one-argument procedure, and we're also defining and binding a variable named double, and initializing its storage with a pointer to the procedure. The procedure-defining syntax for define is just syntactic sugar--there's nothing you can do with it that you can't do with local variables and lambda.

Lambda exp and lexical scope Lambda creates a procedure that will execute in the scope where the lambda expression was evaluated. Except for local variables of the procedure itself, including its arguments, names in the body of the procedure refer to whatever they refer to at the point where the procedure is created by lambda. This is necessary for preserving lexical scope Lambda creates a closure, a procedure whose free variable references are "fixed" at the time the procedure is created. Whenever the procedure references a free variable, it will refer to the bindings of those variables in the environment where the procedure was created.

Lambda exp and lexical scope (define foo 1) (define (baz) foo) (define (quux) (let ((foo 6)) (baz))) (quux) The procedure baz returns to the environment where it was created before it executes, and even before it binds its arguments – lexical scope LISP – dynamic scope

Lambda exp for local definitions of procedures Scheme lets you define local procedures, scoped inside other procedures or blocks with local variables. You can define local procedures using let and lambda (define (quadruple x) (let ((double (lambda (x) (+ x x)))) (double (double x))))

Local definitions (define (quadruple x) (let ((double (lambda (x) (+ x x)))) (double (double x)))) (define (quadruple x) (define (double x) ; define a local procedure double (+ x x)))) (double (double x)))) ; nested calls to the local procedure There's a restriction on internal defines They must be at the beginning of the procedure body - or the beginning of another body, like a let body, before the normal executable expressions in the body.

Local definitions Local procedure definitions follow the normal lexical scope rule, like nested lets. (define (quadruple x) (define (double x) ; define a local procedure double (+ x x)))) (double (double x)))) ; nested calls to the local procedure scope of x scope of double

Recursive local definitions (define (foo x) (let ((local-proc (lambda (y)... (local-proc...) ; recursive call? No....)))... (local-proc x)...) scope of y scope of local-proc local variable local-proc isn't visible to the lambda expression

Recursive local definitions (define (foo x) (letrec ((local-proc (lambda (y)... (local-proc...) ; recursive call? Yes....)))... (local-proc x)...) scope of y scope of local-proc

High-order procedures Scheme is designed to make it easy to use higher-order procedures i.e., procedures that may take other procedures as arguments or return them as values. (sort (2 3 5). (sort > '(5 2 3)) => (5 3 2) (sort string<? '("foo" "bar" "baz" "quux")) => ("bar" "baz" "foo" "quux")

High-order procedures - map (map proc list1 list2...) (map cadr '((a b) (d e) (g h))) => (b e h) (map (lambda (x) (+ x 1)) '(1 2 3)) => (2 3 4) (map (lambda (n) (expt n n)) '( )) => ( ) (map + '(1 2 3) '(4 5 6)) => (5 7 9)

High-order procedures - map (define (map1 proc lis) (cond ((null? lis) '()) ((pair? lis) (cons (proc (car lis)) (map proc (cdr lis)))))) (map1 (lambda (x) (+ x 1)) '(1 2 3)) => (2 3 4)

High-order procedures - map (define (first-name name) (car name)) (define (first-name-list name-lis) (cond ((null? name-lis) ()) (else (cons (caar name-lis) (first-name-list (cdr name-lis)))))) (first-name '(maria petrescu)) => maria (first-name-list '((maria petrescu) (gigel popescu) (john smith))) => (maria gigel john) (map first-name '((maria petrescu) (gigel popescu) (john smith))) => (maria gigel john)

High-order procedures – for-each (for-each proc list1 list2...) (let ((v (make-vector 5))) (for-each (lambda (i) (vector-set! v i (* i i))) '( )) v) => #5( ) (for-each (lambda (x) (+ x 1)) '(1 2 3)) =>

High-order procedures – for-each (define (for-each1 proc lis) (cond ((null? (cdr lis)) ; one-element list? (proc (car lis))) (else (proc (car lis)) (for-each1 proc (cdr lis))))) (for-each1 (lambda (x) (+ x 1)) '(1 2 3)) => 4

High-order procedures ;;; insert: given an ordering predicate, construct a procedure that ;;; adds a given value to a given ordered list, returning the new list ;;; (also ordered) ;;; Given: ;;; MAY-PRECEDE?, a binary predicate ;;; Result: ;;; INSERTER, a binary procedure ;;; Precondition: ;;; MAY-PRECEDE? expresses an ordering relation (that is, it is connected ;;; and transitive). ;;; Postcondition: ;;; Given any value NEW-ELEMENT that meets any precondition that ;;; MAY-PRECEDE? imposes on its first argument, and any list LS of values ;;; that meet the preconditions that MAY-PRECEDE? imposes on either of ;;; its arguments and moreover are ordered within LS by MAY-PRECEDE?, ;;; INSERTER returns a list, also ordered by MAY-PRECEDE?, containing all ;;; of the elements of LS and in addition NEW-ELEMENT.

High-order procedures (define insert (lambda (may-precede?) (letrec ((inserter (lambda (new-element ls) (cond ((null? ls) (list new-element)) ((may-precede? new-element (car ls)) (cons new-element ls)) (else (cons (car ls) (inserter new-element (cdr ls)))))))) inserter))) ((insert (1 2 3) ((insert >) 2 '(3 1)) => (3 2 1) ((insert string ("aa" "bb" "mm" "xx")

High-order procedures – returning functions Have a procedure that can create procedures of some general type, producing a specialized procedure each time it's called. Parenthesis (eqv? obj1 obj2) Compares two values to see if they refer to the same object Returns #t if obj1 and obj2 should normally be regarded as the same object. The eqv? procedure returns #t if: obj1 and obj2 are both #t or both #f. obj1 and obj2 are both symbols and (string=? (symbol->string obj1) (symbol->string obj2)) => #t

High-order procedures – returning functions Parenthesis (equal? obj1 obj2) does a deep, element-by-element structural comparison (eq? obj1 obj2) Eq? is similar to eqv? except that in some cases it is capable of discerning distinctions finer than those detectable by eqv?. Eq? and eqv? are guaranteed to have the same behavior on symbols, booleans, the empty list, pairs, procedures, and non- empty strings and vectors. Eq?'s behavior on numbers and characters is implementation- dependent, but it will always return either true or false, and will return true only when eqv? would also return true. Eq? may also behave differently from eqv? on empty vectors and empty strings.

High-order procedures – returning functions (define (make-mem-proc pred?) (letrec ((mem-proc (lambda (thing lis) (if (null? lis) #f (if (pred? (car lis) thing) lis (mem-proc thing (cdr lis))))))) mem-proc)) (define member1 (make-mem-proc equal?)) (define memq1 (make-mem-proc eq?)) (define memv1 (make-mem-proc eqv?)) (member1 1 '(1 2 3)) => (1 2 3) (member1 '2 '(1 2 3)) => (2 3)

High-order procedures – returning functions (memq 'a '(a b c)) => (a b c) (memq 'b '(a b c)) => (b c) (memq 'a '(b c d)) => #f (memq (list 'a) '(b (a) c)) => #f (member (list 'a) '(b (a) c)) => ((a) c) (memq 101 '( )) => unspecified (memv 101 '( )) => ( )