You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As shown in the example above, keyword lists are mostly used as optional arguments to functions.
38
+
37
39
As the name implies, keyword lists are simply lists. In particular, they are lists consisting of 2-item tuples where the first element (the key) is an atom and the second element can be any value. Both representations are the same:
38
40
39
41
```elixir
@@ -86,7 +88,7 @@ query =
86
88
select: w
87
89
```
88
90
89
-
Although we can pattern match on keyword lists, it is rarely done in practice since pattern matching on lists requires the number of items and their order to match:
91
+
Although we can pattern match on keyword lists, it is not done in practice since pattern matching on lists requires the number of items and their order to match:
** (MatchError) no match of right hand side value: [a:1, b:2]
100
102
```
101
103
102
-
In order to manipulate keyword lists, Elixir provides the `Keyword` module. Remember, though, keyword lists are simply lists, and as such they provide the same linear performance characteristics as them: the longer the list, the longer it will take to find a key, to count the number of items, and so on. For this reason, keyword lists are used in Elixir mainly for passing optional values. If you need to store many items or guarantee one-key associates with at maximum one-value, you should use maps instead.
104
+
Furthermore, given keyword lists are often used as optional arguments, they are used in situations where not all keys may be present, which would make it impossible to match on them. In a nutshell, do not pattern match on keyword lists.
105
+
106
+
In order to manipulate keyword lists, Elixir provides the `Keyword` module. Remember, though, keyword lists are simply lists, and as such they provide the same linear performance characteristics as them: the longer the list, the longer it will take to find a key, to count the number of items, and so on. If you need to store a large amount of keys in a key-value data structure, Elixir offers maps, which we will soon learn.
103
107
104
108
### `do`-blocks and keywords
105
109
@@ -125,7 +129,7 @@ Pay close attention to both syntaxes. In the keyword list format, we separate ea
125
129
126
130
Note that only a handful of keyword lists can be converted to blocks: `do`, `else`, `catch`, `rescue`, and `after`. Those are all the keywords used by Elixir control-flow constructs. We have already learned some of them and we will learn others in the future.
127
131
128
-
With this out of the way, let's see how we can work with nested data structures.
In the previous section, we have used maps as a key-value data structure where keys can be added or removed at any time. However, it is also common to create maps with a pre-defined set of keys. Their values may be updated, but new keys are never added nor removed. This is useful when we know the shape of the data we are working with and, if we get a different key, it likely means a mistake was done elsewhere.
As you can see from the printed result above, Elixir also allows you to write maps of atom keys using the same `key: value` syntax as keyword lists.
188
192
189
-
When the keys are atoms, in particular when working with maps of fixed keys, we can also also access them using the `map.key` syntax:
193
+
When the keys are atoms, in particular when working with maps of predefined keys, we can also also access them using the `map.key` syntax:
190
194
191
195
```elixir
192
196
iex> map = %{name:"John", age:23}
@@ -198,7 +202,16 @@ iex> map.agee
198
202
** (KeyError) key :ageenot found in: %{name:"John", age:23}
199
203
```
200
204
201
-
This syntax has one large benefit in that it raises if the key does not exist in the map and the compiler may even detect and warn when possible. This makes it useful to get quick feedback and spot bugs and typos early on. This is also the syntax used to power another Elixir feature called "Structs", which we will learn later on.
205
+
There is also syntax for updating keys, which also raises if the key has not yet been defined:
206
+
207
+
```elixir
208
+
iex> %{map |name:"Mary"}
209
+
%{name:"Mary", age:23}
210
+
iex> %{map |agee:27}
211
+
** (KeyError) key :ageenot found in: %{name:"John", age:23}
212
+
```
213
+
214
+
These operations have one large benefit in that they raise if the key does not exist in the map and the compiler may even detect and warn when possible. This makes them useful to get quick feedback and spot bugs and typos early on. This is also the syntax used to power another Elixir feature called "Structs", which we will learn later on.
202
215
203
216
Elixir developers typically prefer to use the `map.key` syntax and pattern matching instead of the functions in the `Map` module when working with maps because they lead to an assertive style of programming. [This blog post by José Valim](https://dashbit.co/blog/writing-assertive-code-with-elixir) provides insight and examples on how you get more concise and faster software by writing assertive code in Elixir.
204
217
@@ -250,12 +263,14 @@ There is more to learn about `put_in/2` and `update_in/2`, including the `get_an
250
263
251
264
## Summary
252
265
253
-
The different ways for working with key-value stores in Elixir can be daunting at first, the bottom line is that, between the `Access` module and pattern matching, Elixir developers have a rich set of tools for manipulating complex, potentially nested, data structures.
266
+
There are two different data structures for working with key-value stores in Elixir. Alongside the `Access` module and pattern matching, they provide a rich set of tools for manipulating complex, potentially nested, data structures.
254
267
255
268
As we conclude this chapter, the important to keep in mind is that you should:
256
269
257
270
* Use keyword lists for passing optional values to functions
258
271
259
-
* Use maps for general key-value data structures and when working with known data (by using maps with fixed keys)
272
+
* Use maps for general key-value data structures
273
+
274
+
* Use maps when working with data that has a predefined set of keys
0 commit comments