Class summary: Practice with Known Names
Copyright (c) 2017 Kathi Fisler
We have talked about how Pyret maintains a collection of "known names" under the hood. Pyret uses the "known names" area to look up the values associated with names while running your program. We’ve talked a bit about this idea, but today we want to look at it in much more detail, since managing known names is one of the essential tasks in any programming language.
While we’ve been using the informal term "known names", the actual technical term for this mapping from names to values is the environment. We’ll switch to using the actual term now that you hopefully have intuition about the concept.
1 Recap: What’s in the Environment
So far, we’ve had the following rules for populating the environment:
A bunch of standard functions, like + and string-length are in the environment by default
If you use include, you add several more functions (e.g., on tables or images) to the environment
If you associate a name with a value using
name = some-expression
then name goes into the environment, associated with the value from computing some-expression.
If a name gets added to the environment while Pyret is evaluating the body of a function, Pyret creates a temporary environment for definitions that arise within the function. Pyret deletes the temporary environment once the function body bfinishes evaluating.
There’s one more rule we haven’t talked about yet. Up until now, we have said that when you call a function, Pyret substitutes the inputs that you provided for the variables within the function. Actually, Pyret just makes entries in the temporary environment for the variables and associates those names with the values you provided. This behaves the same way as substitution, but it will prove a bit easier for us to work with as our programs get more complicated.
Let’s Try It: For the following program, what is in the environment at each of the marked points?
month = "July" |
# point 1 |
|
fun create-date(day :: Number) -> String: |
# point 3 |
month + " " + day + ", 2019" |
end |
|
# point 2 |
today = create-date(7) |
# point 4 |
Answer: We’ll omit the Pyret defaults as we write these out.
At point 1, the environment has
month -> "July" |
At point 2, the environment has
month -> "July" |
create-date -> function<...> |
At point 3, the environment has
month -> "July" |
create-date -> function<...> |
------ # we'll use lines to mark off the temporary environment |
day = 7 |
------ |
At point 4, the environment has
month -> "July" |
create-date -> function<...> |
today = "July 7, 2019" |
Notice that day goes into the temporary environment for the use (call) of the function, then disappears once the function has finished.
Question: Point 3 appears on an earlier line than Point 2 in the original code sample. Why did we use that numbering, instead of swapping points 2 and 3? (Hint: what order does the code get evaluated in?}
1.1 Practice Exercises
We worked through two handouts of sample programs to make sure you see how the environment works in different situations (handout 1 – handout 2). For each handout, you were asked to indicate what order the lines are executed in, and the environment contents at each marked point.
Hopefully these exercises have helped you strengthen your understanding of how programs evaluate in Pyret. These rules are fairly standard across most programming languages.
Takeaways from this segment:
Two functions can use the same variable name. The two names won’t clash due to the temporary environments.
The same value can be referenced via multiple names during the course of a program. This allows programmers to use different names in different parts of the code without causing problems.
If the same function is called multiple times, it gets a fresh temporary environment on each call.