## Class Summary: How Programs Evaluate

The textbook discusses how expressions evaluate, but not how definitions evaluate or the relationship between the definitions and interactions windows.

Now that you’re learning how to write programs, you also need to understand how Pyret will compute the results of those programs.

### 1Evaluating Expressions

We say that expressions evaluate to values. The result computed by an expression is its value. The process by which an expression is computed into a value is called evaluation.

You probabaly already have an intuition for evaluation from arithmetic. In what order do you perform the operations when you evaluate

 3 * (4 + (6 - 1))

? We do 6 - 1 first, then we add 4, then we multiply by 3. We work from the inside out, evaluating the innermost computation, replacing the expression with its value, then moving out to the next innermost expression.

The same rule—evaluate from the inside out—works whether your expression is over numbers, strings, images, or booleans (or other kinds of data that we will learn about later). Let’s look at this is the context of images:

 overlay-xy(circle(15, "solid", "blue"), -25, -25, circle(15 * 2, "outline", "black"))

The expression for the blue circle evaluates first, then the expression for the black circle, then the call to overlay-xy, which produces the final image.

### 2Evaluating Definitions

Imagine that you had the following contents in the definitions window (the one on the left):

 include image SCOOP-SIZE = 15 cone = flip-vertical(triangle(SCOOP-SIZE * 2, "solid", "tan")) overlay-xy(circle(SCOOP-SIZE, "solid", "pink"), 0, 25, overlay-xy(circle(SCOOP-SIZE, "solid", "green"), 0, 25, cone)) # what would happen if we entered each of the following into the # interactions window BEFORE pressing Run? circle(15, "solid", "red") circle(SCOOP-SIZE, "solid", "red") cone = triangle(30, "solid", "blue") # what would happen if we entered each of the following into the # interactions window AFTER pressing Run? SCOOP-SIZE SCOOP cone = triangle(30, "solid", "blue")

Now that you see what happens, let’s understand why.

#### 2.1The Dictionary of Operations and Values

Under the hood, Pyret maintains what you can think of as a dictionary that maps names to values and operations. When you first start a Pyret window, the dictionary contains entries such as:

 *   --->  the multiplication operator /   --->  the division operator string-length ---> the operator to compute the length of a string

In the interactions window, you can write expressions using operators that are in the dictionary (Pyret also knows the number and string values, so you can use them in expressions too).

Now let’s say you want to make a circle. The circle operation isn’t in the default dictionary (Pyret keeps the dictionary small, unless you tell it otherwise). When you run

 include image

You are telling Pyret "add the image operations to the dictionary". So now the dictionary looks like:

 *   --->  the multiplication operator /   --->  the division operator string-length ---> the operator to compute the length of a string circle ---> the operation to create circles ...

You can also add to the dictionary by writing definitions that associate names with values. So if you write

 red-circ = circle(50, "solid", "red")

Pyret extends the dictionary to look like:

 *   --->  the multiplication operator /   --->  the division operator string-length ---> the operator to compute the length of a string circle ---> the operation to create circles ... red-circ ---> the value for a solid red circle with radius 50

#### 2.2Using the Dictionary

Now assume you wrote the following:

 scale(10, red-circ)

How does Pyret evaluate this expression? First, it checks that the operator (scale) exists in the dictionary (this got added when you did include image). It then evaluates the operands from left to right. It evaluates 10, which is already a value. Then it evaluates red-circ. red-circ is a name, so Pyret goes to the dictionary to look it up. The dictionary has an entry for red-circ, so Pyret grabs the associated value. Finally, Pyret uses the scale operation from the dictionary to compute a value.

When you use a name in your program, whether as an operator, and operand, or just as a value at the prompt, Pyret goes to the dictionary to look it up. If you ask for something that isn’t in the dictionary, then Pyret gives you the error saying that "this identifier is unbound". "Identifier" is the technical term for a name in a programming language. "Unbound" is the technical term for "not in the dictionary".

#### 2.3Evaluating Files (and Interactions)

Let’s put it all together. Go back to the ice cream cone program in the definitions window:

 include image scoop-size = 15 cone = flip-vertical(triangle(SCOOP-SIZE * 2, "solid", "tan")) overlay-xy(circle(SCOOP-SIZE, "solid", "pink"), 0, 25, overlay-xy(circle(SCOOP-SIZE, "solid", "green"), 0, 25, cone))

When you hit the Run button, Pyret takes the following steps:

• It resets the dictionary to the initial one (with just the operators on numbers, strings, and other basic stuff we haven’t learned yet).

• It goes through the definitions window, one item at a time, and evaluates each item:

• If the item is an include statement, Pyret extends the dictionary.

• If the item is a definition, Pyret evaluates the expression being named, then extends the dictionary with the defined name and the computed value.

• If the item is an expression, Pyret evalutes the expression and displays the result in the interactions window.

While evaluating expressions, Pyret looks up values of names that are used in expressions.

• Once all the items in the file have been processed, Pyret waits for you to enter expressions in the interactions window. When you do, it evaluates them (using the dictionary when needed) and displays the result of each expression.

To check your understanding of these rules, ask yourself what happens in each of the following situations:

• You run the ice-cream-cone program, then type scoop in the interactions window

• You run the ice-cream-cone program, then type "scoop" in the interactions window

• You run the ice-cream-cone program, then type scoop-size + 5 in the interactions window

• You run the ice-cream-cone program, then type scoop-size + cone-size in the interactions window

• You enter flavor = "strawberry" in the interactions window, hit run, then enter flavor in the interactions window.

• You run the ice-cream-cone program, then type scoop-size = 10 in the interactions window

The last question makes a key point: you can’t give two definitions to the same name (what a confusing dictionary _that_ would be). You can edit your file (with a new value for name) and run it again, but you can’t have multiple definitions for the same name. What if you want to update the value in the dictionary while the program is running? For now, you can’t. Being able to do this complicates all sorts of things, so we will get to updating the dictionary much later in the course (this may seem odd to those who have programmed before, but there are good reasons for this which we will explain when the class as a whole gets to that point).