Program Analysis and Understanding - Fall 2009 | CMSC 631, Papers of Computer Science

Material Type: Paper; Class: PROG ANLYS&UNDERSTANDING; Subject: Computer Science; University: University of Maryland; Term: Spring 2009;

Typology: Papers

Pre 2010

Uploaded on 07/30/2009

koofers-user-y6c
koofers-user-y6c 🇺🇸

10 documents

1 / 10

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Lambda Calculus
CMSC 631 – Program Analysis and
Understanding
Spring 2009
CMSC 631 2
Commonly-used programming languages are
large are complex
!ANSI C99 standard: 538 pages
!ANSI C++ standard: 714 pages
!Java language specification 2.0: 505 pages
Not good vehicles for understanding language
features or explaining program analysis
Motivation
CMSC 631 3
Develop a “core language” that has
!The essential features
!No overlapping constructs
!And none of the cruft
-Extra features of full language can be defined in terms of the
core language (“syntactic sugar”)
Lambda calculus
!Standard core language for single-threaded procedural
programming
!Often with added features (e.g., state); we’ll see that
later
Goal
CMSC 631
Lambda Calculus is Practical!
An 8-bit microcontroller (Zilog Z8 encore board w/4KB
SRAM)computing 1 + 1 using Church numerals in the Lambda
calculus
4
Tim
Fraser
pf3
pf4
pf5
pf8
pf9
pfa

Partial preview of the text

Download Program Analysis and Understanding - Fall 2009 | CMSC 631 and more Papers Computer Science in PDF only on Docsity!

Lambda Calculus CMSC 631 – Program Analysis and Understanding Spring 2009 CMSC 631 (^2)

• Commonly-used programming languages are

large are complex

! ANSI C99 standard: 538 pages ! ANSI C++ standard: 714 pages ! (^) Java language specification 2.0: 505 pages

• Not good vehicles for understanding language

features or explaining program analysis

Motivation

CMSC 631 (^3)

• Develop a “core language” that has

! The essential features ! No overlapping constructs ! And none of the cruft

  • Extra features of full language can be defined in terms of the core language (“syntactic sugar”)

• Lambda calculus

! Standard core language for single-threaded procedural programming ! Often with added features (e.g., state); we’ll see that later

Goal

CMSC 631

Lambda Calculus is Practical!

  • An 8-bit microcontroller (Zilog Z8 encore board w/4KB SRAM)computing 1 + 1 using Church numerals in the Lambda calculus 4 Tim Fraser

CMSC 631

Origins of Lambda Calculus

• Invented in 1936 by Alonzo Church (1903-1995)

! Princeton Mathematician ! Lectures of lambda calculus published in 1941 ! Also know for

  • Church’s Thesis
    • All effective computation is expressed by recursive (decidable) functions, i.e., in the lambda calculus
  • Church’s Theorem
    • First order logic is undecidable 5 CMSC 631^6

• Syntax:

e ::= x variable | "x.e function abstraction | e e function application

• Only constructs in pure lambda calculus

! (^) Functions take functions as arguments and return functions as results ! I.e., the lambda calculus supports higher-order functions

Lambda Calculus

• To evaluate ("x.e1) e

! (^) Bind x to e ! Evaluate e ! Return the result of the evaluation

• This is called “beta-reduction”

! ("x.e1) e2^ #$ e1[e2\x] ! (^) ("x.e1) e2 is called a redex ! (^) We’ll usually omit the beta

Semantics

• Syntactic sugar for local declarations

! (^) let x = e1 in e2 is short for ("x.e2) e

• Scope of " extends as far to the right as possible

! (^) "x."y.x y is "x.("y.(x y))

• Function application is left-associative

! x y z is (x y) z

Three Conveniences

CMSC 631 (^13)

• Formal definition:

! x[e\x] = e ! (^) z[e\x] = z if z % x ! (e1 e2)[e\x] = (e1[e\x] e2[e\x]) ! ("z.e1)[e\x] = "z.(e1[e\x]) if z % x and z FV(e)

• Example:

! ("x.y x) x =& ("w.y w) x^ #$ y x ! (We won’t write alpha conversion down in the future)

Substitution

CMSC 631 (^14)

• People write substitution many different ways

! e1[e2\x] ! e1[x!e2] ! (^) [x/e2]e ! (^) and more...

• But they all mean the same thing

A Note on Substitutions

• We can’t (yet) write multi-argument functions

! (^) E.g., a function of two arguments "(x, y).e

• Trick: Take arguments one at a time

! (^) "x."y.e ! This is a function that, given argument x, returns a function that, given argument y, returns e ! (^) ("x."y.e) a b # ("y.e[a\x]) b # e[a\x][b\y]

• This is often called Currying and can be used to

represent functions with any # of arguments

Multi-Argument Functions

• true = "x."y.x

• false = "x."y.y

• if a then b else c = a b c

• Example:

! (^) if true then b else c # ("x."y.x) b c #("y.b) c # b ! (^) if false then b else c # ("x."y.y) b c #("y.y) c # c

Booleans

CMSC 631 (^17)

• Any closed term is also called a combinator

! So true and false are both combinators

• Other popular combinators

! (^) I = "x.x ! (^) S = "x."y.x ! (^) K = "x."y."z.x z (y z) ! (^) Can also define calculi in terms of combinators

  • E.g., the SKI calculus
  • Turns out the SKI calculus is also Turing complete

Combinators

CMSC 631 (^18)

• (a, b) = "x.if x then a else b

• fst = "p.p true

• snd = "p.p false

• Then

! (^) fst (a, b) #* a ! (^) snd (a, b) #* b

Pairs

• 0 = "x."y.y

• 1 = "x."y.x y

• 2 = "x."y.x(x y)

• i.e., n = "x."y.

• succ = "z."x."y.x(z x y)

• iszero = "z.z ("y.false) true

Natural Numbers (Church)

• 0 = "x."y.x

• 1 = "x."y.y 0

• 2 = "x."y.y 1

• I.e., n = "x."y.y (n-1)

• succ = "z."x."y.y z

• pred = "z.z 0 ("x.x)

• iszero = "z.z true ("x.false)

Natural Numbers (Scott)

CMSC 631 (^25)

• A term is in normal form if it cannot be reduced

! (^) Examples: "x.x, "x."y.z

• By Church-Rosser Theorem, every term reduces

to at most one normal form

! Warning: All of this applies only to the pure lambda calculus with non-deterministic evaluation

• Notice that for our application rule, the

argument need not be in normal form

Normal Form

CMSC 631 (^26)

• Let^ =$ be the reflexive, symmetric, and transitive

closure of

! (^) E.g., ("x.x) y # y ( ("z."w.z) y y, so all three are beta equivalent

• If^ a =$ b, then there exists^ c^ such that^ a^ #*^ c

and b #* c

! (^) Proof: Consequence of Church-Rosser Theorem

• In particular, if^ a =$ b^ and both are normal

forms, then they are equal

Beta-Equivalence

• Consider

! (^) ) = "x.x x ! (^) Then ) ) # ) ) #***

• In general, self application leads to loops

! ...which is good if we want recursion

Not Every Term Has a Normal Form

• Also called a paradoxical combinator

! (^) Y = "f.("x.f (x x)) ("x.f (x x)) ! Note: There are many versions of this combinator

• Then^ Y F =$ F (Y F)

! (^) Y F = ("f.("x.f (x x)) ("x.f (x x))) F ! (^) # ("x.F (x x)) ("x.F (x x)) ! (^) # F (("x.F (x x)) ("x.F (x x))) ! ( F (Y F)

A Fixpoint Combinator

CMSC 631 (^29)

• Fact n = if n = 0 then 1 else n * fact(n-1)

• Let G = "f.

! I.e., G = "f. "n.if n = 0 then 1 else n*f(n-1)

• Y G 1 =$ G (YG) 1

! =$ ("f."n.if n = 0 then 1 else nf(n-1)) (Y G) 1 ! =$ if 1 = 0 then 1 else 1((Y G) 0) ! =$ if 1 = 0 then 1 else 1(G (Y G) 0) ! =$ if 1 = 0 then 1 else 1("f."n.if n = 0 then 1 else nf(n-1) (Y G) 0) ! =$ if 1 = 0 then 1 else 1(if 0 = 0 then 1 else 0((Y G) 0) ! =$ 11 = 1

Example

CMSC 631 (^30)

• The Y combinator “unrolls” or “unfolds” its

argument an infinite number of times

! Y G = G (Y G) = G (G (Y G) = G (G (G (Y G))) = ...

! G needs to have a “base case” to ensure termination

• But, only works because we’re call-by-name

! Different combinator(s) for call-by-value

  • Z =^ "f.("x.f ("y. x x y)) ("x.f ("y. x x y))
  • Why is this a fixed-point combinator? How does its difference from Y make it work for call-by-value?

In Other Words

• Encodings are fun

• They show language expressiveness

• In practice, we usually add constructs as

primitives

! Much more efficient ! Much easier to perform program analysis on and avoid silly mistakes with

  • E.g., our encodings of^ true^ and^0 are exactly the same, but we may want to forbid mixing booleans and integers

Encodings

• Our non-deterministic reduction rule is fine for

theory, but awkward to implement

• Two deterministic strategies:

! (^) Lazy: Given ("x.e1) e2, do not evaluate e2 if x does not “need” e

  • Also called left-most, call-by-name, call-by-need, applicative, normal-order (with slightly different meanings) ! (^) Eager: Given ("x.e1) e2, always evaluate e2 fully before applying the function
  • Also called call-by-value

Lazy vs. Eager Evaluation

CMSC 631 (^37)

• Two main camps:

! Haskell – Pure, lazy functional language; no side effects ! ML (SML/NJ, OCaml) – Call-by-value, with side effects

• Still around: LISP, Scheme

! (^) Disadvantage/advantage: No static type systems

Functional Programming Today

CMSC 631 (^38)

Influence of Functional Programming

• Functional ideas in many other languages

! (^) Garbage collection was first designed with Lisp; most languages often rely on a GC today ! Generics in Java/C++ came from polymorphism in ML and from type classes in Haskell ! (^) Higher-order functions and closures (used widely in Ruby; proposed extension to Java) are pervasive in all functional languages ! Many data abstraction principles of OO came from ML’s module system ! (^) … CMSC 631

Call-by-Name Example

39 OCaml let cond p x y = if p then x else y let rec loop () = loop () let z = cond true 42 (loop ()) Haskell cond p x y = if p then x else y loop () = loop () z = cond True 42 (loop ()) infinite loop at call 3rd argument never used by cond, so never invoked CMSC 631

Two Cool Things to Do with CBN

• Build control structures with functions

• “Infinite” data structures

40 cond p x y = if p then x else y integers n = n:(integers (n+1)) take 10 (integers 0) ( infinite loop in cbv )