Default values and sentinel values
The source gives the integer case: the default for an integer type is 0.
Asking a Map a Question
A map pairs keys with values. You give it a key of one type, and it hands back the value of a second type that is associated with that key. The source material makes this concrete with a phone book: a name goes in, a telephone number comes out. This article looks at the single moment you ask a map for a value by writing a key in square brackets, an operation called subscripting. The goal is to understand exactly what happens inside that one line of code, including the case where the key you asked about has never been stored. That case is where many learners' expectations go wrong, so it gets the most attention.
What do you think happens?
A function takes a name and returns whatever value the phone book gives back for that name. If the name has never been stored as a key, what do you think the lookup returns?
Reveal answer
A default value of 0 is returned for the integer value type, and the map gains a new entry for that name.
The lookup has a second behavior that is easy to overlook. If the key is not found, the map creates an entry for that key and gives it a default value. The lookup both returns a value and changes the map.
A Phone Book as a Map
When a map is indexed by a value of its first type, the map is searched for that key. If the key is present, the map returns the value stored with it. The first type is called the key, and the second type is called the value, or the mapped type. In the phone book example, the key type is a string (a name) and the value type is an integer (a telephone number).
Picture the map as a set of pairs. Each key sits next to exactly one value. The diagram below shows two illustrative entries. A lookup starts from the key you supply, finds the pair that holds it, and reads off the value on the other side. The sample names and numbers are invented for illustration; the source describes the structure, not these particular entries.
Subscripting Finds a Stored Value
The function below is the entire lookup described in the source. It takes a string, uses that string as a key into a map called phone_book, and returns whatever value the map gives back. Notice that it does not loop, search, or compare anything by hand. The subscript operation performs the entire search, and the function is a named wrapper around that one operation. This is why the source describes subscripting as essentially the lookup itself.
phone_book[name] is the subscript: name is the key being searched for- return passes back whatever value the map gives for that key
Looking up a key that is present
The phone book already contains the key Cara with the value 9032. What does get_number return when called with Cara?
- 1Identify the key
The argument is the string Cara, which is used as the key for the subscript.
- 2Search the map
The map is searched for the key Cara. The key is present, so the search succeeds.
- 3Read the stored value
The value stored with Cara is 9032. The map returns that value.
- 4Check for side effects
Because the key was already present, nothing is added. The map is unchanged.
get_number returns 9032, and the phone book still has exactly the same entries as before.
What Happens When the Key Is Absent
The subscript has two branches, and the choice between them depends entirely on whether the key is already in the map at the moment the subscript runs. The flowchart below traces both paths from the same starting point. In the first branch the map already holds the key, so nothing is added and the stored value comes back. In the second branch the key is absent, so the map grows by one entry before the default value is returned.
The branch that matters most for surprises is the second one. A learner who expects a missing key to produce only a notification of absence is following a model the source does not describe. Instead, the map creates an entry for the missing key and gives it a default value, and that default is what the lookup returns.
Default Value Initialization Changes the Map
The process of inserting a missing key with a default value is called default value initialization. The default value depends on the type of the value. The source gives the integer case: the default for an integer type is 0. Because the subscript both inserts and returns a value, a lookup of a missing key changes the map as well as producing a result. The diagram below compares the phone book before and after looking up the missing name Ben. The sample entries are illustrative.
Pick the value type and the meaning of its default together. The source's own choice of 0 for an invalid telephone number shows the intent: the default is a meaningful placeholder for the program's design, not a universal constant that means the same thing everywhere.
Tracing Where a Result Diverges
When a lookup returns something surprising, the fastest way to find out why is to trace it. The source points to two questions that locate the divergence: was the key present when the subscript ran, and what was stored under that key at that moment? Checking those two facts usually explains the returned value. The worked example below applies both questions to a lookup that a learner might not expect.
Tracing a lookup that returned an unexpected value
The map holds Ana with 4417 and Cara with 9032. A learner calls get_number with Ben and expects an error. The function returns 0 instead. Where did the result diverge from the expectation?
- 1Write down the map before the lookup
The map contains two keys, Ana and Cara. Ben is not among them.
- 2Ask whether the key was present
At the moment the subscript ran, Ben was absent. This is the point where the expectation and the behavior part ways: the learner assumed absence would signal an error, but the map inserts the key instead.
- 3Apply default value initialization
Because Ben was absent, the map creates an entry for Ben and assigns the default value 0 for the integer value type.
- 4Return the default
The subscript returns the value it just stored, which is 0.
- 5Check the map again
The map now contains Ana, Cara, and Ben. A second lookup for Ben would find the key present and return 0 from storage, which looks identical to the first result.
The divergence occurs at the subscript itself. The returned 0 is the default inserted for a missing key, and the map grew by one entry.
Sentinel Values Versus Stored Values
A default value that the program uses to mean that no real answer exists is one kind of sentinel value. The source's example is 0 used for an invalid telephone number, a placeholder that signals the program's design rather than a genuine stored fact. The danger is that a sentinel and a real stored value can have the same content. The table below compares them. Notice that the value alone may not reveal which one you are looking at.
| Aspect | Genuine stored value | Sentinel or default value |
|---|---|---|
| How it gets in the map | Stored deliberately under a key that was already present | Inserted by default value initialization when the key was missing |
| What it means | A real value the program recorded for that key | A placeholder the program's design treats as not a real answer |
| Example | Cara maps to 9032 | Ben maps to 0 after a missing-key lookup |
| Can the value alone tell them apart? | No, if the stored value happens to be 0 | No, the default 0 looks the same as a stored 0 |
Genuine stored values versus sentinel defaults
Mistakes Beginners Make with Missing Keys
Common mistake Assuming a lookup for a missing key leaves the map unchanged
What it looks likeAfter calling get_number with Ben, the learner counts two entries and expects the phone book to still hold two.
Why it failsThe subscript both returns a value and changes the map. A missing key causes an entry to be inserted, so the map grows by one.
Do this insteadAfter any lookup that might miss, recount the map and expect one extra entry for each missing key that was looked up.
Common mistake Treating a 0 result as proof that the key was stored
What it looks likeThe function returns 0 for Ben, and the learner concludes that Ben's number is 0.
Why it failsA 0 can be a genuine stored value or a default inserted for a missing key. The returned value alone does not reveal which.
Do this insteadCheck whether the key was present before the subscript ran. That fact, not the returned value, determines what happened.
Common mistake Choosing a default without deciding what it means
What it looks likeA program uses 0 as the default telephone number and later treats every 0 as a real, reachable number.
Why it failsThe source presents the default as a meaningful placeholder for the program's design. If its meaning is not decided, the placeholder gets read as data.
Do this insteadPick the value type and the meaning of its default together, and document what the default represents.
Common mistake Expecting a missing key to be reported rather than filled in
Practice Tracing Lookups
The map holds Ana with 4417 and Cara with 9032. Trace three calls to get_number in order: first Cara, then Ben, then Ben again. For each call, state whether the key was present, what the function returns, and how many entries the map holds afterward.
Hints
- Ask first whether the key is present at the moment each subscript runs, not whether it will be present later.
- The first call to Ben is the one that changes the map. Consider what the second call to Ben finds.
- Keep a running count of entries, starting from two.
Key Takeaways
- Subscripting a map uses a key of the first type to find and return the value of the second type stored with that key.
- When the key is present, the map returns the stored value and does not change.
- When the key is absent, the map inserts the key with a default value, such as 0 for an integer type, and returns that default, so the map grows by one entry.
- A default can act as a sentinel placeholder, but its returned value can match a genuine stored value, so trace whether the key was present before the lookup ran.