Functional compositions are purposely opaque, with no obvious way to "visualize" the data as it transforms. This is great when our function works, as it's hard to add bugs, but challenging when our compositions aren't correct. This lesson teaches you how to debug functional compositions by writing and using a trace()
function to log out our values as they transform. This allows us to continue using pointfree programming while also providing a view into our compositions.
Instructor: [00:00] Compositions of pure point free functions can often be opaque and difficult to debug. Let me illustrate that with an example. I'm going to create a function slugify that will take these book titles and turn them into URL slugs. I'm going to purposefully put a bug in the code. Now let's try logging out the result. We get a huge error.
[00:31] What we see is that string.toLowercase is not a function, which probably means that when we get to lower case, the value getting passed in isn't a string. What we need is a function that gives us a side-effect of being able to log out the current value.
[00:47] We can do this by creating a trace function. Trace receives a message as its first augment, and then the value getting passed to it, and now we're going to use the comma operator to log out our message and value, and return the value.
[01:02] Now we can place traces before and after functions in our composition in order to see the value transform step by step. We'll place a trace before we split. Remember with compositions we work from right to left, or bottom to up, hence why that one's before.
[01:21] We'll call this one afterSplit, and finally we'll put one after lower case. We'll save this and run it in the terminal again. We still got our error, but now we can see a little more information about what's taken place.
[01:36] Before split we have our array of book titles, and after split we actually have a two-dimensional array. What happened was that split took our strings. Split them at spaces, and made them arrays themselves, and our map.lowercase isn't working, because lowercase expects a string, and what it's getting is an array.
[01:56] What we can do is reverse the arguments that we have of map.split and map.lowercase. Now I'll rename my trace functions, I'll save it, and I'll run it again. All right, we didn't get an error, but I didn't get slugs at the bottom either. Let's look at our trace one more time.
[02:15] Before lowercase we have the array of titles like we would expect. After lowercase, we still have a one-dimensional array of lowercase strings. After the split, it looks like we now have a two-dimensional array each one was split at their space, and now we have each string individually.
[02:34] What happened when we called join on this array, is we actually put the hyphen between the last and the first values of each array. What we need to do, is we need to call a map.onJoin as well. We'll come back to our code, we'll add map here, we'll save this, and we'll run our code again.
[02:52] You can see we now have an array of slugs exactly like we expected. We can now clean up our traces knowing that our function works the way we expected. Save it, run it, nothing should have changed, we still have our array. Now you might notice we're calling map on all of these, so how could we make this better?
[03:10] We can make a composition of the functions and pass it once into map. We'll save that, and we'll run it in our terminal, and we get the same answer.