Midterm Review

Table of Contents

1. Midterm Review

1.1. Binder

A binder for example is x in the following function definition.

def func(x): #<--- here
    return x + 1

1.2. Lazy vs Eager

Example

f(x) = x + 2

f(3 * 4)

Eager (Call by value)

f(3 * 4)

= f(12)

= 12 + 2

= 14

Lazy (Call by name)

f(3 * 4)

= 3 * 4 + 2

= 12 + 2

= 14

Lazy can find the way to an answer while Eager errors.

Eager is better because we can point to where we should error.

Another Example

def f(x):
    print("f is called")
    return x + 3
def g(y):
    print("g is called")
    return y + 2

g(f(7))

In python f is called first because it is an eager langauge, but in a lazy language f(7) will not be firstly evaluated before it substitutes.

1.3. Curry

Originaly,

def f(a, b):
        .
        .
        .
f(1, 2)

what if instead,

def f(a):
        def g(b):
              body
      return g
f((1)(2))

Instead of having multiple arguments, why not have nested functions.

In theory we dont need function with multiple arguments.

Example In Racket

(define (f x y)
        (+ (* x x) (- y 5)))

(define (curried-f x)
        (lambda (y) (+ (* x x) (- y 5)))))

(f          10  20)
((curried-f 10) 20)

1.4. Lexical vs Dynamic Scope

def f(x):
    return x + y
def g(y):
    return y - f(7)
g(6)

Lexical Scope : be able to look at every binder and figure out the scope of each function where bindings arent shared between scopes in a sense

  • usually how most languages work
  • above code doesnt work

Dynamic Scope : the scope of bindings is shared with its children(s)

  • seen as a mistake
  • code might work depending on if binding exists
  • above code does work

1.5. Substitution - Small Step Reduction Sequence

note: only time anything gets added to an environment is in function applications

Example

{{{(x) => {(y) => { + x y }}} 3} 7} -> at this point x and y are in the environment

= { {(y) => { + 3 y }} 7}

= {+ 3 7}

= 10

Date: 2024-10-28 Mon 00:00

Author: Anthony Rossi

Created: 2024-10-28 Mon 17:00