Lab: Kick Forward Style in JavaScript

Kick Forward style in JavaScript - Introduction

In this lab you will implement a solution of the Kick Forward style in JavaScript for the term frequency task.

(The unchanged task description is available in the Prelude of the first lab.)

These are the constraints for the Kick Forward style as specified in the book:

Variation of the Pipeline style, with the following additional constraints:

  • Each function takes an additional parameter, usually the last, which is another function.
  • The function parameter is applied at the end of the current function.
  • The function parameter is given, as input, what would be the output of the current function.
  • The larger problem is solved as a pipeline of functions, but where the next function to be applied is given as a parameter to the current function.

The goal of this lab is to write code that follows the Kick Forward style.

Create and Clone Your GitHub Repository

To create the repository for this lab, fork this starter repository.

Your repository now exists on the GitHub servers. If you want to work on it, you first have to “clone” it on your computer.

Implement Your Program

You can find Crista’s Python implementation of the Term Frequency task in Kick Forward style in her GitHub repository:

https://github.com/crista/exercises-in-programming-style/tree/master/09-kick-forward


⚠️ WARNING ⚠️

While Crista’s implementation follows all the constraints above, it also suffers from a shortcoming.

Take a look at the implementation of the function read_file, which is the first function to be called at line 52. The function parameter (func) is called (“applied”) not only passing the data resulting from the computation, but also with a reference to the function that should be called after that one (normalize).

This makes it impossible to reuse any function outside the prescribed order in the sequence of calls (e.g., when implemented like that, read_file cannot be called from remove_stop_words). On top of that, it makes hard to implement those functions, as one needs to think about which function has to be called “two steps ahead”. Try to trace (mentally, or with the help of a debugger, or with debug prints) Crista’s implementation to verify that it actually works. You will realize that it is not trivial.

Here is a better, well-known alternative that respects all the constraints of the Kick Forward style and does not require to hard-code the sequence in the functions’ implementations. Consider this variation of Crista’s read_file, which simply calls func with the result of the computation:

def read_file(path_to_file, func):
    with open(path_to_file) as f:
        data = f.read()
    func(data)

What should we use as an argument​ for func? We need a function that takes in the result of the computation (i.e., the content of the file, in this case) and passes it to the appropriate next function. Given that this is a one-off job, we can conveniently use an anonymous function​:

# The main function
read_file(
  sys.argv[1],
  lambda file_content: filter_chars(file_content, ...)
)

If you want, you can use Crista’s implementation as a starting point for your JavaScript code (but be mindful of the warning). You can also make use of the functions’ implementations you wrote for the JavaScript Pipeline lab (or the code snippets provided in the description of that lab).

Once you have the repository (a directory) on your computer, you can open it in your IDE (e.g., in VS Code). You can easily do this using the code command, passing as an argument the path to the appropriate directory:

code ~/lab-03-kickforward-javascript

Before you start “hacking”, please read the README (file README.md).

Then create a new JavaScript file named TermFrequency.js.

Implement a solution to the term frequency task in JavaScript following the Kick Forward style.

Run, Test, and Debug the Program

Read the README.md and the first part of this lab to figure out how to run the program.

Test

We strongly recommend to use the test script, because it shows you whether your solution is functionally correct. For this, it compares your output with the reference output we provided. Obviously, this only works if you strictly follow the rules (e.g., don’t print out debug output), otherwise the script will tell you that you don’t produce the correct output.