Namespaces and creating our first function

We now have the basis to create a function. It will return a lazy infinite sequence of floating point numbers within an upper and lower bound. defn is a Clojure function that takes an anonymous function and binds a name to it in a given namespace. A Clojure namespace is an organizational tool used to map human readable names to things, such as functions, named data structures, and so on. Here, we're going to bind our function to the generate-prices name in our current namespace. You'll notice that our function is starting to span multiple lines. This will be a good time to author the code in your text editor of choice. I'll be using Emacs (you can read more about Emacs at https://en.wikipedia.org/wiki/Emacs):

  1. Open your text editor and add this code to the file called src/edgar/core.clj. Make sure that (ns edgar.core) is at the top of this file.
  2. After adding the following code, you can then reload the code in your REPL. (load "edgaru/core") uses the load function to load the Clojure code in src/edgaru/core.clj:
      (defn generate-prices [lower-bound upper-bound]
          (filter (fn [x] (>= x lower-bound))
                  (repeatedly (fn [] (rand upper-bound)))))

The Read-Eval-Print-Loop

In our REPL, we can pull in code in various namespaces with the help of the require function. This applies to the src/edgar/core.clj file we've just edited. Here is the code in the edgar.core namespace:

  1. In your REPL, evaluate (require '[edgar.core :as c]); c is just a handy alias we can use instead of the long name.
  2. You can then generate random prices within an upper and lower bound. Take the first 10 of them (take 10 (c/generate-prices 12 35)).
  3. You should see results akin to the following output. All elements should be within the range of 12 to 35:
      (29.60706184716407 12.507593971664075 19.79939384292759 31.322074615579716 19.737852534147326 25.134649707849572 19.952195022152488 12.94569843904663   23.618693004455086 14.695872710062428)
    

    Here's a sample graph output (your data may vary):

    The Read-Eval-Print-Loop

There's a subtle abstraction in the preceding code that deserves attention. (require '[edgar.core :as c]) introduces the quote symbol. ' is the reader shorthand for the quote function. So, the equivalent invocation would be (require (quote [edgar.core :as c])). Quoting a form tells the Clojure reader not to evaluate the subsequent expression (or form). Therefore, evaluating '(a b c) returns a list of 3 symbols without trying to evaluate any part of that form. Even though these symbols haven't yet been assigned, it's okay because this expression (or form) has not yet been evaluated.

But, this begs a larger question. What is the reader? Clojure (and all Lisps) are what's known as homoiconic (you can read more about it at http://en.wikipedia.org/wiki/Homoiconicity). This means that Clojure code is also data and data can be directly output and evaluated as code. The reader is what parses our src/edgar/core.clj file (or the (+ 1 1) input from the REPL prompt) and produces data structures that are evaluated. read and eval are the two essential processes by which Clojure code runs. The evaluation result is printed (or output) to the standard output device usually. Then, we loop the process back to the read function. So, when REPL reads your src/edgar/two.clj file, it directly transforms this text representation into data and evaluates it. A few things fall out of this. For example, it becomes trivial for Clojure programs to directly read, transform, and write out other Clojure programs. The implications of this will become clearer when we look at macros. But for now, know that there are ways to modify or delay the evaluation process, in this case by quoting a form.

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

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