Surveying the function landscape

In order to accomplish everything we've spoken about so far, let's take a step back and explore some functions to traverse data, branching, and conditional dispatch, and other first order functions. The Clojure cheatsheet is a good location for a bird's-eye view of different categories of functions. Their official documentation can be found at http://clojure.org/cheatsheet.

Traversing data

Recursion in computer science is a technique where a function continuously calls itself until some decision point is reached (you can read more about this technique at https://en.wikipedia.org/wiki/Recursion_(computer_science)). This is useful when the same block of code needs to be run against successive or iterative contexts.

The reduce function is used when we have a finite list that we need to collect or fold up into a result value.

Clojure also has the repeatedly function, which continuously calls a function with no arguments. There's also iterate, which is a single argument function that takes its results and successively calls the same function on successive results.

These options constrain the number and evaluation of input arguments. If more input arguments are needed, you also have the option of simply recalling your same function over and over again until some condition is reached. However, this has some internal side effects where a resource called stack is consumed. The loop function (technically a macro) lets us recur over a block of code without consuming this stack. It also has the benefit of allowing us to set a different recursion point in our code. Paired with loop is the recur function (also a macro) that evaluates a set of expressions, goes back to the recursion point (set by the preceding loop function), and binds these results in a source binding location. The recur operator can also be used outside loop where it will just call the available recursion point, which would be the function itself.

List comprehensions in computer science are ways of creating new lists from previous lists. The map, filter, and so on, are the functions which generally let us create a new list from a source list using one condition or pass over the source data. Clojure's for comprehension lets us take an arbitrary number of lists and create a new result list based on one or more conditionals or modifiers.

Branching and conditional dispatch

The macros, case and cond, are two straightforward ways of making a decision. case is a macro that looks at one value (scalar or composite) and tries to find a matching pair in the following body. This is a good option when there's a single known Var and we want to take different actions based on its value. cond, on the other hand, is a macro that simply tries to find a true condition in a series of pairs. It can be used when you need to meet a condition between several competing predicate values.

Multimethods let us add decision points (or dispatches) in our code based on any attribute of a value, such as its type, metadata, and so on. This functionality, called runtime polymorphism, is provided by Clojure's defmulti and defmethod macros.

Pattern matching in computer science is a language feature that lets us check a set of values for a particular pattern. Dispatch of a particular kind of code occurs when a pattern is matched. Clojure's core.match is a third-party library that implements pattern matching as an add-on to the language. This, again, is made possible by macros, which rewrite the code on the fly. It's another example of a little language being embedded into the main one.

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

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