Implementing conditional logic in functional pipes

Since the logical flow is quite linear, how do we deal with conditional logic?

Suppose we want to determine the hotness of top stories by checking the average score against a threshold. If the average score is higher than 100, then it would be considered high; otherwise, it would be considered low. So, literally, we need an if-statement that determines what to execute next.

We can use dynamic dispatch to solve this problem. We are going to build this function from the bottom-up, as follows.

  1. Create the hotness function, which determines the hotness of the Hacker News site by score. It returns an instance of the Val{:high} or Val{:low} parametric type. The built-in Val data type is a convenient way to create new parametric types that can be used for dispatch purposes:
hotness(score) = score > 100 ? Val(:high) : Val(:low)
  1. Create two celebrate functions with respect to the Val parametric types. They simply use the logx function to print some text. We call it with the value of v so that the hotness argument is passed downstream if we ever want to do more work after celebration:
celebrate(v::Val{:high}) = logx("Woohoo! Lots of hot topics!")(v)
celebrate(v::Val{:low}) = logx("It's just a normal day...")(v)
  1. Build the check_hotness function, which uses a functional pipe pattern. It uses the average_score3 function to calculate the average score. Then, it uses the hotness function to determine how to change the execution path. Finally, it calls the celebrate function via the multiple dispatch mechanism:
check_hotness(n = 10) =
average_score3(n) |> hotness |> celebrate

Let's test this out:

This simple example demonstrates how conditional logic can be implemented in functional pipe design. Of course, in reality, we would have more complex logic than just printing something to the screen. 

An important observation is that functional pipes only handle linear execution. Hence, whenever the execution splits conditionally, we would form a new pipe for each possible path. The following diagram depicts how an execution path may be designed with functional pipes. Each split of execution is enabled by dispatching over the type of a single argument:

Functional pipes look fairly simple and straightforward from a conceptual point of view. However, they are sometimes criticized for having to pass intermediate data between each component in the pipe, causing unnecessary memory allocation and slowness. In the next section, we will go over how to use broadcasting to overcome this issue.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.140.5