Comparing Clojure with object orientation

Java is a class-based, object-oriented programming language. This object-oriented paradigm was developed in the late 1950s. It grew out of a need to reliably build larger, more complex systems than was previously possible using an imperative programming model (you can read more at https://en.wikipedia.org/wiki/Imperative_programming). Object orientation's original computation model focused on data encapsulation and object interaction through message passing versus imperative's model of statements that change the state of a program. These objects can be derived from classes, prototypes, or through some other mechanism. Object-oriented programming was first popularized in languages, such as Simula (you can read more at https://en.wikipedia.org/wiki/Simula) and Smalltalk (you can read more at https://en.wikipedia.org/wiki/Smalltalk). There are now many major languages that use this programming model, including Java.

It has statically and dynamically typed program elements. This means that you can inspect and dispatch (decide) based on the type of object at runtime. Java variable types are also checked at compile time. Let's take a look at a possible implementation of our simple-moving-average function using Java:

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Lagging {

    public Stream<Double> readPrices(String path) throws     URISyntaxException , IOException {
        return Files.lines(Paths.get(new URI(path)),         StandardCharsets.UTF_8)
                .map(Double::parseDouble);
    }

    public List listPrices(String path) throws URISyntaxException     , IOException {
        return this.readPrices(path).collect(Collectors.toList());
    }

    public List simpleMovingAverages(String pricesPath, int     tickWindow) throws URISyntaxException , IOException {

        List priceList = this.listPrices(pricesPath);
        List averageList = new ArrayList();

        int begin = 1;
        int end = tickWindow;
        while(end <= priceList.size()) {

            List currentWindow = priceList.subList(begin, end);
            Iterator iter = currentWindow.iterator();
            double total = 0d;
            while (iter.hasNext()) {
                total += (Double)iter.next();
            }

            averageList.add(total / tickWindow);

            begin++;
            end++;
        }

        return averageList;
    }

    public static void main(String[] args) throws     URISyntaxException , IOException {

        String pricesPath = "file:///Users/timothyw/Projects/LaggingJava/src/main/resources/prices.txt";
        int tickWindow = 20;
        Lagging lagging = new Lagging();

        List simpleMovingAverages =         lagging.simpleMovingAverages(pricesPath, tickWindow);
        System.out.println(simpleMovingAverages);
    }
}

The main method is the start point of the program. However, before we study it, notice that it exists inside the Lagging class. All program state and behavior must be created inside a class or similar structure (interface, abstract class, and so on). The idea is that the class is a template from which we create an actual thing called an object.

Static program elements are those that exist in the class or template itself, not its objects. This is the condition of the main method. After compiling this code, there will be a compiled Lagging representation that we can run from our computer. This is done by invoking the java runner (or runtime environment) and passing in the compiled Lagging representation. By default, the java runtime invokes the static main method on the class it is given. In this case, when run, main creates a string variable that represents the input file on a computer's hard drive. The Lagging lagging = new Lagging(); expression then creates a new Lagging instance or an object. The next expression, List simpleMovingAverages = lagging.simpleMovingAverages(pricesPath, tickWindow);, calls the simpleMovingAverages method on this object. The result is assigned to another object of the abstract List, type which is then printed to the console.

Just by studying the main method and its context, we see that classes and class instantiation is central to where Java places state and behavior. Diving into the simpleMovingAverages method, the first expression calls the listPrices method on the current object or the this reference. listPrices then calls out again to the readPrices helper method to pull in the pricelist.txt data file, divides it into a list of text lines, and then converts each element of this list into a numeric value of the java.lang.Double type.

The second expression, List averageList = new ArrayList();, simply creates a list that will be added to or mutated later on in the method. The next two expressions set up the begin and end states to be used to control the while loop. while loops are control structures in imperative and object-oriented languages that repeatedly execute code inside a block until some condition is met. In our case, we have two while loops. The first while(end <= priceList.size()) condition will execute everything inside its block, while the end variable is below or equal to the length (or size) of the price list. What this block is doing is taking a subset or window of the entire list and calculating the average for this window. The second while loop walks or iterates over the subset or currentWindow, using the Iterator type in order to sum all the numbers in this subset. Each time the outer while loop is executed, the average is calculated, the result placed into averageList, and the begin and end markers each increment forward until end hits the length of the list. When we run this class, the console printed averageList, has the average values we expect.

[6.971467579790411, 7.464540409139185, 8.010389878709972, 8.595550217357273, 9.199880686839014, 9.803134294595337, 10.391281772750983, 10.960810205584073, 11.519789847777256, 12.085410173832697, 12.657204984470962, 13.512979176946038, 14.336798333665858, 15.033597887711505, 15.93293648884989, 17.236687274535527, 18.017166796811743, 18.747178634896592, 19.36891681775512, 19.88107990363371, 20.352063482865127, 20.809990525663345, 21.292779590969797, 21.65720104327843, 21.88759572553658, 22.0960538285178, 22.522518975747712, 22.921023864595572, 23.300273299533917, 23.677893061861866, 23.791812046695554, 23.92261161858174, 24.13540925343312, 24.28043376993932, 23.99307801388237, 23.69529121331615, 23.444825362117815, 23.313832222382498, 23.30398859426755, 23.34531490845263, 23.386641222637703, 23.52694480589677, 23.67574694970999, 23.906119057816472, 24.25121614021084, 24.211544668391998, 24.23599987692504, 24.305644963968547, 24.243653669023793, 24.31898689789535, 24.369948081810513, 24.364340164808066, 24.518113870232213, 24.573545352458943, 24.63940787919494, 24.75959935515974, 24.806090418384898, 24.772532158349563, 24.774246735296167, 24.857257750991796, 24.765966922838224, 24.67207478924459, 24.61362131993375, 24.52537925344091, 24.58801417608733, 24.586522418381865, 24.532091262456568, 24.56313935471497, 24.393672293029404, 24.188468574045014, 24.05833078712983, 23.919361348321903, 23.947386025442054, 23.872246343092222, 23.637285378280023, 23.515604315240033, 23.594912277922973, 23.649875136387475, 23.505921609914147, 23.30230219819553, 23.255901647048383]

However, the way in which we've calculated this information, by manually sliding a current window through the length of the price list, is different from our original Clojure version. The Java version forces us to not just declare types for each program element. It's also a more manual process of managing how lists are processed and all the intermediate types and steps required in this traversal. Clojure's partition function lazily gave us a subset of an entire list. reduce walks over this list of lists to calculate the average value of each one. Nowhere did we manually manage the order of operations to walk a list. We simply gave calculation instructions at each step. This is what's meant by a more declarative style of programming (you can read more at https://en.wikipedia.org/wiki/Declarative_programming).

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

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