When I was studying the SICP course, the execution order of the following code in the environment diagram is inconsistent with what I expected.
def add_one(x):
y = x+1
return y
def square(x):
return x*x
square(add_one(9))
I am expecting the following evaluation order:
square
. A function value is returned.add_one(9)
.add_one
. A function value is returned.9
. Now the expression add_one(9)
returns 10square(add_one(9))
return 100.However, I run the code on this website It told me that the add_one
frame created before the square
, which is opposite of what I expected. Is it right?
I asked ChatGPT about this question. It gives the answer that this is because in Python, the priority of function calls is higher than that of operators.
Your order is evaluation is mostly correct. However you are confusing "creation of the frame" with "evaluation of the frame".
To call a function, Python evaluates the function and its arguments. This order appears to be left-to-right, but I cannot find anything in the documentation that guarantees this. [Other StackOverflow answers say it is guaranteed left-to-right, so maybe there's something I'm missing.]
Only after the function and its arguments are evaluated is the function call actually made. This is when the frame is created.
Try the following code. It will give you a clearer idea of evaluation order.
def add_onex():
print("Calling add_one")
return add_one
def squarex():
print("Evaluating square")
return square
def add_one(x):
print("Calling add one")
y = x + 1
return y
def square(x):
print("Calling square")
return x * x
result = squarex()(add_onex()(9))
Obviously, in most cases, the evaluation of a function is a simple name lookup. But in cases where evaluation of the function is not trivial, you can see that this evaluation happens before the arguments are evaluated.