 A key is a value which is used to point at another value. It's a value which uniquely identifies some other value. A key and the value associated with it are together known as a key-value pair. A key-value pair is an associative relationship. You have a value which is known by its association with another value, a key. Key-value pairs make up our other kind of collection type, what we'll call dictionaries. Whereas a list is a collection of values organized in sequence and known by a numeric index. In a dictionary there is no order. Instead, there are just a bunch of key-value pairs in no particular order, and no two keys can be equal with each other because the values are indexed by the keys. To create a dictionary, we use the dict operator. In the top expression here, we create an empty dictionary, and in the bottom expression we create a dictionary with two key-value pairs. The key-value pairs are written with a key first, followed by the value, so in this example the key 77 has the value yo, and the key of vast has the value true. Again, be clear that there is no sense of order among the key-value pairs, so it doesn't matter which order we write them in here. The operators len, get, and set can all be used on dictionaries as well as lists. Here we assign to Ted a new dictionary with two key-value pairs, the key 5 with the value 2, and the key yo with the value negative 1. Len Ted first returns 2 because the dictionary has two key-value pairs, get Ted yo 0 returns negative 1 the value of the key yo. Set Ted yo 8 changes the value of the key yo from negative 1 to 8. Len Ted still returns 2 because the number of key-value pairs has not changed. Get Ted yo returns 8, the current value of the key yo. Set Ted 21 false, the new key-value pair, a key 21 with the value false. Lastly, Len Ted then returns 3 because the dictionary now has three key-value pairs. So like lists, dictionaries are mutable, so we have to be cognizant of when they are modified. Here we assign an empty dictionary to a variable cow and also to a variable goose. Set cow name Fred adds a key name with the value Fred, and then get goose name returns Fred because goose and cow reference the same dictionary. So when might you want to use dictionaries? Well imagine you have a program in which you need to create information about a bunch of people. One solution would be to have a bunch of lists, such that one list stores their names, another stores their addresses, another stores their phone numbers, and so on. These lists would be kept in sync such that the info of one person is stored at the same index in each list. For example, the address at index 5 of the address list should be the address of the person whose name is at index 5 of the name list. While workable, this solution is error-prone. The better solution is to create a single list of dictionaries, where each dictionary holds the info of one person, e.g. the person's name is stored as the value of the name key, and the person's address is stored as the value of the address key. Here we have a function we might use to create such a dictionary, a function which takes a name, age, and social security number and returns a new dictionary with those values. We could then call this make person function like so, with the string Mike Smith for the name, 43 for the age, and 555-555-5555 for the social security number. The function would then return a new dictionary with a key name with the value of Mike Smith, a key age with the value of 43, and a key SS with the value of 555-555-5555. So that's actually everything to know about Pigeon. Imagine you're wondering what makes real language is different. Well, first off, as we already discussed, Pigeon has no way of doing interesting input and output beyond simple text input and output on the console. If Pigeon were a real language, we'd have some means of doing things like reading and writing files, getting mouse input, and drawing graphics on the screen. Other things which Pigeon deliberately lacks are conveniences, such as an easier way of writing loops that isn't so verbose. Lastly, all of the tiny programs we wrote were all written as one file of source code. In any non-trivial program, though, you'll want to separate your source code into multiple files for organizational purposes, because past a few hundred lines, keeping all of your code in one file becomes more and more impractical. So, real languages give us ways to modularize code into separate source files. All of this said, aside from input output, conveniences, and modularization of code, most real languages don't have all that much going on conceptually, which we haven't just seen in Pigeon.