├── script ├── run.clj ├── test.clj ├── repl ├── run ├── test ├── test.bat ├── run.bat ├── repl.bat └── deploy.sh ├── .gitignore ├── project.clj ├── ideaboard.txt ├── src └── koans │ ├── 04_sets.clj │ ├── 19_java_interop.clj │ ├── 10_lazy_sequences.clj │ ├── 20_partition.clj │ ├── 16_atoms.clj │ ├── 01_equalities.clj │ ├── 03_vectors.clj │ ├── 06_functions.clj │ ├── 11_sequence_comprehensions.clj │ ├── 12_creating_functions.clj │ ├── 08_higher_order_functions.clj │ ├── 15_refs.clj │ ├── 02_lists.clj │ ├── 17_macros.clj │ ├── 18_datatypes.clj │ ├── 09_runtime_polymorphism.clj │ ├── 13_recursion.clj │ ├── 07_conditionals.clj │ ├── 14_destructuring.clj │ └── 05_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 | target 6 | *.jar 7 | .DS_Store 8 | .lein-deps-sum 9 | .lein-plugins 10 | .lein-repl-history 11 | 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /script/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p releases 4 | lein1 deps 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 (somewhere...)" 12 | echo `ls -t releases/clojure-koans-*.zip | head -n1` 13 | echo "git push" 14 | echo "git push --tags" 15 | echo 16 | 17 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject clojure-koans "0.5.0-SNAPSHOT" 2 | :description "The Clojure koans." 3 | :dependencies [[org.clojure/clojure "1.5.1"] 4 | [koan-engine "0.2.0"]] 5 | :dev-dependencies [[lein-koan "0.1.2"]] 6 | :profiles {:dev {:dependencies [[lein-koan "0.1.2"]]}} 7 | :repl-options {:init-ns user} 8 | :plugins [[lein-koan "0.1.2"]] 9 | :main koan-engine.runner/exec) 10 | -------------------------------------------------------------------------------- /ideaboard.txt: -------------------------------------------------------------------------------- 1 | Concepts / Language Features 2 | ===== 3 | 4 | Quoting 5 | 6 | new record syntax 7 | Agents 8 | Vars 9 | state identity lifetime 10 | Metadata 11 | immutability / side effects 12 | type hints 13 | Pre and Post conditions of functions 14 | 15 | Particular Functions 16 | ===== 17 | fnil - creating_a_function 18 | juxt - creating_a_function 19 | constantly - creating_a_function 20 | flatten 21 | 22 | frequencies 23 | reductions 24 | group-by 25 | keep 26 | keep-indexed 27 | map-indexed 28 | partition-all 29 | partition-by 30 | repeatedly 31 | 32 | -------------------------------------------------------------------------------- /src/koans/04_sets.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "You can create a set by converting another collection" 3 | (= #{3} (set '(3))) 4 | 5 | "Counting them is like counting other collections" 6 | (= 3 (count #{1 2 3})) 7 | 8 | "Remember that a set is a *mathematical* set" 9 | (= #{1 2 3 4 5} (set '(1 1 2 2 3 3 4 4 5 5))) 10 | 11 | "You can ask clojure for the union of two sets" 12 | (= #{1 2 3 4 5} (clojure.set/union #{1 2 3 4} #{2 3 5})) 13 | 14 | "And also the intersection" 15 | (= #{2 3} (clojure.set/intersection #{1 2 3 4} #{2 3 5})) 16 | 17 | "But don't forget about the difference" 18 | (= #{1 4} (clojure.set/difference #{1 2 3 4 5} #{2 3 5}))) 19 | -------------------------------------------------------------------------------- /src/koans/19_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/10_lazy_sequences.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "There are many ways to generate a sequence" 3 | (= '(1 2 3 4) (range 1 5)) 4 | 5 | "The range starts at the beginning by default" 6 | (= [0 1 2 3 4] (range 5)) 7 | 8 | "Only take what you need when the sequence is large" 9 | (= [0 1 2 3 4 5 6 7 8 9] 10 | (take 10 (range 100))) 11 | 12 | "Or limit results by dropping what you don't need" 13 | (= [95 96 97 98 99] 14 | (drop 95 (range 100))) 15 | 16 | "Iteration provides an infinite lazy sequence" 17 | (= (range 20) (take 20 (iterate inc 0))) 18 | 19 | "Repetition is key" 20 | (= [:a :a :a :a :a :a :a :a :a :a ] 21 | (repeat 10 :a)) 22 | 23 | "Iteration can be used for repetition" 24 | (= (repeat 100 :foo) 25 | (take 100 (iterate identity :foo)))) 26 | -------------------------------------------------------------------------------- /src/koans/20_partition.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "To split a collection you can use the partition function" 3 | (= '((0 1) (2 3)) (__ 2 (range 4))) 4 | 5 | "But watch out if there are not enough elements to form n sequences" 6 | (= '(__) (partition 3 [:a :b :c :d :e])) 7 | 8 | "You can use partition-all to also get partitions with less than n elements" 9 | (= __ (partition-all 3 (range 5))) 10 | 11 | "If you need to, you can start each sequence with an offset" 12 | (= '((0 1 2) (5 6 7) (10 11 12)) (partition 3 __ (range 13))) 13 | 14 | "Consider padding the last sequence with some default values.." 15 | (= '((0 1 2) (3 4 5) (6 :hello)) (partition 3 3 [__] (range 7))) 16 | 17 | ".. but notice that they will only pad up to given sequence length" 18 | (= '((0 1 2) (3 4 5) __) (partition 3 3 [:this :are "my" "words"] (range 7)))) 19 | -------------------------------------------------------------------------------- /src/koans/16_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/01_equalities.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "We shall contemplate truth by testing reality, via equality" 3 | (= true true) 4 | 5 | "To understand reality, we must compare our expectations against reality" 6 | (= 2 (+ 1 1)) 7 | 8 | "You can test equality of many things" 9 | (= (+ 3 4) 7 (+ 2 5)) 10 | 11 | "Some things may appear different, but be the same" 12 | (= true (= 2 2/1)) 13 | 14 | "You cannot generally float to heavens of integers" 15 | (= false (= 2 2.0)) 16 | 17 | "But a looser equality is also possible" 18 | (= true (== 2.0 2)) 19 | 20 | "Something is not equal to nothing" 21 | (= true (not (= 1 nil))) 22 | 23 | "Strings, and keywords, and symbols: oh my!" 24 | (= false (= "foo" :foo 'foo)) 25 | 26 | "Make a keyword with your keyboard" 27 | (= :foo (keyword :foo)) 28 | 29 | "Symbolism is all around us" 30 | (= 'foo (symbol 'foo)) 31 | 32 | "When things cannot be equal, they must be different" 33 | (not= :fill-in-the-blank :ok)) 34 | -------------------------------------------------------------------------------- /src/koans/03_vectors.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "You can use vectors in clojure as array-like structures" 3 | (= 1 (count [42])) 4 | 5 | "You can create a vector from a list" 6 | (= [1] (vec '(1))) 7 | 8 | "Or from some elements" 9 | (= [nil nil] (vector nil nil)) 10 | 11 | "But you can populate it with any number of elements at once" 12 | (= [1 2] (vec '(1 2))) 13 | 14 | "Conjoining to a vector is different than to a list" 15 | (= [111 222 333] (conj [111 222] 333)) 16 | 17 | "You can get the first element of a vector like so" 18 | (= :peanut (first [:peanut :butter :and :jelly])) 19 | 20 | "And the last in a similar fashion" 21 | (= :jelly (last [:peanut :butter :and :jelly])) 22 | 23 | "Or any index if you wish" 24 | (= :jelly (nth [:peanut :butter :and :jelly] 3)) 25 | 26 | "You can also slice a vector" 27 | (= [:butter :and] (subvec [:peanut :butter :and :jelly] 1 3)) 28 | 29 | "Equality with collections is in terms of values" 30 | (= (list 1 2 3) (vector 1 2 3))) 31 | -------------------------------------------------------------------------------- /src/koans/06_functions.clj: -------------------------------------------------------------------------------- 1 | (defn multiply-by-ten [n] 2 | (* 10 n)) 3 | 4 | (defn square [n] (* n n)) 5 | 6 | (meditations 7 | "Calling a function is like giving it a hug with parentheses" 8 | (= 81 (square 9)) 9 | 10 | "Functions are usually defined before they are used" 11 | (= 20 (multiply-by-ten 2)) 12 | 13 | "But they can also be defined inline" 14 | (= 10 ((fn [n] (* 5 n)) 2)) 15 | 16 | "Or using an even shorter syntax" 17 | (= 60 (#(* 15 %) 4)) 18 | 19 | "Even anonymous functions may take multiple arguments" 20 | (= 15 (#(+ %1 %2 %3) 4 5 6)) 21 | 22 | "Arguments can also be skipped" 23 | (= 30 (#(* 15 %2) 1 2)) 24 | 25 | "One function can beget another" 26 | (= 9 (((fn [] +)) 4 5)) 27 | 28 | "Functions can also take other functions as input" 29 | (= 20 ((fn [f] (f 4 5)) 30 | *)) 31 | 32 | "Higher-order functions take function arguments" 33 | (= 25 (#(% 5) 34 | (fn [n] (* n n)))) 35 | 36 | "But they are often better written using the names of functions" 37 | (= 25 ((fn [f] (f 5)) square))) 38 | -------------------------------------------------------------------------------- /src/koans/11_sequence_comprehensions.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "Sequence comprehensions can bind each element in turn to a symbol" 3 | (= '(0 1 2 3 4 5) 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 | (* index index))) 13 | 14 | "And also filtering" 15 | (= '(1 3 5 7 9) 16 | (filter odd? (range 10)) 17 | (for [index (range 10) :when (odd? index)] 18 | index)) 19 | 20 | "Combinations of these transformations is trivial" 21 | (= '(1 9 25 49 81) 22 | (map (fn [index] (* index index)) 23 | (filter odd? (range 10))) 24 | (for [index (range 10) :when (odd? index)] 25 | (* index index))) 26 | 27 | "More complex transformations simply take 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] 32 | column [:left :middle :right]] 33 | [row column]))) 34 | -------------------------------------------------------------------------------- /src/koans/12_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 | (= [true false true] (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? (complement 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 | (multiply-by-5 4))) 16 | 17 | "Don't forget: first things first" 18 | (= [:a :b :c :d] 19 | (let [ab-adder (partial concat [:a :b])] 20 | (ab-adder [:c :d]))) 21 | 22 | "Functions can join forces as one 'composed' function" 23 | (= 25 (let [inc-and-square (comp square inc)] 24 | (inc-and-square 4))) 25 | 26 | "Have a go on a double dec-er" 27 | (= 8 (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 (comp dec square)] 32 | (square-and-dec 10)))) 33 | -------------------------------------------------------------------------------- /src/koans/08_higher_order_functions.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "The map function relates a sequence to another" 3 | (= [4 8 12] (map (fn [x] (* 4 x)) [1 2 3])) 4 | 5 | "You may create that mapping" 6 | (= [1 4 9 16 25] (map (fn [x] (* x x)) [1 2 3 4 5])) 7 | 8 | "Or use the names of existing functions" 9 | (= [false false true false false] (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 | (= '(:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here))) 16 | 17 | "Or somewhere in between" 18 | (= [10 20 30] (filter (fn [x] (< x 36)) [10 20 30 40 50 60 70 80])) 19 | 20 | "Maps and filters may be combined" 21 | (= [10 20 30] (map (fn [x] (* 10 x)) (filter (fn [x] (< x 4)) [1 2 3 4 5 6 7 8]))) 22 | 23 | "Reducing can increase the result" 24 | (= 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)) 100 [1 2 3 4])) 28 | 29 | "Numbers are not the only things one can reduce" 30 | (= "longest" (reduce (fn [a b] 31 | (if (< (count a) (count b)) b a)) 32 | ["which" "word" "is" "longest"]))) 33 | -------------------------------------------------------------------------------- /src/koans/15_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/02_lists.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "Lists can be expressed by function or a quoted form" 3 | (= '(1 2 3 4 5) (list 1 2 3 4 5)) 4 | 5 | "They are Clojure seqs (sequences), so they allow access to the first" 6 | (= 1 (first '(1 2 3 4 5))) 7 | 8 | "As well as the rest" 9 | (= '(2 3 4 5) (rest '(1 2 3 4 5))) 10 | 11 | "Count your blessings" 12 | (= 3 (count '(dracula dooku chocula))) 13 | 14 | "Before they are gone" 15 | (= 0 (count '())) 16 | 17 | "The rest, when nothing is left, is empty" 18 | (= '() (rest '(100))) 19 | 20 | "Construction by adding an element to the front is easy" 21 | (= '(:a :b :c :d :e) (cons :a '(:b :c :d :e))) 22 | 23 | "Conjoining an element to a list isn't hard either" 24 | (= '(:e :a :b :c :d) (conj '(:a :b :c :d) :e)) 25 | 26 | "You can use a list like a stack to get the first element" 27 | (= :a (peek '(:a :b :c :d :e))) 28 | 29 | "Or the others" 30 | (= '(:b :c :d :e) (pop '(:a :b :c :d :e))) 31 | 32 | "But watch out if you try to pop nothing" 33 | (= "No dice!" (try 34 | (pop '()) 35 | (catch IllegalStateException e 36 | "No dice!"))) 37 | 38 | "The rest of nothing isn't so strict" 39 | (= '() (try 40 | (rest '()) 41 | (catch IllegalStateException e 42 | "No dice!")))) 43 | 44 | -------------------------------------------------------------------------------- /src/koans/17_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 | "I can haz 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 don't always work as you would like them to... " 39 | (= __ (macroexpand '(infix-better ( 10 + (2 * 3))))) 40 | 41 | "Really, you don't understand recursion until you understand recursion" 42 | (= 36 (r-infix (10 + (2 * 3) + (4 * 5))))) 43 | -------------------------------------------------------------------------------- /src/koans/18_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/09_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] (str (:name a) " eats veggies.")) 11 | (defmethod diet :carnivore [a] (str (:name a) " eats animals.")) 12 | (defmethod diet :default [a] "I don't know what Rich Hickey eats.") 13 | 14 | (meditations 15 | "Some functions can be used in different ways - with no arguments" 16 | (= "Hello World!" (hello)) 17 | 18 | "With one argument" 19 | (= "Hello, you silly world." (hello "world")) 20 | 21 | "Or with many arguments" 22 | (= "Hello to this group: Peter, Paul, Mary!" 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/13_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 it becomes 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 100003N))) 52 | -------------------------------------------------------------------------------- /src/koans/07_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 | (= :a (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 | (= nil (if (nil? 0) 22 | [:a :b :c])) 23 | 24 | "In others your alternative may be interesting" 25 | (= :glory (if (not (empty? ())) 26 | :doom 27 | :glory)) 28 | 29 | "You may have a multitude of possible paths" 30 | (let [x 5] 31 | (= :your-road (cond (= x 4) :road-not-taken 32 | (= x 6) :another-road-not-taken 33 | :else :your-road))) 34 | 35 | "Or your fate may be sealed" 36 | (= 'doom (if-not (zero? 0) 37 | 'doom 38 | 'doom)) 39 | 40 | "In case of emergency, sound the alarms" 41 | (= :sirens 42 | (explain-defcon-level :cocked-pistol)) 43 | 44 | "But admit it when you don't know what to do" 45 | (= :say-what? 46 | (explain-defcon-level :yo-mama))) 47 | -------------------------------------------------------------------------------- /src/koans/14_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/05_maps.clj: -------------------------------------------------------------------------------- 1 | (meditations 2 | "Don't get lost when creating a map" 3 | (= {:a 1 :b 2} (hash-map :a 1 :b 2)) 4 | 5 | "A value must be supplied for each key" 6 | (= {:a 1} (hash-map :a 1)) 7 | 8 | "The size is the number of entries" 9 | (= 2 (count {:a 1 :b 2})) 10 | 11 | "You can look up the value for a given key" 12 | (= 2 (get {:a 1 :b 2} :b)) 13 | 14 | "Maps can be used as functions to do lookups" 15 | (= 1 ({:a 1 :b 2} :a)) 16 | 17 | "And so can keywords" 18 | (= 1 (:a {:a 1 :b 2})) 19 | 20 | "But map keys need not be keywords" 21 | (= "Vancouver" ({2006 "Torino" 2010 "Vancouver" 2014 "Sochi"} 2010)) 22 | 23 | "You may not be able to find an entry for a key" 24 | (= nil (get {:a 1 :b 2} :c)) 25 | 26 | "But you can provide your own default" 27 | (= :key-not-found (get {:a 1 :b 2} :c :key-not-found)) 28 | 29 | "You can find out if a key is present" 30 | (= true (contains? {:a nil :b nil} :b)) 31 | 32 | "Or if it is missing" 33 | (= false (contains? {:a nil :b nil} :c)) 34 | 35 | "Maps are immutable, but you can create a new and improved version" 36 | (= {1 "January" 2 "February"} (assoc {1 "January" } 2 "February")) 37 | 38 | "You can also create a new version with an entry removed" 39 | (= {1 "January"} (dissoc {1 "January" 2 "February"} 2)) 40 | 41 | "Often you will need to get the keys, but the order is undependable" 42 | (= (list 2006 2010 2014) 43 | (sort (keys {2006 "Torino" 2010 "Vancouver" 2014 "Sochi"}))) 44 | 45 | "You can get the values in a similar way" 46 | (= (list "Sochi" "Torino" "Vancouver") 47 | (sort (vals {2006 "Torino" 2010 "Vancouver" 2014 "Sochi"})))) 48 | -------------------------------------------------------------------------------- /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 19 | your own branch - that way if you pull back the latest koans from master, it'll 20 | be a bit easier to manage the inevitable conflicts if we make changes to 21 | exercises you've already 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.5.1.jar](http://repo1.maven.org/maven2/org/clojure/clojure/1.5.1/clojure-1.5.1.zip) 27 | 28 | You can use [Leiningen](http://github.com/technomancy/leiningen) to 29 | automatically install the Clojure jar in the right place. Leiningen will also 30 | get you a couple more jarfiles, including JLine, which allows you some of the 31 | functionality of readline (command-line history, for example). 32 | 33 | ### Installing dependencies 34 | 35 | Dependencies are installed automatically with lein 2, but if you are still 36 | using lein 1 run 37 | 38 | `lein deps` 39 | 40 | which will download all dependencies you need to run the Clojure koans. 41 | 42 | 43 | ### Running the Koans 44 | 45 | If you're running from the zipfile or using lein 1, simply run 46 | 47 | `script/run` on Mac/\*nix 48 | 49 | `script\run` on Windows 50 | 51 | If you're running from a checkout using lein 2, run the koans via 52 | 53 | `lein koan run` 54 | 55 | It's an auto-runner, so as you save your files with the correct answers, it will 56 | advance you to the next koan or file (conveniently, all files are prefixed with 57 | the sequence that you should follow). 58 | 59 | You'll see something like this: 60 | 61 | Now meditate on /home/colin/Projects/clojure-koans/src/koans/01_equalities.clj:3 62 | --------------------- 63 | Assertion failed! 64 | We shall contemplate truth by testing reality, via equality. 65 | (= __ true) 66 | 67 | The output is telling you that you have a failing test in the file named 68 | `01_equalities.clj`, on line 3. So you just need to open that file up and make 69 | it pass! You'll always be filling in the blanks to make tests pass. 70 | Sometimes there could be several correct answers (or even an infinite number): 71 | any of them will work in these cases. Some tests will pass even if you replace 72 | the blanks with whitespace (or nothing) instead of the expected answer. Make sure 73 | you give one correct expression to replace each blank. 74 | 75 | The koans differ from normal TDD in that the tests are already written for you, 76 | so you'll have to pay close attention to the failure messages, because up until 77 | the very end, making a test pass just means that the next failure message comes 78 | up. 79 | 80 | While it might be easy (especially at first) to just fill in the blanks making 81 | things pass, you should work thoughtfully, making sure you understand why the 82 | answer is what it is. Enjoy your path to Clojure enlightenment! 83 | 84 | 85 | ### Trying more things out 86 | 87 | There's a REPL (Read-Evaluate-Print Loop) included in the Clojure Koans. Just 88 | run: 89 | 90 | `script/repl` on Mac/\*nix 91 | 92 | `script\repl` on Windows 93 | 94 | If you're on lein 2, `lein repl` is what you want instead. 95 | 96 | Here are some interesting commands you might try, once you're in a running REPL: 97 | 98 | ```clojure 99 | (find-doc "vec") 100 | (find-doc #"vec$") 101 | (doc vec) 102 | ``` 103 | 104 | And if those still don't make sense: 105 | 106 | ```clojure 107 | (doc doc) 108 | (doc find-doc) 109 | ``` 110 | 111 | will show you what those commands mean. 112 | 113 | You can exit the REPL with `CTRL-d` on any OS. 114 | 115 | 116 | ### Contributing 117 | 118 | Patches are encouraged! Make sure the answer sheet still passes 119 | (`script/test`, or `script\test` on Windows, or `lein koan test` on lein2), and 120 | send a pull request. 121 | 122 | The file ideaboard.txt has lots of good ideas for new koans to start, or things 123 | to add to existing koans. So write some fun exercises, add your answers to 124 | `resources/koans.clj`, and we'll get them in there! 125 | 126 | Feel free to contact me (Colin Jones / trptcolin) on Github or elsewhere if you 127 | have any questions or want more direction before you start pitching in. 128 | 129 | 130 | ### Contributors 131 | 132 | https://github.com/functional-koans/clojure-koans/contributors 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. 155 | -------------------------------------------------------------------------------- /resources/koans.clj: -------------------------------------------------------------------------------- 1 | [["01_equalities" {"__" [true 2 | 2 3 | 5 4 | true 5 | false 6 | true 7 | true 8 | false 9 | "foo" 10 | "foo" 11 | 3]}] 12 | 13 | ["02_lists" {"__" [1 2 3 4 5 14 | 1 15 | [2 3 4 5] 16 | 3 17 | 0 18 | () 19 | [:a :b :c :d :e] 20 | [:e :a :b :c :d] 21 | :a 22 | [:b :c :d :e] 23 | "No dice!" 24 | ()]}] 25 | 26 | ["03_vectors" {"__" [1 27 | [1] 28 | [nil nil] 29 | 2 30 | [111 222 333] 31 | :peanut 32 | :jelly 33 | :jelly 34 | [:butter :and] 35 | 3]}] 36 | 37 | ["04_sets" {"__" [[3] 38 | 3 39 | #{1 2 3 4 5} 40 | #{1 2 3 4 5} 41 | #{2 3} 42 | #{1 4}]}] 43 | 44 | ["05_maps" {"__" [:b 2 45 | 1 46 | 2 47 | 2 48 | 1 49 | 1 50 | "Vancouver" 51 | nil 52 | :key-not-found 53 | true 54 | false 55 | "February" 56 | 1 "January" 57 | 2006 2010 2014 58 | "Vancouver"]}] 59 | 60 | ["06_functions" {"__" [81 61 | 20 62 | 10 63 | 60 64 | 15 65 | 30] 66 | "___" [+ 67 | * 68 | (fn [f] (f 5)) 69 | (fn [f] (f 5))]}] 70 | 71 | ["07_conditionals" {"__" [:a 72 | [] 73 | nil 74 | :glory 75 | 4 6 :your-road 76 | 'doom 0 77 | :cocked-pistol 78 | :say-what?]}] 79 | 80 | ["08_higher_order_functions" {"__" [4 8 12 81 | (* x x) 82 | [false false true false false] 83 | () 84 | [:anything :goes :here] 85 | (< x 31) 86 | (* 10 x) (< x 4) 87 | 24 88 | 100 89 | (count a) (count b)]}] 90 | 91 | ["09_runtime_polymorphism" {"__" [(str (:name a) " eats veggies.") 92 | (str (:name a) " eats animals.") 93 | (str "I don't know what " (:name a) " eats.") 94 | "Hello World!" 95 | "Hello, you silly world." 96 | "Hello to this group: Peter, Paul, Mary!" ]}] 97 | 98 | ["10_lazy_sequences" {"__" [[1 2 3 4] 99 | [0 1 2 3 4] 100 | 10 101 | 95 102 | (range 20) 103 | :a] 104 | "___" [(fn [x] :foo)]}] 105 | 106 | ["11_sequence_comprehensions" {"__" [[0 1 2 3 4 5] 107 | (* index index) 108 | (range 10) 109 | (odd? index) (* index index) 110 | [row column] 111 | ]}] 112 | 113 | ["12_creating_functions" {"__" [true false true 114 | 4 115 | :a :b :c :d 116 | :c :d 117 | 4 118 | 8] 119 | "___" [(complement nil?) 120 | multiply-by-5 121 | (comp dec square)]}] 122 | 123 | ["13_recursion" {"__" [true 124 | acc 125 | (loop [coll coll 126 | acc ()] 127 | (if (seq coll) 128 | (recur (rest coll) (conj acc (first coll))) 129 | acc)) 130 | (loop [n n 131 | acc 1] 132 | (if (zero? n) 133 | acc 134 | (recur (dec n) (* acc n))))] 135 | "___" [not]}] 136 | 137 | ["14_destructuring" {"__" [":bar:foo" 138 | (format (str "First comes %s, " 139 | "then comes %s, " 140 | "then comes %s with the baby carriage") 141 | a b c) 142 | (apply str 143 | (interpose " " 144 | (apply list 145 | first-name 146 | last-name 147 | (interleave (repeat "aka") aliases)))) 148 | {:original-parts full-name 149 | :named-parts {:first first-name :last last-name}} 150 | (str street-address ", " city ", " state) 151 | city state 152 | (str street-address ", " city ", " state)] 153 | "___" [(fn [[fname lname] 154 | {:keys [street-address city state]}] 155 | (str fname " " lname ", " 156 | street-address ", " city ", " state)) 157 | ]}] 158 | 159 | ["15_refs" {"__" ["hello" 160 | "hello" 161 | "better" 162 | "better!!!" 163 | (dosync (ref-set the-world 0)) 164 | (map :jerry [@the-world @bizarro-world]) 165 | ] 166 | "___" [(fn [x] (+ 20 x))]}] 167 | 168 | ["16_atoms" {"__" [0 169 | 1 170 | (swap! atomic-clock (partial + 4)) 171 | 20 172 | 20 173 | atomic-clock 20 :fin 174 | ]}] 175 | 176 | ["17_macros" {"__" [~(first form) 177 | ~(nth form 2) 178 | form 179 | (drop 2 form) 180 | "Hello, Macros!" 181 | 10 182 | '(+ 9 1) 183 | '(* 10 2) 184 | '(+ 10 (2 * 3))]}] 185 | 186 | ["18_datatypes" {"__" [(print 187 | (str "You're really the " 188 | (.category this) 189 | ", " recipient "... sorry.")) 190 | "peace" 191 | "literature" 192 | "physics" 193 | nil 194 | [true false] 195 | (str "Congratulations on your Best Picture Oscar, " 196 | "Evil Alien Conquerors!")]}] 197 | 198 | ["19_java_interop" {"__" [java.lang.String 199 | "SELECT * FROM" 200 | 10 201 | 1024 202 | ] 203 | "___" [#(.toUpperCase %) 204 | ] 205 | }] 206 | ["20_partition" {"__" [partition 207 | [:a :b :c] 208 | '((0 1 2) (3 4)) 209 | 5 210 | :hello 211 | (6 :this :are) 212 | ]}]] 213 | -------------------------------------------------------------------------------- /epl-v10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 |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 | --------------------------------------------------------------------------------