Due: before class on Monday 09 November
-
Select all TRUE statements in a language that has lexical scope and closures:
-
When a function is called, the parent pointer of the newly created environment frame is set to the environment frame of the caller (the call site).
-
Environment frames (especially in functions that return a lambda) must be allocated on the stack, not the heap.
-
In a standard recursive Scheme function (e.g.,
(define (factorial n) ...)), each recursive call creates a new frame whose parent pointer points to the frame of the immediately preceding recursive call. -
Two closures created by two separate calls to the same outer factory function point to the same compiled code/AST node, but point to different environment frames.
-
The return value of a function is always stored in the frame of the called function itself, not in the parent frame.
-
-
Consider the following Scheme code:
(define make-stepper (lambda (start step) (define current start) (lambda (msg . args) (cond ((eq? msg 'step!) (set! current (+ current step)) current) ((eq? msg 'fork) (make-stepper current (car args))) ((eq? msg 'get) current) (else (error "Unknown msg")))))) (define s1 (make-stepper 10 2)) (s1 'step!) (define s2 (s1 'fork 5)) (s1 'step!) (s2 'step!)-
What are the three values produced by calling
(s1 'step!)both (both times) and(s2 'step!) -
Draw the complete frames and closures diagram from running this program. Be sure to follow the “rules” on when to make a new closure vs. a new frame, and how to correctly set the parent frame.
-
-
Write a higher-order Python function
make_rate_limiter(max_calls)that returns a function which transforms any other one-argument function, into one that refuses to work after the given number ofmax_calls.That sentence is hard to read! Just check out this example on how
make_rate_limitershould work:# Creates a limiter for up to 2 calls limit_twice = make_rate_limiter(2) # Wrap an arbitrary single-argument function greet = limit_twice(lambda name: f"Hello, {name}!") print(greet("Alice")) # Prints: "Hello, Alice!" print(greet("Bob")) # Prints: "Hello, Bob!" print(greet("Charlie")) # Prints: "Rate limit exceeded" print(greet("Diana")) # Prints: "Rate limit exceeded" # Calling limit_twice again resets the limit print(limit_twice(abs)(-5)) # Prints 5 # Each wrapped function encapsulates its own independent state three_squares = make_rate_limiter(3)(lambda x: x * x) print(three_squares(3)) # Prints: 9 print(three_squares(4)) # Prints: 16 print(three_squares(5)) # Prints: 25 print(three_squares(6)) # Prints: "Rate limit exceeded"