├── script ├── run.clj ├── test.clj ├── repl ├── run ├── test ├── test.bat ├── run.bat ├── repl.bat └── deploy.sh ├── .gitignore ├── project.clj ├── ideaboard.txt ├── src └── koans │ ├── sets.clj │ ├── equalities.clj │ ├── java_interop.clj │ ├── lazy_sequences.clj │ ├── functions.clj │ ├── atoms.clj │ ├── vectors.clj │ ├── lists.clj │ ├── sequence_comprehensions.clj │ ├── higher_order_functions.clj │ ├── creating_functions.clj │ ├── runtime_polymorphism.clj │ ├── refs.clj │ ├── macros.clj │ ├── datatypes.clj │ ├── conditionals.clj │ ├── recursion.clj │ ├── destructuring.clj │ └── maps.clj ├── README.md ├── resources └── koans.clj └── epl-v10.html /script/run.clj: -------------------------------------------------------------------------------- 1 | (require 'koan-engine.runner) 2 | (koan-engine.runner/exec "run") 3 | -------------------------------------------------------------------------------- /script/test.clj: -------------------------------------------------------------------------------- 1 | (require 'koan-engine.runner) 2 | (koan-engine.runner/exec "test") 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | classes 3 | lib 4 | releases 5 | *.jar 6 | .DS_Store 7 | .lein-deps-sum 8 | -------------------------------------------------------------------------------- /script/repl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | CLASSPATH=src 3 | 4 | for f in lib/*.jar lib/dev/*.jar resources/; do 5 | CLASSPATH=$CLASSPATH:$f 6 | done 7 | 8 | if [ "$OSTYPE" = "cygwin" ]; then 9 | CLASSPATH=`cygpath -wp $CLASSPATH` 10 | fi 11 | 12 | java -Xmx1G -cp $CLASSPATH jline.ConsoleRunner clojure.main 13 | -------------------------------------------------------------------------------- /script/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | CLASSPATH=src 3 | 4 | for f in lib/*.jar lib/dev/*.jar resources/; do 5 | CLASSPATH=$CLASSPATH:$f 6 | done 7 | 8 | if [ "$OSTYPE" = "cygwin" ]; then 9 | CLASSPATH=`cygpath -wp $CLASSPATH` 10 | fi 11 | 12 | java -cp "$CLASSPATH" clojure.main script/run.clj 13 | echo 14 | -------------------------------------------------------------------------------- /script/test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | CLASSPATH=src 3 | 4 | 5 | for f in lib/*.jar lib/dev/*.jar resources/; do 6 | CLASSPATH=$CLASSPATH:$f 7 | done 8 | 9 | if [ "$OSTYPE" = "cygwin" ]; then 10 | CLASSPATH=`cygpath -wp $CLASSPATH` 11 | fi 12 | 13 | java -cp "$CLASSPATH" clojure.main script/test.clj 14 | echo 15 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject functional-koans "0.4.5" 2 | :description "The functional koans." 3 | :dependencies [[org.clojure/clojure "1.3.0"] 4 | [koan-engine "0.1.2-SNAPSHOT"]] 5 | :dev-dependencies [[swank-clojure "1.3.0" :exclusions [org.clojure/clojure]] 6 | [lein-koan "0.1.0"]]) 7 | -------------------------------------------------------------------------------- /script/test.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setLocal EnableDelayedExpansion 3 | 4 | set CLASSPATH=" 5 | for %%j in (".\lib\*.jar", ".\lib\dev\*.jar") do ( 6 | set CLASSPATH=!CLASSPATH!;%%~fj 7 | ) 8 | set CLASSPATH=!CLASSPATH!" 9 | set CLASSPATH=%CLASSPATH%;src;resources 10 | 11 | java -Xmx1G -cp %CLASSPATH% clojure.main script\test.clj 12 | -------------------------------------------------------------------------------- /script/run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setLocal EnableDelayedExpansion 3 | 4 | set CLASSPATH=" 5 | for %%j in (".\lib\*.jar", ".\lib\dev\*.jar") do ( 6 | set CLASSPATH=!CLASSPATH!;%%~fj 7 | ) 8 | set CLASSPATH=!CLASSPATH!" 9 | set CLASSPATH=%CLASSPATH%;src;resources 10 | 11 | java -Xmx1G -cp %CLASSPATH% clojure.main script\run.clj 12 | 13 | -------------------------------------------------------------------------------- /script/repl.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setLocal EnableDelayedExpansion 3 | 4 | set CLASSPATH=" 5 | for %%j in (".\lib\*.jar") do ( 6 | set CLASSPATH=!CLASSPATH!;%%~fj 7 | ) 8 | set CLASSPATH=!CLASSPATH!" 9 | set CLASSPATH=%CLASSPATH%;src;resources 10 | 11 | set JLINE=jline.ConsoleRunner 12 | 13 | java -Xmx1G -cp %CLASSPATH% %JLINE% clojure.main 14 | 15 | -------------------------------------------------------------------------------- /ideaboard.txt: -------------------------------------------------------------------------------- 1 | Concepts / Language Features 2 | ===== 3 | Agents 4 | Vars 5 | state identity lifetime 6 | Metadata 7 | Tuples - syntax 8 | Pattern Matching 9 | immutability/side effects 10 | memoization 11 | trampolining 12 | reflection 13 | Java interop 14 | Protocols 15 | Deftypes 16 | DefRecords 17 | Pre and Post conditions of functions 18 | 19 | Particular Functions 20 | ===== 21 | vector-of 22 | flatten 23 | frequencies 24 | group-by 25 | keep 26 | keep-indexed 27 | map-indexed 28 | partition-all 29 | partition-by 30 | rand-nth 31 | reductions 32 | constantly 33 | repeatedly 34 | shuffle 35 | 36 | -------------------------------------------------------------------------------- /src/koans/sets.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "You can create a set in two ways" 3 | (= #{} (set __)) 4 | 5 | "They are another important data structure in clojure" 6 | (= __ (count #{1 2 3})) 7 | 8 | "Remember that a set is a 'set'" 9 | (= __ (set '(1 1 2 2 3 3 4 4 5 5))) 10 | 11 | "You can ask clojure for the union of two sets" 12 | (= __ (clojure.set/union #{1 2 3 4} #{2 3 5})) 13 | 14 | "And also the intersection" 15 | (= __ (clojure.set/intersection #{1 2 3 4} #{2 3 5})) 16 | 17 | "But don't forget about the difference" 18 | (= __ (clojure.set/difference #{1 2 3 4 5} #{2 3 5}))) 19 | -------------------------------------------------------------------------------- /script/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | git push 4 | mkdir -p releases 5 | zip -r releases/clojure-koans-`date +"%Y-%m-%d_%H-%M"`.zip \ 6 | . \ 7 | -x "./.git/*" \ 8 | -x "releases/*" 9 | 10 | echo 11 | echo "Don't forget to upload the zipfile" 12 | echo " to https://github.com/functional-koans/clojure-koans/downloads" 13 | echo `ls -t releases/clojure-koans-*.zip | head -n1` 14 | echo 15 | 16 | # TODO: use http://developer.github.com/v3/repos/downloads/ 17 | # to do the upload automatically 18 | # GET example: 19 | # curl https://api.github.com/repos/functional-koans/clojure-koans/downloads 20 | -------------------------------------------------------------------------------- /src/koans/equalities.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "We shall contemplate truth by testing reality, via equality." 3 | (= __ true) 4 | 5 | "To understand reality, we must compare our expectations against reality." 6 | (= __ (+ 1 1)) 7 | 8 | "You can test equality of many things" 9 | (= (+ 3 4) __ (+ 2 __)) 10 | 11 | "Some things may appear different, but be the same" 12 | (= 2 2/1 __) 13 | 14 | "You cannot generally float to heavens of integers" 15 | (= __ (= 2 2.0)) 16 | 17 | "But a looser equality is also possible" 18 | (== 2.0 2 __) 19 | 20 | "When things cannot be equal, they must be different" 21 | (not= :fill-in-the-blank __)) 22 | -------------------------------------------------------------------------------- /src/koans/java_interop.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "You may have done more with Java than you know" 3 | (= __ (class "warfare")) ; hint: try typing (javadoc "warfare") in the REPL 4 | 5 | "The dot signifies easy and direct Java interoperation" 6 | (= __ (.toUpperCase "select * from")) 7 | 8 | "But instance method calls are very different from normal functions" 9 | (= ["SELECT" "FROM" "WHERE"] (map ___ ["select" "from" "where"])) 10 | 11 | "Constructing might be harder than breaking" 12 | (= 10 (let [latch (java.util.concurrent.CountDownLatch. __)] 13 | (.getCount latch))) 14 | 15 | "Static methods are slashing prices!" 16 | (== __ (Math/pow 2 10))) 17 | -------------------------------------------------------------------------------- /src/koans/lazy_sequences.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "There are a wide range of ways to generate a sequence" 3 | (= __ (range 1 5)) 4 | 5 | "The range starts at the beginning by default" 6 | (= __ (range 5)) 7 | 8 | "It's important to only take what you need from a big sequence" 9 | (= [0 1 2 3 4 5 6 7 8 9] 10 | (take __ (range 100))) 11 | 12 | "You can also limit results by dropping what you don't need" 13 | (= [95 96 97 98 99] 14 | (drop __ (range 100))) 15 | 16 | "Iteration provides an infinite lazy sequence" 17 | (= __ (take 20 (iterate inc 0))) 18 | 19 | "Repetition is key" 20 | (= [:a :a :a :a :a :a :a :a :a :a ] 21 | (repeat 10 __)) 22 | 23 | "Iteration can be used for repetition" 24 | (= (repeat 100 :foo) 25 | (take 100 (iterate ___ :foo)))) 26 | -------------------------------------------------------------------------------- /src/koans/functions.clj: -------------------------------------------------------------------------------- 1 | (defn multiply-by-ten [n] 2 | (* 10 n)) 3 | 4 | (defn square [n] (* n n)) 5 | 6 | (meditations 7 | "Functions are often defined before they are used" 8 | (= __ (multiply-by-ten 2)) 9 | 10 | "But they can also be defined inline" 11 | (= __ ((fn [n] (* __ n)) 2)) 12 | 13 | "Or using even shorter syntax" 14 | (= __ (#(* 15 %) __)) 15 | 16 | "Short anonymous functions may take multiple arguments" 17 | (= __ (#(+ %1 %2 %3) 4 5 6)) 18 | 19 | "One function can beget another" 20 | (= __ ((fn [] 21 | ((fn [a b] (__ a b)) 22 | 4 5)))) 23 | 24 | "Higher-order functions take function arguments" 25 | (= 25 (___ 26 | (fn [n] (* n n)))) 27 | 28 | "But they are often better written using the names of functions" 29 | (= 25 (___ square))) 30 | -------------------------------------------------------------------------------- /src/koans/atoms.clj: -------------------------------------------------------------------------------- 1 | (def atomic-clock (atom 0)) 2 | 3 | (meditations 4 | "Atoms are like refs" 5 | (= __ @atomic-clock) 6 | 7 | "You can change at the swap meet" 8 | (= __ (do 9 | (swap! atomic-clock inc) 10 | @atomic-clock)) 11 | 12 | "Keep taxes out of this: swapping requires no transaction" 13 | (= 5 (do 14 | __ 15 | @atomic-clock)) 16 | 17 | "Any number of arguments might happen during a swap" 18 | (= __ (do 19 | (swap! atomic-clock + 1 2 3 4 5) 20 | @atomic-clock)) 21 | 22 | "Atomic atoms are atomic" 23 | (= __ (do 24 | (compare-and-set! atomic-clock 100 :fin) 25 | @atomic-clock)) 26 | 27 | "When your expectations are aligned with reality things, proceed that way" 28 | (= :fin (do 29 | (compare-and-set! __ __ __) 30 | @atomic-clock))) 31 | -------------------------------------------------------------------------------- /src/koans/vectors.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "You can use vectors in clojure to create an 'Array' like structure" 3 | (= __ (count [42])) 4 | 5 | "You can create a vector in several ways" 6 | (= __ (vec nil)) 7 | 8 | "And populate it in either of these ways" 9 | (= __ (vec '(1))) 10 | 11 | "There is another way as well" 12 | (= __ (vector nil)) 13 | 14 | "But you can populate it with any number of elements at once" 15 | (= [1 __] (vec '(1 2))) 16 | 17 | "And add to it as well" 18 | (= __ (conj (vec nil) 333)) 19 | 20 | "You can get the first element of a vector like so" 21 | (= __ (first [:peanut :butter :and :jelly])) 22 | 23 | "And the last in a similar fashion" 24 | (= __ (last [:peanut :butter :and :jelly])) 25 | 26 | "Or any index if you wish" 27 | (= __ (nth [:peanut :butter :and :jelly] 3)) 28 | 29 | "You can also slice a vector" 30 | (= __ (subvec [:peanut :butter :and :jelly] 1 3)) 31 | 32 | "Equality with collections is in terms of values" 33 | (= (list 1 2 3) (vector 1 2 __))) 34 | -------------------------------------------------------------------------------- /src/koans/lists.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "Lists can be expressed by function or a quoted form" 3 | (= '(__ __ __ __ __) (list 1 2 3 4 5)) 4 | 5 | "They are Clojure seqs (sequences), so they allow access to the first" 6 | (= __ (first '(1 2 3 4 5))) 7 | 8 | "As well as the rest" 9 | (= __ (rest '(1 2 3 4 5))) 10 | 11 | "The rest when nothing is left is empty" 12 | (= __ (rest '(100))) 13 | 14 | "And construction by adding an element to the front is simple" 15 | (= __ (cons :a '(:b :c :d :e))) 16 | 17 | "Conjoining an element to a list can be done in the reverse order" 18 | (= __ (conj '(:a :b :c :d :e) 0)) 19 | 20 | "You can use a list like a stack to get the first element" 21 | (= __ (peek '(:a :b :c :d :e))) 22 | 23 | "Or the others" 24 | (= __ (pop '(:a :b :c :d :e))) 25 | 26 | "But watch out if you try to pop nothing" 27 | (= __ (try 28 | (pop '()) 29 | (catch IllegalStateException e "No dice!"))) 30 | 31 | "The rest of nothing isn't so strict" 32 | (= __ (try 33 | (rest '()) 34 | (catch IllegalStateException e "No dice!")))) 35 | -------------------------------------------------------------------------------- /src/koans/sequence_comprehensions.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "Sequence comprehensions can bind each element in turn to a symbol" 3 | (= __ 4 | (for [index (range 6)] 5 | index)) 6 | 7 | "They can easily emulate mapping" 8 | (= '(0 1 4 9 16 25) 9 | (map (fn [index] (* index index)) 10 | (range 6)) 11 | (for [index (range 6)] 12 | __)) 13 | 14 | "And also filtering" 15 | (= '(1 3 5 7 9) 16 | (filter odd? (range 10)) 17 | (for [index __ :when (odd? index)] 18 | index)) 19 | 20 | "And they trivially allow combinations of the two transformations" 21 | (= '(1 9 25 49 81) 22 | (map (fn [index] (* index index)) 23 | (filter odd? (range 10))) 24 | (for [index (range 10) :when __] 25 | __)) 26 | 27 | "More complex transformations can be formed with multiple binding forms" 28 | (= [[:top :left] [:top :middle] [:top :right] 29 | [:middle :left] [:middle :middle] [:middle :right] 30 | [:bottom :left] [:bottom :middle] [:bottom :right]] 31 | (for [row [:top :middle :bottom] column [:left :middle :right]] 32 | __))) 33 | -------------------------------------------------------------------------------- /src/koans/higher_order_functions.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "The map function relates a sequence to another" 3 | (= [__ __ __] (map (fn [x] (* 4 x)) [1 2 3])) 4 | 5 | "You may create that mapping" 6 | (= [1 4 9 16 25] (map (fn [x] __) [1 2 3 4 5])) 7 | 8 | "Or use the names of existing functions" 9 | (= __ (map nil? [:a :b nil :c :d])) 10 | 11 | "A filter can be strong" 12 | (= __ (filter (fn [x] false) '(:anything :goes :here))) 13 | 14 | "Or very weak" 15 | (= __ (filter (fn [x] true) '(:anything :goes :here))) 16 | 17 | "Or somewhere in between" 18 | (= [10 20 30] (filter (fn [x] __) [10 20 30 40 50 60 70 80])) 19 | 20 | "Maps and filters may be combined" 21 | (= [10 20 30] (map (fn [x] __) (filter (fn [x] __) [1 2 3 4 5 6 7 8]))) 22 | 23 | "Reducing can increase the result" 24 | (= __ (reduce (fn [a b] (* a b)) [1 2 3 4])) 25 | 26 | "You can start somewhere else" 27 | (= 2400 (reduce (fn [a b] (* a b)) __ [1 2 3 4])) 28 | 29 | "Numbers are not the only things one can reduce" 30 | (= "longest" (reduce (fn [a b] 31 | (if (< __ __) b a)) 32 | ["which" "word" "is" "longest"]))) 33 | -------------------------------------------------------------------------------- /src/koans/creating_functions.clj: -------------------------------------------------------------------------------- 1 | (defn square [x] (* x x)) 2 | 3 | (meditations 4 | "One may know what they seek by knowing what they do not seek" 5 | (= [__ __ __] (let [not-a-symbol? (complement symbol?)] 6 | (map not-a-symbol? [:a 'b "c"]))) 7 | 8 | "Praise and 'complement' may help you separate the wheat from the chaff" 9 | (= [:wheat "wheat" 'wheat] 10 | (let [not-nil? ___] 11 | (filter not-nil? [nil :wheat nil "wheat" nil 'wheat nil]))) 12 | 13 | "Partial functions allow procrastination" 14 | (= 20 (let [multiply-by-5 (partial * 5)] 15 | (___ __))) 16 | 17 | "Don't forget: first things first" 18 | (= [__ __ __ __] 19 | (let [ab-adder (partial concat [:a :b])] 20 | (ab-adder [__ __]))) 21 | 22 | "Functions can join forces as one 'composed' function" 23 | (= 25 (let [inc-and-square (comp square inc)] 24 | (inc-and-square __))) 25 | 26 | "Have a go on a double dec-er" 27 | (= __ (let [double-dec (comp dec dec)] 28 | (double-dec 10))) 29 | 30 | "Be careful about the order in which you mix your functions" 31 | (= 99 (let [square-and-dec ___] 32 | (square-and-dec 10)))) 33 | -------------------------------------------------------------------------------- /src/koans/runtime_polymorphism.clj: -------------------------------------------------------------------------------- 1 | (defn hello 2 | ([] "Hello World!") 3 | ([a] (str "Hello, you silly " a ".")) 4 | ([a & more] (str "Hello to this group: " 5 | (apply str 6 | (interpose ", " (concat (list a) more))) 7 | "!"))) 8 | 9 | (defmulti diet (fn [x] (:eater x))) 10 | (defmethod diet :herbivore [a] __) 11 | (defmethod diet :carnivore [a] __) 12 | (defmethod diet :default [a] __) 13 | 14 | (meditations 15 | "Some functions can be used in different ways - with no arguments" 16 | (= __ (hello)) 17 | 18 | "With one argument" 19 | (= __ (hello "world")) 20 | 21 | "Or with many arguments" 22 | (= __ 23 | (hello "Peter" "Paul" "Mary")) 24 | 25 | "Multimethods allow more complex dispatching" 26 | (= "Bambi eats veggies." 27 | (diet {:species "deer" :name "Bambi" :age 1 :eater :herbivore})) 28 | 29 | "Different methods are used depending on the dispatch function result" 30 | (= "Simba eats animals." 31 | (diet {:species "lion" :name "Simba" :age 1 :eater :carnivore})) 32 | 33 | "You may use a default method when no others match" 34 | (= "I don't know what Rich Hickey eats." 35 | (diet {:name "Rich Hickey"}))) 36 | -------------------------------------------------------------------------------- /src/koans/refs.clj: -------------------------------------------------------------------------------- 1 | (def the-world (ref "hello")) 2 | (def bizarro-world (ref {})) 3 | 4 | (meditations 5 | "In the beginning, there was a word" 6 | (= __ (deref the-world)) 7 | 8 | "You can get the word more succinctly, but it's the same" 9 | (= __ @the-world) 10 | 11 | "You can be the change you wish to see in the world." 12 | (= __ (do 13 | (dosync (ref-set the-world "better")) 14 | @the-world)) 15 | 16 | "Alter where you need not replace" 17 | (= __ (let [exclamator (fn [x] (str x "!"))] 18 | (dosync 19 | (alter the-world exclamator) 20 | (alter the-world exclamator) 21 | (alter the-world exclamator)) 22 | @the-world)) 23 | 24 | "Don't forget to do your work in a transaction!" 25 | (= 0 (do __ 26 | @the-world)) 27 | 28 | "Functions passed to alter may depend on the data in the ref" 29 | (= 20 (do 30 | (dosync (alter the-world ___)))) 31 | 32 | "Two worlds are better than one" 33 | (= ["Real Jerry" "Bizarro Jerry"] 34 | (do 35 | (dosync 36 | (ref-set the-world {}) 37 | (alter the-world assoc :jerry "Real Jerry") 38 | (alter bizarro-world assoc :jerry "Bizarro Jerry") 39 | __)))) 40 | -------------------------------------------------------------------------------- /src/koans/macros.clj: -------------------------------------------------------------------------------- 1 | (defmacro hello [x] 2 | (str "Hello, " x)) 3 | 4 | (defmacro infix [form] 5 | (list (second form) (first form) (nth form 2))) 6 | 7 | (defmacro infix-better [form] 8 | `(~(second form) ; Note the syntax-quote (`) and unquote (~) characters! 9 | __ 10 | __ )) 11 | 12 | (defmacro r-infix [form] 13 | (cond (not (seq? form)) 14 | __ 15 | (= 1 (count form)) 16 | `(r-infix ~(first form)) 17 | :else 18 | (let [operator (second form) 19 | first-arg (first form) 20 | others __] 21 | `(~operator 22 | (r-infix ~first-arg) 23 | (r-infix ~others))))) 24 | 25 | (meditations 26 | "Macros are like functions created at compile time" 27 | (= __ (hello "Macros!")) 28 | 29 | "Can I haz some infix?" 30 | (= __ (infix (9 + 1))) 31 | 32 | "Remember, these are nothing but code transformations" 33 | (= __ (macroexpand '(infix (9 + 1)))) 34 | 35 | "You can do better than that, hand crafting ftw!" 36 | (= __ (macroexpand '(infix-better (10 * 2)))) 37 | 38 | "Things dont always work as you would like them to... " 39 | (= __ (macroexpand '(infix-better ( 10 + (2 * 3))))) 40 | 41 | "Really, you dont understand recursion until you understand recursion" 42 | (= 36 (r-infix (10 + (2 * 3) + (4 * 5))))) 43 | -------------------------------------------------------------------------------- /src/koans/datatypes.clj: -------------------------------------------------------------------------------- 1 | (defrecord Nobel [prize]) 2 | (deftype Pulitzer [prize]) 3 | 4 | (defprotocol Award 5 | (present [this recipient])) 6 | 7 | (defrecord Oscar [category] 8 | Award 9 | (present [this recipient] 10 | (print (str "Congratulations on your " 11 | (:category this) " Oscar, " 12 | recipient 13 | "!")))) 14 | 15 | (deftype Razzie [category] 16 | Award 17 | (present [this recipient] 18 | __)) 19 | 20 | (meditations 21 | "Holding records is meaningful only when the record is worthy of you" 22 | (= __ (.prize (Nobel. "peace"))) 23 | 24 | "Types are quite similar" 25 | (= __ (.prize (Pulitzer. "literature"))) 26 | 27 | "Records may be treated like maps" 28 | (= __ (:prize (Nobel. "physics"))) 29 | 30 | "While types may not" 31 | (= __ (:prize (Pulitzer. "poetry"))) 32 | 33 | "Further study reveals why" 34 | (= __ 35 | (map map? [(Nobel. "chemistry") 36 | (Pulitzer. "music")])) 37 | 38 | "Either sort of datatype can define methods in a protocol" 39 | (= __ 40 | (with-out-str (present (Oscar. "Best Picture") "Evil Alien Conquerors"))) 41 | 42 | "Surely we can implement our own by now" 43 | (= "You're really the Worst Picture, Final Destination 5... sorry." 44 | (with-out-str (present (Razzie. "Worst Picture") "Final Destination 5")))) 45 | -------------------------------------------------------------------------------- /src/koans/conditionals.clj: -------------------------------------------------------------------------------- 1 | (defn explain-defcon-level [exercise-term] 2 | (case exercise-term 3 | :fade-out :you-and-what-army 4 | :double-take :call-me-when-its-important 5 | :round-house :o-rly 6 | :fast-pace :thats-pretty-bad 7 | :cocked-pistol :sirens 8 | :say-what?)) 9 | 10 | (meditations 11 | "You will face many decisions" 12 | (= __ (if (false? (= 4 5)) 13 | :a 14 | :b)) 15 | 16 | "Some of them leave you no alternative" 17 | (= __ (if (> 4 3) 18 | [])) 19 | 20 | "And in such a situation you may have nothing" 21 | (= __ (if (nil? 0) 22 | [:a :b :c])) 23 | 24 | "In others your alternative may be interesting" 25 | (= :glory (if (not (empty? ())) 26 | :doom 27 | __)) 28 | 29 | "You may have a multitude of possible paths" 30 | (let [x 5] 31 | (= :your-road (cond (= x __) :road-not-taken 32 | (= x __) :another-road-not-taken 33 | :else __))) 34 | 35 | "Or your fate may be sealed" 36 | (= __ (if-not (zero? __) 37 | 'doom 38 | 'doom)) 39 | 40 | "In case of emergency, sound the alarms" 41 | (= :sirens 42 | (explain-defcon-level __)) 43 | 44 | "But admit it when you don't know what to do" 45 | (= __ 46 | (explain-defcon-level :yo-mama))) 47 | -------------------------------------------------------------------------------- /src/koans/recursion.clj: -------------------------------------------------------------------------------- 1 | (defn is-even? [n] 2 | (if (= n 0) 3 | __ 4 | (___ (is-even? (dec n))))) 5 | 6 | (defn is-even-bigint? [n] 7 | (loop [n n 8 | acc true] 9 | (if (= n 0) 10 | __ 11 | (recur (dec n) (not acc))))) 12 | 13 | (defn recursive-reverse [coll] 14 | __) 15 | 16 | (defn factorial [n] 17 | __) 18 | 19 | (meditations 20 | "Recursion ends with a base case" 21 | (= true (is-even? 0)) 22 | 23 | "And starts by moving toward that base case" 24 | (= false (is-even? 1)) 25 | 26 | "Having too many stack frames requires explicit tail calls with recur" 27 | (= false (is-even-bigint? 100003N)) 28 | 29 | "Reversing directions is easy when you have not gone far" 30 | (= '(1) (recursive-reverse [1])) 31 | 32 | "Yet more difficult the more steps you take" 33 | (= '(5 4 3 2 1) (recursive-reverse [1 2 3 4 5])) 34 | 35 | "Simple things may appear simple." 36 | (= 1 (factorial 1)) 37 | 38 | "They may require other simple steps." 39 | (= 2 (factorial 2)) 40 | 41 | "Sometimes a slightly bigger step is necessary" 42 | (= 6 (factorial 3)) 43 | 44 | "And eventually you must think harder" 45 | (= 24 (factorial 4)) 46 | 47 | "You can even deal with very large numbers" 48 | (< 1000000000000000000000000N (factorial 1000N)) 49 | 50 | "But what happens when the machine limits you?" 51 | (< 1000000000000000000000000N (factorial 10000N))) 52 | -------------------------------------------------------------------------------- /src/koans/destructuring.clj: -------------------------------------------------------------------------------- 1 | (def test-address 2 | {:street-address "123 Test Lane" 3 | :city "Testerville" 4 | :state "TX"}) 5 | 6 | (meditations 7 | "Destructuring is an arbiter: it breaks up arguments" 8 | (= __ ((fn [[a b]] (str b a)) 9 | [:foo :bar])) 10 | 11 | "Whether in function definitions" 12 | (= (str "First comes love, " 13 | "then comes marriage, " 14 | "then comes Clojure with the baby carriage") 15 | ((fn [[a b c]] __) 16 | ["love" "marriage" "Clojure"])) 17 | 18 | "Or in let expressions" 19 | (= "Rich Hickey aka The Clojurer aka Go Time aka Macro Killah" 20 | (let [[first-name last-name & aliases] 21 | (list "Rich" "Hickey" "The Clojurer" "Go Time" "Macro Killah")] 22 | __)) 23 | 24 | "You can regain the full argument if you like arguing" 25 | (= {:original-parts ["Steven" "Hawking"] :named-parts {:first "Steven" :last "Hawking"}} 26 | (let [[first-name last-name :as full-name] ["Steven" "Hawking"]] 27 | __)) 28 | 29 | "Break up maps by key" 30 | (= "123 Test Lane, Testerville, TX" 31 | (let [{street-address :street-address, city :city, state :state} test-address] 32 | __)) 33 | 34 | "Or more succinctly" 35 | (= "123 Test Lane, Testerville, TX" 36 | (let [{:keys [street-address __ __]} test-address] 37 | __)) 38 | 39 | "All together now!" 40 | (= "Test Testerson, 123 Test Lane, Testerville, TX" 41 | (___ ["Test" "Testerson"] test-address))) 42 | -------------------------------------------------------------------------------- /src/koans/maps.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "There are two ways to create maps" 3 | (= __ (hash-map)) 4 | 5 | "Maps in clojure associate keys with values" 6 | (= __ (count (hash-map))) 7 | 8 | "A value must be supplied for each key" 9 | (= {:a 1} (hash-map :a __)) 10 | 11 | "The size is the number of entries" 12 | (= __ (count {:a 1 :b 2})) 13 | 14 | "You can look up the value for a given key" 15 | (= __ (get {:a 1 :b 2} :b)) 16 | 17 | "Maps can be used as lookup functions" 18 | (= __ ({:a 1 :b 2} :a)) 19 | 20 | "And so can keywords" 21 | (= __ (:a {:a 1 :b 2})) 22 | 23 | "But map keys need not be keywords" 24 | (= __ ({2006 "Torino" 2010 "Vancouver" 2014 "Sochi"} 2010)) 25 | 26 | "You may not be able to find an entry for a key" 27 | (= __ (get {:a 1 :b 2} :c)) 28 | 29 | "But you can provide your own default" 30 | (= __ (get {:a 1 :b 2} :c :key-not-found)) 31 | 32 | "You can find out if a key is present" 33 | (= __ (contains? {:a nil :b nil} :b)) 34 | 35 | "Or if it is missing" 36 | (= __ (contains? {:a nil :b nil} :c)) 37 | 38 | "Maps are immutable, but you can create a new, 'changed' version" 39 | (= {1 "January" 2 __} (assoc {1 "January" } 2 "February")) 40 | 41 | "You can also 'remove' an entry" 42 | (= {__ __} (dissoc {1 "January" 2 "February"} 2)) 43 | 44 | "Often you will need to get the keys (which will be in hash order)" 45 | (= (list __ __ __) 46 | (sort (keys {2006 "Torino" 2010 "Vancouver" 2014 "Sochi"}))) 47 | 48 | "Or the values" 49 | (= (list "Sochi" "Torino" __) 50 | (sort (vals {2006 "Torino" 2010 "Vancouver" 2014 "Sochi"})))) 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Clojure Koans 2 | 3 | The Clojure Koans are a fun and easy way to get started with Clojure - no 4 | experience assumed or required. Just follow the instructions below to start 5 | making tests pass! 6 | 7 | 8 | ### Getting Started 9 | 10 | The easiest and fastest way to get the koans up and running is to [download the 11 | latest zip file from Github](https://github.com/functional-koans/clojure-koans/downloads). 12 | This way, you'll have all the dependencies you need, including Clojure itself 13 | and JLine, and you can skip the rest of this section (skip to "Running the 14 | Koans"). 15 | 16 | If you're starting from a cloned or forked repo, that's cool too. This way 17 | you'll be able to track your progress in Git, and see how your answers compare 18 | to others, by checking out the project's Network tab. You might want to create your 19 | own branch - that way if you pull back the latest koans from master, it'll be a bit 20 | easier to manage the inevitable conflicts if we make changes to exercises you've already 21 | completed. 22 | 23 | The only things you'll need to run the Clojure Koans are: 24 | 25 | - JRE 1.5 or higher 26 | - [clojure-1.3.0.jar](http://repo1.maven.org/maven2/org/clojure/clojure/1.3.0/clojure-1.3.0.zip) 27 | 28 | clojure-1.3.0.jar needs to be in a directory `lib` under this project. 29 | 30 | You can use [Leiningen](http://github.com/technomancy/leiningen) to 31 | automatically install the Clojure jar in the right place. Leiningen will also 32 | get you a couple more jarfiles, including JLine, which allows you some of the 33 | functionality of readline (command-line history, for example). 34 | 35 | After you have leiningen installed, run 36 | 37 | `lein deps` 38 | 39 | which will download all dependencies you need to run the Clojure koans. 40 | 41 | 42 | ### Running the Koans 43 | 44 | To run the koans, simply run 45 | 46 | `script/run` on Mac/\*nix 47 | 48 | `script\run` on Windows 49 | 50 | It's an auto-runner, so as you save your files with the correct answers, it will 51 | advance you to the next koan or file. 52 | 53 | You'll see something like this: 54 | 55 | Problem in /home/colin/Projects/clojure-koans/src/koans/equalities.clj 56 | --------------------- 57 | Assertion failed! 58 | We shall contemplate truth by testing reality, via equality. 59 | (= __ true) 60 | 61 | The output is telling you that you have a failing test in equalities.clj. 62 | So open that file up and make it pass! In general, you just fill in the 63 | blanks to make tests pass. Sometimes there are several (or even an infinite 64 | number) of correct answers: any of them will work in these cases. 65 | 66 | The koans differ from normal TDD in that the tests are already written for you, 67 | so you'll have to pay close attention to the failure messages, because up until 68 | the very end, making a test pass just means that the next failure message comes 69 | up. 70 | 71 | While it might be easy (especially at first) to just fill in the blanks making 72 | things pass, you should work thoughtfully, making sure you understand why the 73 | answer is what it is. Enjoy your path to Clojure enlightenment! 74 | 75 | 76 | ### Trying more things out 77 | 78 | There's a REPL (Read-Evaluate-Print Loop) included in the Clojure Koans. Just 79 | run: 80 | 81 | `script/repl` on Mac/\*nix 82 | 83 | `script\repl` on Windows 84 | 85 | Here are some interesting commands you might try, once you're in a running REPL: 86 | 87 | ```clojure 88 | (find-doc "vec") 89 | (find-doc #"vec$") 90 | (doc vec) 91 | ``` 92 | 93 | And if those still don't make sense: 94 | 95 | ```clojure 96 | (doc doc) 97 | (doc find-doc) 98 | ``` 99 | 100 | will show you what those commands mean. 101 | 102 | You can exit the REPL with `CTRL-d` on any OS. 103 | 104 | 105 | ### Contributing 106 | 107 | Patches are encouraged! Make sure the answer sheet still passes (`script/test`, 108 | or `script\test` on Windows), and send a pull request. 109 | 110 | The file ideaboard.txt has lots of good ideas for new koans to start, or things 111 | to add to existing koans. So write some fun exercises, add your answers to 112 | `resources/koans.clj`, and we'll get them in there! 113 | 114 | Feel free to contact me (Colin Jones / trptcolin) on Github or elsewhere if you 115 | have any questions or want more direction before you start pitching in. 116 | 117 | 118 | ### Contributors (in order of appearance) 119 | 120 | - Aaron Bedra 121 | - Colin Jones (maintainer) 122 | - Eric Lavigne 123 | - Nuno Marquez 124 | - Micah Martin 125 | - Michael Kohl 126 | - Ben Lickly 127 | - Alex Robbins 128 | - Jaskirat Singh Veen 129 | - Mark Simpson 130 | - Mike Jansen 131 | - Caleb Phillips 132 | - Doug South 133 | 134 | 135 | ### Credits 136 | 137 | These exercises were started by [Aaron Bedra](http://github.com/abedra) of 138 | [Relevance, Inc.](http://github.com/relevance) in early 2010, as a learning 139 | tool for newcomers to functional programming. Aaron's macro-fu makes these 140 | koans extremely simple and fun to use, and to improve upon, and without 141 | Relevance's initiative, this project would not exist. 142 | 143 | Using the [koans](http://en.wikipedia.org/wiki/koan) metaphor as a tool for 144 | learning a programming language started with the 145 | [Ruby Koans](http://rubykoans.com) by [EdgeCase](http://github.com/edgecase). 146 | 147 | 148 | ### License 149 | 150 | The use and distribution terms for this software are covered by the 151 | Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 152 | which can be found in the file epl-v10.html at the root of this distribution. 153 | By using this software in any fashion, you are agreeing to be bound by 154 | the terms of this license. -------------------------------------------------------------------------------- /resources/koans.clj: -------------------------------------------------------------------------------- 1 | [["equalities" {"__" [true 2 | 2 3 | 7 4 | 5 5 | 4/2 6 | false 7 | 6/3 8 | 3]}] 9 | 10 | ["lists" {"__" [1 2 3 4 5 11 | 1 12 | [2 3 4 5] 13 | () 14 | [:a :b :c :d :e] 15 | [0 :a :b :c :d :e] 16 | :a 17 | [:b :c :d :e] 18 | "No dice!" 19 | ()]}] 20 | 21 | ["vectors" {"__" [1 22 | [] 23 | [1] 24 | [nil] 25 | 2 26 | [333] 27 | :peanut 28 | :jelly 29 | :jelly 30 | [:butter :and] 31 | 3]}] 32 | 33 | ["sets" {"__" [nil 34 | 3 35 | #{1 2 3 4 5} 36 | #{1 2 3 4 5} 37 | #{2 3} 38 | #{1 4}]}] 39 | 40 | ["maps" {"__" [{} 41 | 0 42 | 1 43 | 2 44 | 2 45 | 1 46 | 1 47 | "Vancouver" 48 | nil 49 | :key-not-found 50 | true 51 | false 52 | "February" 53 | 1 "January" 54 | 2006 2010 2014 55 | "Vancouver"]}] 56 | 57 | ["functions" {"__" [20 58 | 10 5 59 | 30 2 60 | 15 61 | 20 *] 62 | "___" [(fn [f] (f 5)) 63 | (fn [f] (f 5))]}] 64 | 65 | ["conditionals" {"__" [:a 66 | [] 67 | nil 68 | :glory 69 | 4 6 :your-road 70 | 'doom 0 71 | :cocked-pistol 72 | :say-what?]}] 73 | 74 | ["higher_order_functions" {"__" [4 8 12 75 | (* x x) 76 | [false false true false false] 77 | () 78 | [:anything :goes :here] 79 | (< x 31) 80 | (* 10 x) (< x 4) 81 | 24 82 | 100 83 | (count a) (count b)]}] 84 | 85 | ["runtime_polymorphism" {"__" [(str (:name a) " eats veggies.") 86 | (str (:name a) " eats animals.") 87 | (str "I don't know what " (:name a) " eats.") 88 | "Hello World!" 89 | "Hello, you silly world." 90 | "Hello to this group: Peter, Paul, Mary!" ]}] 91 | 92 | ["lazy_sequences" {"__" [[1 2 3 4] 93 | [0 1 2 3 4] 94 | 10 95 | 95 96 | (range 20) 97 | :a] 98 | "___" [(fn [x] :foo)]}] 99 | 100 | ["sequence_comprehensions" {"__" [[0 1 2 3 4 5] 101 | (* index index) 102 | (range 10) 103 | (odd? index) (* index index) 104 | [row column] 105 | ]}] 106 | 107 | ["creating_functions" {"__" [true false true 108 | 4 109 | :a :b :c :d 110 | :c :d 111 | 4 112 | 8] 113 | "___" [(complement nil?) 114 | multiply-by-5 115 | (comp dec square)]}] 116 | 117 | ["recursion" {"__" [true 118 | acc 119 | (loop [coll coll 120 | acc ()] 121 | (if (seq coll) 122 | (recur (rest coll) (conj acc (first coll))) 123 | acc)) 124 | (loop [n n 125 | acc 1] 126 | (if (zero? n) 127 | acc 128 | (recur (dec n) (* acc n))))] 129 | "___" [not]}] 130 | 131 | ["destructuring" {"__" [":bar:foo" 132 | (format (str "First comes %s, " 133 | "then comes %s, " 134 | "then comes %s with the baby carriage") 135 | a b c) 136 | (apply str 137 | (interpose " " 138 | (apply list 139 | first-name 140 | last-name 141 | (interleave (repeat "aka") aliases)))) 142 | {:original-parts full-name 143 | :named-parts {:first first-name :last last-name}} 144 | (str street-address ", " city ", " state) 145 | city state 146 | (str street-address ", " city ", " state)] 147 | "___" [(fn [[fname lname] 148 | {:keys [street-address city state]}] 149 | (str fname " " lname ", " 150 | street-address ", " city ", " state)) 151 | ]}] 152 | 153 | ["refs" {"__" ["hello" 154 | "hello" 155 | "better" 156 | "better!!!" 157 | (dosync (ref-set the-world 0)) 158 | (map :jerry [@the-world @bizarro-world]) 159 | ] 160 | "___" [(fn [x] (+ 20 x))]}] 161 | 162 | ["atoms" {"__" [0 163 | 1 164 | (swap! atomic-clock (partial + 4)) 165 | 20 166 | 20 167 | atomic-clock 20 :fin 168 | ]}] 169 | 170 | ["macros" {"__" [~(first form) 171 | ~(nth form 2) 172 | form 173 | (drop 2 form) 174 | "Hello, Macros!" 175 | 10 176 | '(+ 9 1) 177 | '(* 10 2) 178 | '(+ 10 (2 * 3))]}] 179 | 180 | ["datatypes" {"__" [(print 181 | (str "You're really the " 182 | (.category this) 183 | ", " recipient "... sorry.")) 184 | "peace" 185 | "literature" 186 | "physics" 187 | nil 188 | [true false] 189 | (str "Congratulations on your Best Picture Oscar, " 190 | "Evil Alien Conquerors!")]}] 191 | 192 | ["java_interop" {"__" [java.lang.String 193 | "SELECT * FROM" 194 | 10 195 | 1024 196 | ] 197 | "___" [#(.toUpperCase %) 198 | ] 199 | }]] 200 | -------------------------------------------------------------------------------- /epl-v10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Eclipse Public License - Version 1.0 8 | 25 | 26 | 27 | 28 | 29 | 30 |

Eclipse Public License - v 1.0

31 | 32 |

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE 33 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR 34 | DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS 35 | AGREEMENT.

36 | 37 |

1. DEFINITIONS

38 | 39 |

"Contribution" means:

40 | 41 |

a) in the case of the initial Contributor, the initial 42 | code and documentation distributed under this Agreement, and

43 |

b) in the case of each subsequent Contributor:

44 |

i) changes to the Program, and

45 |

ii) additions to the Program;

46 |

where such changes and/or additions to the Program 47 | originate from and are distributed by that particular Contributor. A 48 | Contribution 'originates' from a Contributor if it was added to the 49 | Program by such Contributor itself or anyone acting on such 50 | Contributor's behalf. Contributions do not include additions to the 51 | Program which: (i) are separate modules of software distributed in 52 | conjunction with the Program under their own license agreement, and (ii) 53 | are not derivative works of the Program.

54 | 55 |

"Contributor" means any person or entity that distributes 56 | the Program.

57 | 58 |

"Licensed Patents" mean patent claims licensable by a 59 | Contributor which are necessarily infringed by the use or sale of its 60 | Contribution alone or when combined with the Program.

61 | 62 |

"Program" means the Contributions distributed in accordance 63 | with this Agreement.

64 | 65 |

"Recipient" means anyone who receives the Program under 66 | this Agreement, including all Contributors.

67 | 68 |

2. GRANT OF RIGHTS

69 | 70 |

a) Subject to the terms of this Agreement, each 71 | Contributor hereby grants Recipient a non-exclusive, worldwide, 72 | royalty-free copyright license to reproduce, prepare derivative works 73 | of, publicly display, publicly perform, distribute and sublicense the 74 | Contribution of such Contributor, if any, and such derivative works, in 75 | source code and object code form.

76 | 77 |

b) Subject to the terms of this Agreement, each 78 | Contributor hereby grants Recipient a non-exclusive, worldwide, 79 | royalty-free patent license under Licensed Patents to make, use, sell, 80 | offer to sell, import and otherwise transfer the Contribution of such 81 | Contributor, if any, in source code and object code form. This patent 82 | license shall apply to the combination of the Contribution and the 83 | Program if, at the time the Contribution is added by the Contributor, 84 | such addition of the Contribution causes such combination to be covered 85 | by the Licensed Patents. The patent license shall not apply to any other 86 | combinations which include the Contribution. No hardware per se is 87 | licensed hereunder.

88 | 89 |

c) Recipient understands that although each Contributor 90 | grants the licenses to its Contributions set forth herein, no assurances 91 | are provided by any Contributor that the Program does not infringe the 92 | patent or other intellectual property rights of any other entity. Each 93 | Contributor disclaims any liability to Recipient for claims brought by 94 | any other entity based on infringement of intellectual property rights 95 | or otherwise. As a condition to exercising the rights and licenses 96 | granted hereunder, each Recipient hereby assumes sole responsibility to 97 | secure any other intellectual property rights needed, if any. For 98 | example, if a third party patent license is required to allow Recipient 99 | to distribute the Program, it is Recipient's responsibility to acquire 100 | that license before distributing the Program.

101 | 102 |

d) Each Contributor represents that to its knowledge it 103 | has sufficient copyright rights in its Contribution, if any, to grant 104 | the copyright license set forth in this Agreement.

105 | 106 |

3. REQUIREMENTS

107 | 108 |

A Contributor may choose to distribute the Program in object code 109 | form under its own license agreement, provided that:

110 | 111 |

a) it complies with the terms and conditions of this 112 | Agreement; and

113 | 114 |

b) its license agreement:

115 | 116 |

i) effectively disclaims on behalf of all Contributors 117 | all warranties and conditions, express and implied, including warranties 118 | or conditions of title and non-infringement, and implied warranties or 119 | conditions of merchantability and fitness for a particular purpose;

120 | 121 |

ii) effectively excludes on behalf of all Contributors 122 | all liability for damages, including direct, indirect, special, 123 | incidental and consequential damages, such as lost profits;

124 | 125 |

iii) states that any provisions which differ from this 126 | Agreement are offered by that Contributor alone and not by any other 127 | party; and

128 | 129 |

iv) states that source code for the Program is available 130 | from such Contributor, and informs licensees how to obtain it in a 131 | reasonable manner on or through a medium customarily used for software 132 | exchange.

133 | 134 |

When the Program is made available in source code form:

135 | 136 |

a) it must be made available under this Agreement; and

137 | 138 |

b) a copy of this Agreement must be included with each 139 | copy of the Program.

140 | 141 |

Contributors may not remove or alter any copyright notices contained 142 | within the Program.

143 | 144 |

Each Contributor must identify itself as the originator of its 145 | Contribution, if any, in a manner that reasonably allows subsequent 146 | Recipients to identify the originator of the Contribution.

147 | 148 |

4. COMMERCIAL DISTRIBUTION

149 | 150 |

Commercial distributors of software may accept certain 151 | responsibilities with respect to end users, business partners and the 152 | like. While this license is intended to facilitate the commercial use of 153 | the Program, the Contributor who includes the Program in a commercial 154 | product offering should do so in a manner which does not create 155 | potential liability for other Contributors. Therefore, if a Contributor 156 | includes the Program in a commercial product offering, such Contributor 157 | ("Commercial Contributor") hereby agrees to defend and 158 | indemnify every other Contributor ("Indemnified Contributor") 159 | against any losses, damages and costs (collectively "Losses") 160 | arising from claims, lawsuits and other legal actions brought by a third 161 | party against the Indemnified Contributor to the extent caused by the 162 | acts or omissions of such Commercial Contributor in connection with its 163 | distribution of the Program in a commercial product offering. The 164 | obligations in this section do not apply to any claims or Losses 165 | relating to any actual or alleged intellectual property infringement. In 166 | order to qualify, an Indemnified Contributor must: a) promptly notify 167 | the Commercial Contributor in writing of such claim, and b) allow the 168 | Commercial Contributor to control, and cooperate with the Commercial 169 | Contributor in, the defense and any related settlement negotiations. The 170 | Indemnified Contributor may participate in any such claim at its own 171 | expense.

172 | 173 |

For example, a Contributor might include the Program in a commercial 174 | product offering, Product X. That Contributor is then a Commercial 175 | Contributor. If that Commercial Contributor then makes performance 176 | claims, or offers warranties related to Product X, those performance 177 | claims and warranties are such Commercial Contributor's responsibility 178 | alone. Under this section, the Commercial Contributor would have to 179 | defend claims against the other Contributors related to those 180 | performance claims and warranties, and if a court requires any other 181 | Contributor to pay any damages as a result, the Commercial Contributor 182 | must pay those damages.

183 | 184 |

5. NO WARRANTY

185 | 186 |

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS 187 | PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 188 | OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, 189 | ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY 190 | OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely 191 | responsible for determining the appropriateness of using and 192 | distributing the Program and assumes all risks associated with its 193 | exercise of rights under this Agreement , including but not limited to 194 | the risks and costs of program errors, compliance with applicable laws, 195 | damage to or loss of data, programs or equipment, and unavailability or 196 | interruption of operations.

197 | 198 |

6. DISCLAIMER OF LIABILITY

199 | 200 |

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT 201 | NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, 202 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING 203 | WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF 204 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 205 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR 206 | DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED 207 | HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

208 | 209 |

7. GENERAL

210 | 211 |

If any provision of this Agreement is invalid or unenforceable under 212 | applicable law, it shall not affect the validity or enforceability of 213 | the remainder of the terms of this Agreement, and without further action 214 | by the parties hereto, such provision shall be reformed to the minimum 215 | extent necessary to make such provision valid and enforceable.

216 | 217 |

If Recipient institutes patent litigation against any entity 218 | (including a cross-claim or counterclaim in a lawsuit) alleging that the 219 | Program itself (excluding combinations of the Program with other 220 | software or hardware) infringes such Recipient's patent(s), then such 221 | Recipient's rights granted under Section 2(b) shall terminate as of the 222 | date such litigation is filed.

223 | 224 |

All Recipient's rights under this Agreement shall terminate if it 225 | fails to comply with any of the material terms or conditions of this 226 | Agreement and does not cure such failure in a reasonable period of time 227 | after becoming aware of such noncompliance. If all Recipient's rights 228 | under this Agreement terminate, Recipient agrees to cease use and 229 | distribution of the Program as soon as reasonably practicable. However, 230 | Recipient's obligations under this Agreement and any licenses granted by 231 | Recipient relating to the Program shall continue and survive.

232 | 233 |

Everyone is permitted to copy and distribute copies of this 234 | Agreement, but in order to avoid inconsistency the Agreement is 235 | copyrighted and may only be modified in the following manner. The 236 | Agreement Steward reserves the right to publish new versions (including 237 | revisions) of this Agreement from time to time. No one other than the 238 | Agreement Steward has the right to modify this Agreement. The Eclipse 239 | Foundation is the initial Agreement Steward. The Eclipse Foundation may 240 | assign the responsibility to serve as the Agreement Steward to a 241 | suitable separate entity. Each new version of the Agreement will be 242 | given a distinguishing version number. The Program (including 243 | Contributions) may always be distributed subject to the version of the 244 | Agreement under which it was received. In addition, after a new version 245 | of the Agreement is published, Contributor may elect to distribute the 246 | Program (including its Contributions) under the new version. Except as 247 | expressly stated in Sections 2(a) and 2(b) above, Recipient receives no 248 | rights or licenses to the intellectual property of any Contributor under 249 | this Agreement, whether expressly, by implication, estoppel or 250 | otherwise. All rights in the Program not expressly granted under this 251 | Agreement are reserved.

252 | 253 |

This Agreement is governed by the laws of the State of New York and 254 | the intellectual property laws of the United States of America. No party 255 | to this Agreement will bring a legal action under this Agreement more 256 | than one year after the cause of action arose. Each party waives its 257 | rights to a jury trial in any resulting litigation.

258 | 259 | 260 | 261 | 262 | --------------------------------------------------------------------------------