Introduction to Elm, v2

Function Guarantees, Randomness, & Commands

Richard Feldman

Richard Feldman

Vendr, Inc.
Introduction to Elm, v2

Check out a free preview of the full Introduction to Elm, v2 course

The "Function Guarantees, Randomness, & Commands" Lesson is part of the full, Introduction to Elm, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Every Elm function is deterministic in nature. Richard explains how Elm turns a Generator into a randomly value. To do this, a Command must also be introduced. Time is taken to map the Command message into the Elm Architecture model.


Transcript from the "Function Guarantees, Randomness, & Commands" Lesson

>> Richard Feldman: Let's move on and talk about some function guarantees that we have in Elm. So one guarantee that we have is every Elm function if you give it the same arguments you're gonna get the same return value no matter what. Same arguments, same return value no exceptions. So here's an example of a function in JavaScript that does not have that characteristic.

You call Math.random with the same argument or just say no arguments. You expect to get back a not the same result. In fact, if you didn't give back the same result, Math.random would be very boring and not useful. It's a very important property of that function that it gives you back different results every time you call it.

Or at least most of the time you call it. However, because elm has this guarantee, this can not possibly be the API for Elm's randomness. This just wouldn't work because it doesn't fit with Elm's guarantee. So, instead we have something called random.generate which works a little bit differently.

So to illustrate sort of how random.generate works and how it's different from math.random, let's say that we're going to implement a feature. So, you know how, like, in chat apps a lot of the time you'll start up the chat app and the first thing it'll do is it'll show you a randomly chosen greeting.

Like, hey, how's it going? Or, today's a nice day. Or, you should get outside more. Something like that. So let's see if we wanted to pick one of those at random to display to the user. Well just by the type of this function here, pickGreeting list string to string, I could tell you that this is not going to give me a different greeting every time I call it.

In fact I can be quite sure that if I give it the same list of greetings it's gonna choose the same one every single time, because again if you call an Elm function, pass the same arguments you have to get the same results every time, that's a rule of the language.

So if I call it passing the same fixed list of greetings, well, I'm just, every user is gonna see that same greeting every single time. It's unavoidable, that's just a design characteristic. So that sort of can't be how we're gonna do this. Okay, what we can do instead is we can do this.

pickGreeting takes a list of strings, sort of the pool of potential greetings to show the user, and it's gonna return a Cmd Msg. What is a command? Okay so going back to our Elm architecture diagram just a quick recap of how we've ended up where we are right now.

We saw model, view, and update and how they relate to one another, view returns some HTMLs such as like, you know, an h1 that has the text feed. Potentially those HTML values have handlers on them that respond to user inputs by sending messages through update. Initially we had our messages being described as records with description and data but we kinda saw that that didn't really scale very well.

So we ended up refactoring it a little bit later to this, where now we have custom types for this and variance that hold onto whatever additional metadata we need about the message that update's going to need to use with the current model to return a new model. Okay, that's where we are right now.

Commands essentially introduce something new to this. It gives update a new capability. So previously, all update could do is it would require a new model, and that's it. It would say, give me a message on the current model, and I will give you back the new model to transition to.

It's still gonna be able to do that in this new world we're about to move to, but it's gonna have one more addition capability. And it's gonna be based around this idea of the Msg. So Msg fundamentally its job is it's how the Elm Runtime talks to update.

Up to this point, the only thing it's had to say to update is here is some user interaction that happened, like the user clicked a thing. We saw on input in a previous exercise when the user was typing into a thing. Fundamentally, the only thing the Elm Runtime has had to say to update is, here is a piece of user interaction that happened.

Cmds introduce a second thing that the Elm Runtime can say to update. So this is something that goes essentially from update and then to the Elm Runtime and then the Runtime sends a message to update as a result of what update said to the Runtime. So whereas the user interaction case is coming from view, view it says here's my message that I want the Runtime to send to update in response to this user input.

Commands come from update. So this is update saying hey I want you, the Runtime, to go run this command. And when you're done, give me back this message, and I'll continue on from there. So, essentially, a command is a description of something that you want done. It's not a side effect, in the sense that, when you instantiate a command, nothing happens.

If you want, you can instantiate a thousand commands in a row inside update. Right away and nothing will happen as we lost any of them. It's basically just a description written down and saying, hey dear Runtime, please do this and then tell me about what happens. Thank you.

And when update returns, now it's going to return a tupple of the model, so just like before. So we're gonna still be returning the new model. As well as optionally some commands to run. And so the Runtime is gonna say okay I know what to do with the new model, do the same thing as before, pass it to view, continue that cycle.

But also when we look at this command you gave me, and the commands is gonna tell me possibly to do something, so what's we're building up to is we're going to use it for a http request, but in this case, we will also use if for randomness So random.generate gives us back a command message that says hey, Runtime, go randomly produce one of these values.

Randomly pick from one of these greetings. Yeah, you can choose a different one every time. I don't care, but when you're done, send me a message telling me which one you picked.
>> Richard Feldman: And so in this way we sort of isolated that unpredictable, that the side effect-y kind of element inside of the Runtime.

It's the Runtime's job to do all of that stuff. Update is not concerned with that. Update just says here is the description of what I want done, and every single time you call update with the same message and model you are 100% guaranteed to get back the same model as a result, or the same model value as a result and the same command value as a result.

So update itself still obeys this guarantee that Elm has. Same argument, same result. But we're still able to end up with a randomly selected greeting. So, as an example here we got pickGreeting, has a list of strings, it returns a command message-,update can call this function, return that command, and say, hey, Runtime, when you're done, give me back a SetGreeting5 message.

And I'm gonna process that the same way I would process any message that I got from the view.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now