Refactor imperative code to a single composed expression using Box

Brian Lonsdorf
InstructorBrian Lonsdorf
Share this video with your friends

Social Share Links

Send Tweet
Published 8 years ago
Updated 6 years ago

We refactor 3 functions, taking line by line imperative code to a single composed expression using Box container type.

[00:01] Let's look at another example. Here, we have money to float -- it's a nested little expression here -- our percent to float, and applied discount. Applied discount is going to take a string of money and a string of a percentage, and return us what the discount will be. It turns each one into its appropriate float, and then runs a little calculation.

[00:19] We run this. We get four, which is four dollars. It's 20 percent discount of five. Now, what we're going to do here is replace each of these with box. We're going to re-factor these functions. Let's start with money to float.

[00:32] Money to float, if we rewrite it down here and look at this above one for reference, let's start out by putting our string in a box. We can map over it and take our string and call replace. This is the first thing that happens. Map over that and replace.

[00:45] Finally, we will do a fold here as our last part of the chain with our replaced string. We'll get it fold out. These two are equivalent, and you may be asking yourself, "Why is the bottom one better?"

[00:56] That's not always better, but it has un-nested this expression. That's part of what box is good at, is un-nesting expressions like composition, because map is a type of composition. Here, not a big one, but it's good practice. We don't always want to use box. We can use it in certain situations. That was money to float.

[01:13] Let's do the same with percent to float. Here, we have a lot of assignments. We're going to use box to replace this assignment, because as we can see we're capturing assignment with our box.

[01:21] Let's copy this as a template here and the first part of our new function. Instead of actually starting off with a box of string, let's go ahead and start with a box of this whole string replaced.

[01:32] We don't need to start with a string and then map over it. We can go straight from the first expression here. We'll call it replaced, capture that assignment above up here. We're mapping over it. It gets passed right in. We'll call parseFloat on our replaced. Finally, we will fold out our last expression from the box. We'll capture that number assignment, and we'll multiply that by 001.

[01:52] There we go, percent to float check. We've rewritten this in one expression. That's nice and clear data flow [inaudible] variables, and bits and pieces lying about. Let's get rid of these old functions there.

[02:05] Finally, with applied discount, this is the big, challenging one. Now, the thing that's interesting is we have two different assignments being used at once, and we want to keep both variables in scope.

[02:15] Let's see how to do that. We'll copy the same template. We'll start with money to float right here. Now, I'm going to want to put this in a box. If you remember, money to float right up here, we actually called fold to remove it from the box.

[02:29] Since we want to keep mapping over it down here, why don't we go ahead and leave in the box by calling map? We'll do the same with percent to float, because I know I'm going to need to map over this one as well.

[02:38] We don't need to remove them from the boxes altogether. We'll have them right after calling the function. This is just a decision for this one part. Sometimes, you want to remove it, sometimes you don't.

[02:47] Money to float, that returns us a box, and we'll capture the savings or the cost here, pardon me. We want to call percent to float with our discount.

[02:58] Notice how we have cost captured in the closure here. We can continue on capturing more and more variables by just nesting in these closures. Finally here, we will pass both our variables to this little calculation, and we should be done. There we go.

[03:15] That's how we can work with multiple variables in a box. It's by nesting with closures here. We'll comment this out, so it doesn't get mad at us. We can remove it altogether.

[03:32] One problem with this approach is we're calling map on each. The result is going to be two boxes deep. It doesn't even show the second box here, but if we were to fold up here, we will still have this inner box.

[03:38] We had a box within a box of the result four. That's something to be aware of to be able to remember how many levels deep we're on. It's good to see. We have two assignments, so we have two boxes.

[03:47] A fold in the fold, and there's our result four. If we look at our finished product here, we have three expressions all using box, and they're capturing this linear control flow.

[03:58] As you can see, variable is being introduced. You see the indentation moving inward, so you can keep track of the state that's going on. Here, we have two. We will learn some tricks to get rid of this expression. It's good to see what's going on here. Does anybody have any questions?

[04:11] I still don't understand what box does.

[04:15] Box alone doesn't do much. It basically captures something in a context. We can keep mapping, and folding, and composing in different ways around it.

[04:23] As we'll see, there are stronger things in box. They will give us behaviors associated with composition and new ways to compose. This is good practice to work on something as simple as a structure as box that has no added behaviors, and we can practice composing with it.

[04:36] Don't worry. There will be some uses for this style of programming instead of just changing one thing to the other. I hope you learned a lot. Next up, we will learn about Either.