Interoperates with JARs and .NET libraries ◦ "There is an elephant in the room called all the code we have already written." - Rich Hickey • C# + Lisp + Java + "closure" = Clojure
of mutable data objects • Cannot enforce communication of settings changes to observers • Forces serialization of entire settings collection to ensure capture of all changes • Threadsafe?
parens a lot) • Everything is a list • First element in list is in the operator position and indicates the function to call on the elements that follow ◦ Example: (+ 2 3 4)
output set that does not change the input • Note that these are the same rules as LINQ • Defined using the defn macro or the fn function (defn square [x] (* x x)) (square 2) => 4
at least one function as a parameter ◦ Returns a function public static IEnumerable<TSource> Where<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate ) Clojure equivalent: (filter pred coll) (filter even? (range 10)) => (2 4 6 8)
=> x > 3 ◦ (x,y) => x * y • In Clojure, uses # expressions: ◦ #(> % 3) ◦ #(* %1 %2) • Note that % matches the first parameter, and %1 and %2 are positional parameters
data structure in Clojure (and other Lisps) • Makes it easy to write code that modifies other code • Makes the translation into an AST easier to visualize
a statement before it gets to the compiler • It happens during the evaluate step of REPL • Adds expressiveness, and can be used to build DSLs • In traditional Lisps, naming conflicts can occur across libraries, but...
namespaces to avoid naming collisions • Macros should be used infrequently compared to functions (defmacro when "Evaluates test. If logical true, evaluates body in an implicit do." {:added "1.0"} [test & body] (list 'if test (cons 'do body)))
bytecode, even during the REPL ◦ Maintains awesome performance of the platform • But copying all that data is expensive right? ◦ Since everything is part of a list in Clojure, everything can be represented in trees. ◦ You can copy the change from a node into a new tree that shares most of the nodes with the original data tree. ◦ This is cheap in both space & time complexity.
) is one of the most commonly used operators • Clojure equivalent is two-fold: -> and ->> • "Pushes" output to the first and last argument of next statement, respectively ◦ ->> is exactly equivalent to |>
for an old problem. The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g., no casts). - Philip Wadler Source: http://homepages.inf.ed.ac. uk/wadler/papers/expression/expression.txt