Presentation is loading. Please wait.

Presentation is loading. Please wait.

Important Concepts from Clojure

Similar presentations


Presentation on theme: "Important Concepts from Clojure"— Presentation transcript:

1 Important Concepts from Clojure
14-Nov-18

2 Abstract syntax trees Compilers turn source code into ASTs (Abstract Syntax Trees) This is a major first step in virtually all compilers and interpreters Lisp/Clojure syntax is an AST

3 Basic functional programming
Functions are values (“first-class objects”) May be passed as parameters to other functions May be returned as the result of a function call May be stored in variables or data structures Functions have no side effects Given the same parameters, a function returns the same result Referential transparency: The result of a function call may be substituted for the function call Data is immutable and persistent Immutable data makes concurrency much easier Persistent means that structure is shared

4 Recursion Loops and recursion are equivalent in power
Anything that can be done with a loop can be done recursively, and vice versa If a function is tail-recursive, it can be automatically turned into a loop (thus saving stack frames) Tail recursion is when the recursion is the last thing done in every branch of the function Loops are less useful when data is immutable Loops are used primarily to modify data When data is immutable, the substitution rule applies: Any variable or function call may be replaced by its value The substitution rule simplifies reasoning about programs

5 Tail call elimination Recursive functions can often be rewritten to be tail recursive This is done by creating a helper function that takes an additional “accumulator” parameter Non-tail recursive function to find the factorial: (defn factorial-1 [n] (if (= n 1) (* n (factorial-1 (dec n))) ) Tail recursive function to find the factorial: (defn factorial ([n] (factorial-2 1 n)) ([acc n] (if (= n 1) acc (recur (* n acc) (dec n)) ) ) )

6 Higher-order functions add expressiveness
A higher-order function is a function that takes a function as an argument, returns a function as its vallue, or both Of course, higher-order functions do not increase the number of things that can be computed Any Turing complete language can compute anything that can be computed It doesn’t take much for a language to be Turing complete Higher-order functions can take the place of explicit recursions (or explicit loops) Using higher-order functions typically makes code shorter and clearer

7 Common higher-order functions
Almost every functional languages has these features and functions: Anonymous (literal) functions, so a function doesn’t have to be defined independently, but can be placed directly as an argument to a higher-order function (map function sequence) applies the function to each element of the sequence, yielding a sequence of the results (filter predicate sequence) applies the predicate to each element of the sequence, yielding a sequence of the elements that satisfy the predicate (reduce initial-value binary-function sequence) applies the binary-function to each pair of elements of the sequence, starting with aninitial-value , and yielding a single value List comprehensions combine and may simplify the above user=> (for [x (take 10 (iterate inc 1))] (* x x)) ( )

8 Closures When a function definition uses variables that are not parameters or local variables, those variables are “closed over” and retained by the function The function uses those variables, not the value the variables had when the function was created user=> (defn rangechecker [min max] (fn [num] (and (>= num min) (<= num max))) ) #'user/rangechecker Notice that the function being returned gets the values of min and max from the environment, not as parameters user=> (def in-range? (rangechecker 0 100)) #'user/in-range? user=> (in-range? 101) false

9 Currying and function composition
Currying is absorbing a parameter into a function to make a new function user=> (def hundred-times (partial * 100)) #'user/hundred-times user=> (hundred-times 3) 300 Function composition is combining two or more functions into a new function user=> (def third (comp first rest rest)) #'user/third user=> (third [ ]) 3

10 Persistence and laziness
A persistent data structure is one that is itself immutable, but can be modified to create a “new” data structure The original and the new data structure share structure to minimize copying time and wasted storage A lazy data structure is one where parts of it do not exist until they are accessed They are implemented (by Clojure) as functions that return elements of a sequence only when requested This allows you to have “infinite” data structures

11 Macros, metaprogramming, homoiconicity
A macro is like a function whose result is code Arguments to a macro are not evaluated Macro calls are evaluated at compile time The return value of a macro should be executable code Metaprogramming is using programs to write programs This is the primary use of macros in Clojure Macros are used to implement DSLs (Domain Specific Languages) Homoiconicity is when there is no distinction between code and data Homoiconicity greatly simplifies metaprogramming

12 The End


Download ppt "Important Concepts from Clojure"

Similar presentations


Ads by Google