Structuring and Evaluating Code
Copyright (c) 2017 Kathi Fisler
1 Rules for Composing Expressions
In the last lecture, we saw that we can use expressions to build up larger expressions (this is called composition). Some compositions are fine (like we saw in class with images), but others would not make sense, such as above(3, circle(50, "solid", "red")). What distinguishes valid from invalid compositions?
1.1 Types
In programming, values fall into categories called types. We have seen three types so far: Numbers, Strings, and Images. Operations in a programming language are defined in terms of types: each operation works on some types and not others. Furthermore, each operation produces a specific type of value. For example:
Multiplication works on numbers and produces a number
overlay works on images and produces an image
overlay-xy works on an image, two numbers, and an image and produces an image
These descriptions can get verbose, so programming languages often have notation for the types on an operation. If you look at overlay-xy in the Pyret documentation, for example, it shows:
overlay-xy :: ( |
img1 :: Image, |
dx :: Number, |
dy :: Number, |
img2 :: Image |
) |
-> Image |
This notation indicates that overlay-xy requires four inputs (an image, two numbers, and an image, in that order). Each input has both a name (img1, dx, etc) and its type. The names are usually at least somewhat descriptive, to help you remember what each input is. Otherwise the names aren’t significant.
The arrow (->) shows what type the operation produces (in this case, an Image). The produced value isn’t named, because the name of the operation suggests wahat the operation does.
For now, this notation isn’t something you write. It’s just the notation you’ll find in the documentation to know how to use an operation.
1.2 Types Guide Composition
Types help us understand how we can compose expressions. Specifically, any expression that produces a value of a given type can be used as an input that expects that type. The result of overlay-xy, for example, is an Image, and thus can be used for any operation that needs an Image (such as above or another use of overlay-xy).
As we introduce new operations, we will summarize their input and output types, so you can see how expressions build on one another.
2 Code Structure: Emoji code
We looked at two versions of a program to draw an emoji face. Our discussion focused on the following issues:
The first may seem easier to read, since the result of each expression is named.
But the second may also seem easier to read because the indentation of subexpressions reveals the structure of the computation itself. Structuring computations is one of the major tasks in programming, and having your code reflect the structure of your solution is extremely useful when you (or someone else) has to read your code later.
Finding a balance between naming (to remember what pieces of a computation do) and nesting (for structure) is a big part of learning how to write good programs. This is something you’ll practice throughout the course.
There are no significant differences in efficiency between the two versions.
3 How Programs Evaluate: Ice Cream
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)) |
How will Pyret evaluate this program?
Pyret processes the expressions one at a time from top to bottom
When Pyret encounters something of the form name = expr, it creates an entry in an internal dictionary. The dictionary maps names to values. Thus, Pyret evaluates the expression on the right of the =, then makes a dictionary entry to associate the name with that value.
When Pyret encounters an expression that has other expressions nested within it, it evaluates the sub-expressions from left-to-right and innermost to outermost. Thus, in the flip-vertical expression (that creates the cone), the first expression to evaluate is SCOOP-SIZE (which Pyret looks up in the dictionary), then Pyret computes 15 * 2, then it creates the triangle, then flips the triangle.
In the longer overlay-xy expression, the pink circle gets created before the green circle (by the left-to-right rule).
You may have noticed that SCOOP-SIZE is all in caps, while cone is in lowercase. Conceptually, SCOOP-SIZE is a key concept in the program (which we plan to use multiple times), whereas cone is just naming an intermediate computation for readability. We use this naming convention to help us remember the respective roles of the names in the program.
3.1 What does the Run button do?
When you press the Run button, Pyret erases the dictionary then re-processes the definitions window from the beginning. Any dictionary entries that you made only in the interactions (right) window disappear.
4 Expressions versus Statements
We’ve already seen that there’s a difference between
SCOOP-SIZE = 15 |
|
SCOOP-SIZE * 2 |
and their impact on the interactions window: the first adds to the dictionary, while the second displays a value. A piece of a program that changes how future expressions will evaluate is called a statement. Creating a name meets this definition, since expressions will yield errors or not depending on whether a name appears in the dictionary. Expressions perform computations without changing the information that Pyret maintains for running future expressions.
This distinction will become more meaningful later in the course, but we’ll use the terminology to get used to it now.
4.1 Key Takeaways
The theme of this segment is how code can reflect the structure of data or computations. The structure of an image is reflected in which smaller images you use to create it; the structure of a computation is reflected in which operations you choose and how you nest them. Computer scientists look for structure in data and problems, then capture that structure in code so others can see what structure they had in mind.