2
be true. Some notes
When you have a higher order function and pass in multiple operands in one line, like the line that says
yes = yes(yes)(no)... we do not evaluate all the operands at once. For example, we do not evaluate no until
the call to yes(yes) has returned. This is because yes(yes) is tantamount to evaluating the operator for the
next function call on no, and evaluating the operator always precedes evaluating the operand.
Draw pointers for non-primitive data, and write primitive data directly in the box. Primitive expressions
in this course are almost always integers and strings, and non-primitive data are typically things like functions
and lists (which we haven’t learned about yet). A pointer represents a location in memory, so if you draw
a pointer to a primitive that suggests both environment variables refer to the same data in memory when
that may not be the case (i.e., suppose x in f1 is 3 and so is y in Global. Modifying x should not affect the
value of y, but if you draw a pointer to the same number that implies that a change to x will cause a change to y).
If there exists a variable in the global frame like yes and I set yes to be "no" in f1, that does not throw
an error. Instead a new variable in f1 called yes is created. How can that be? Didn’t we learn that we can’t
change the value of variables existing in another frame? Python actually does not interpret yes = "no" in f1
as an attempt to modify the global yes. The most common case in which you’d run into this sort of error would
be if you wrote x = x + 1 where x is exclusively defined in another frame. In this case, the program expects
x to already exist (otherwise, how would we know the value of x + 1?), and if x only exists in global, then
x = x + 1 is interpreted as an attempt to change the existing value that is not in the current frame. Something
like x = 1 does not throw an error because there is no assumption that x already exists in some other frame.
Finally, recall that the value of an argument depends on the frame in which the function was called. This
is because our order of evaluation is evaluate the operator, evaluate the operands, apply the function to the
operands. Hence, the operands are evaluated before the function call is initiated, so they must be evaluated
in the frame in which the call was performed. In this case, the majority of function calls are happening in
the last line of code, which is in the global frame, so we’re going to be evaluating yes’s and no’s in the global
frame most of the time. When working with evaluation in places other than the global frame, we first look
in the current frame for the value of an environment name. If we cannot find that environment name in the
current frame, then we look in its parent and then the parent’s parent and so on. The first time we encounter
the name we are looking for, we stop looking up the frame hierarchy. In f3 the name no exists, so when we try
to evaluate no in f3, we run with the f3 definition and stop looking through our hierarchy. Hence, no is ’ok’ as
defined in f3 instead of a function as defined in global.