Introduction to Elm, v2 Containers
Transcript from the "Containers" Lesson
>> Richard Feldman: Now let's look at this TagFeed, and think about, how are we gonna actually represent the particular tag that you have selected? Well, right now the way that we're doing that is we have a tab which is going to now be of type Tab. And then we have, you may recall from our previous exercises, this string called selectedTag.
[00:00:19] And when you click on one of the tags, we made it so that selectedTag gets updated to be whatever that particular string is of the tag that you clicked on. But if you think about it, selectedTag only makes sense if you've actually selected a tag. If I click on one of these, the new behavior's going to be, we want to switch to a tag feed and set selected tag.
[00:00:41] But if I switch to global feed or your feed, we wanna deselect the tag. We no longer want to have any selected tag. So what are we gonna do with this value? Well it's still there on the model, so we could clear it out, we could make it be empty string if you don't have a particular tag selected.
[00:00:57] Or we could just have it be there and just stale and just try to ignore it. But it'd be nice if it were sort of only there in context. In other words, it were only possible to have a selected tag when we're actually showing the tag feed. Because those two are linked, it would be nice to link them in our data model.
>> Richard Feldman: So how can we link them? Well, like this. We can actually add a parameter to TagFeed that says TagFeed not only specifies that we're on that particular type of feed. But also, there's some additional information in there. There's a string that goes along with that. So if we do it this way, then TagFeed goes from being a value of type tab to a function that returns a tag.
[00:01:41] So if we were in Elm REPL, we would call that function like this. We would call TagFeed, this is now a function with a capital letter at the beginning, first time we've seen that. Call TagFeed, passing the string "happiness", and now it will give us back one of these TagFeeds that's got that string of "happiness" inside of it, and that is of type Tab.
[00:02:01] If we were to just pass TagFeed directly into Elm REPL, it would say, what you've got there is a function which takes a String and returns a Tab. In contrast, if we put your feed in there, it's gonna say that's a Tab global feed, that's a tTab, TagFeed that's a function.
>> Richard Feldman: Okay, so here's how those sort of relate. If I say yours, that is of type Tab, that's YourFeed. Happiness is a Tab, to get one of those, if I want to get a Tab value I have to get call TagFeed passing happiness. Okay, so once I've done that I've obtained this TagFeed that has this string stored inside of it, here's how we get it back out.
[00:02:40] Same case expression as before, but now we've added something to the TagFeed case. We're saying TagFeed space and then a lower case letter variable name selectedTag. I happened to decide to name it selectedTag right now. This works a lot like function arguments. Except sort of in reverse, where we're saying, I have a value that holds onto this thing, I wanna extract that value and give it a name.
[00:03:08] Pull out that string and say, from now on, inside the scope of this branch of the case expression, we now have a thing called selectedTag and it is that string, we can now work with that. So based on this, we can say in the case of YourFeed, we don't have that selectedTag string, it doesn't exist.
[00:03:27] GlobalFeed, same thing, does not exist, can't possibly access it. We only have that selectedTag accessible if we're on the TagFeed. In which case, we have it and we name it. This is why there's a distinction between capitalized and uncapitalized things in Elm. IF we had TagTeed and then a capital S SelectedTag, what we'd be saying is I have a tag feed which contains some custom type variant called SelectedTag.
[00:03:55] Lower case means it's a variable. I am giving this a new name, and just like all other variables, function, arguments, etc, that all have lowercase names. I am saying, yeah, I am not saying that this is a particular value, I am saying I do not know what that value is but give it this name and I am gonna do something with it.
[00:04:11] So we have essentially gone from having Tab be an enumeration, which is what it was before, now it's a container. It's a container that situationally holds additional information, only in the case that we're on a TagFeed. But as you can imagine, we can do a lot more custom stuff than even this.
[00:04:28] We could give TagFeed multiple values that it's storing. We could have TagFeed store a record. We could have GlobalFeed store a record or a list of records. Any combination of things that we want, any of these can specify as much or as a little data as they want to hold on to.
[00:04:45] We can sort of make custom shapes for our data to fit our use case perfectly, and to do things like linking up this relationship between the selectedTag, and which tab we're on at the data model level. Cool, so Evan the creator of Elm wrote that he considers custom types to be the most important feature in Elm.
[00:05:07] And as we'll see in the advanced workshop, there's a pretty deep rabbit hole of like implications and really cool stuff you can do with just the stuff that we just learned. We're not gonna dive into that rabbit hole today, because this is the intro course. But it's worth knowing I think, that there's quite a lot of cool stuff that you can do with this that's not necessarily obvious given how simply we're using it here.