Functional Programming Universitatea Politehnica Bucuresti 2008-2009 Adina Magda Florea

Slides:



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

Variables, Environments and Closures. Overview We will Touch on the notions of variable extent and scope Introduce the notions of lexical scope and.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Winter 2013.
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.
Chapter 8 Runtime Support. How program structures are implemented in a computer memory? The evolution of programming language design has led to the creation.
1 Functional programming Languages And a brief introduction to Lisp and Scheme.
Lifetime “The lifetime of a variable is the time during which the variable is bound to a specific memory location.” [p. 219] “…the lifetime of a variable.
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
Honors Compilers Addressing of Local Variables Mar 19 th, 2002.
Variables Six properties: Binding times of properties:
Run time vs. Compile time
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:
Chapter 9: Subprogram Control
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.
Building An Interpreter After having done all of the analysis, it’s possible to run the program directly rather than compile it … and it may be worth it.
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.
Chapter TwelveModern Programming Languages1 Memory Locations For Variables.
CS3012: Formal Languages and Compilers The Runtime Environment After the analysis phases are complete, the compiler must generate executable code. The.
CS 152: Programming Language Paradigms February 24 Class Meeting Department of Computer Science San Jose State University Spring 2014 Instructor: Ron Mak.
Runtime Environments Compiler Construction Chapter 7.
Bindings and scope  Bindings and environments  Scope and block structure  Declarations Programming Languages 3 © 2012 David A Watt, University.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
Compiler Construction
10/16/2015IT 3271 All about binding n Variables are bound (dynamically) to values n values must be stored somewhere in the memory. Memory Locations for.
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
CS 326 Programming Languages, Concepts and Implementation Instructor: Mircea Nicolescu Lecture 8.
1 Records Record aggregate of data elements –Possibly heterogeneous –Elements/slots are identified by names –Elements in same fixed order in all records.
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
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.
CSE 413 Languages & Implementation Hal Perkins Autumn 2012 Structs, Implementing Languages (credits: Dan Grossman, CSE 341) 1.
Scheme Profs Tim Sheard and Andrew Black CS 311 Computational Structures.
Programming Languages: Design, Specification, and Implementation G Rob Strom September 21, 2006.
Fall 2008Programming Development Techniques 1 Topic 17 Assignment, Local State, and the Environment Model of Evaluation Section 3.1 & 3.2.
Scope: What’s in a Name? CMSC Introduction to Computer Programming October 16, 2002.
1 Scheme (Section 11.2) CSCI 431 Programming Languages Fall 2003.
Cs3180 (Prasad)L156HOF1 Higher-Order Functions. cs3180 (Prasad)L156HOF2 Equivalent Notations (define (f x y) (… body …)) = (define f (lambda (x y) (…
Prof. Necula CS 164 Lecture 171 Operational Semantics of Cool ICOM 4029 Lecture 10.
CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures Dan Grossman Winter 2013.
Functional Programming Universitatea Politehnica Bucuresti Adina Magda Florea
Code Generation Instruction Selection Higher level instruction -> Low level instruction Register Allocation Which register to assign to hold which items?
CS314 – Section 5 Recitation 9
Advanced Programming in C
Data Types In Text: Chapter 6.
6.001 SICP Object Oriented Programming
The interpreter.
Introduction to Scheme
Variables, Environments and Closures
The Environment Model*
Variables, Environments and Closures
Lecture 15 (Notes by P. N. Hilfinger and R. Bodik)
The Metacircular Evaluator
Dynamic Scoping Lazy Evaluation
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)
Explicit Application of Procedures, and Explicit Evaluation
6.001 SICP Variations on a Scheme
6.001 SICP Interpretation Parts of an interpreter
CSE 341 Lecture 11 b closures; scoping rules
topics interpreters meta-linguistic abstraction eval and apply
More Scheme CS 331.
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 construct 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

Recursive local definitions (define (foo) (letrec ((countdown (lambda (i) (if (= i 0) 0 (begin (display i) (newline) (countdown (- i 1))))))) (countdown 10)))

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)) (map1 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