├── .gitignore ├── project.clj ├── README.md ├── src └── socrate2017 │ └── core.clj └── test └── socrate2017 └── core_test.clj /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | pom.xml 5 | pom.xml.asc 6 | *.jar 7 | *.class 8 | /.lein-* 9 | /.nrepl-port 10 | .hgignore 11 | .hg/ 12 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject socrate2017 "0.1.0-SNAPSHOT" 2 | :description "FIXME: write description" 3 | :url "http://example.com/FIXME" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | :dependencies [[org.clojure/clojure "1.8.0"]]) 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Socrates 2017 - Clojure & Haskell kata night 2 | 3 | Results of a coding exercise at Socrates 2017, tackling the _recently used list_ kata. 4 | 5 | This kata was interpreted as a song list, something like spotify. The most recent song playing is at the start of the list. The list of songs is unique, so no song appears in the list more than once. 6 | 7 | Two teams, one Clojure and one Haskell solved this kata using a TDD approach. This is the code from the Clojure team 8 | 9 | 10 | ## Kata: Recently Used List 11 | 12 | Develop a recently-used-list class to hold strings uniquely in Last-In-First-Out order. 13 | 14 | - The most recently added item is first, the least recently added item is last. 15 | 16 | - Items can be looked up by index, which counts from zero. 17 | 18 | - Items in the list are unique, so duplicate insertions are moved rather than added. 19 | 20 | - A recently-used-list is initially empty. 21 | 22 | Optional extras: 23 | 24 | - Null insertions (empty strings) are not allowed. 25 | 26 | - A bounded capacity can be specified, so there is an upper limit to the number of items contained, with the least recently added items dropped on overflow. 27 | 28 | 29 | ## Usage 30 | 31 | Run the tests using the following terminal command: 32 | 33 | ```bash 34 | lein test 35 | ``` 36 | 37 | Run the tests in Emacs / Spacemacs using `M-x cider-test-run-all-tests` 38 | 39 | 40 | The code has only been writen to run in the repl 41 | 42 | ## License 43 | 44 | Copyright © 2017 jr0cket 45 | 46 | Distributed under the Creative Commons Attribution-ShareAlike 4.0 International 47 | 48 | Creative Commons Licence
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. 49 | -------------------------------------------------------------------------------- /src/socrate2017/core.clj: -------------------------------------------------------------------------------- 1 | (ns socrate2017.core) 2 | 3 | 4 | (def recent-songs []) 5 | 6 | (defn add-song [song song-list] 7 | (->> song-list 8 | (remove #(= song %)) 9 | (cons song))) 10 | 11 | 12 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 13 | ;; REPL Driven Development 14 | 15 | ;; (cons "Daft Punk - Get Lucky" recent-songs) 16 | 17 | ;; (add-song "Daft Punk - Get Lucky" recent-songs) 18 | 19 | 20 | 21 | ;; can we add a value to a collection that so that each new value is at the start of the list 22 | 23 | (cons 1 '()) 24 | ;; => (1) 25 | 26 | (cons 1 '(2)) 27 | ;; => (1 2) 28 | 29 | (cons 2 '(3 4 5)) 30 | ;; => (2 3 4 5) 31 | 32 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 33 | ;; Can I look up a list by index, eg. using (nth list-name 0) 34 | 35 | (nth '(1 2 3 4 5) 1) 36 | ;; => 2 37 | 38 | 39 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 40 | ;; Which collections are not unique 41 | 42 | ;; No... 43 | (list 1 2 3 2 1) ;; => (1 2 3 2 1) 44 | 45 | ;; sets 46 | ;; yes, but are not ordered 47 | (set '(1 2 3 4 3 2 1)) ;; => #{1 4 3 2} 48 | 49 | ;; what if we add to a set 50 | ;; cons seems to consistently add values to the front of the set 51 | ;; sets will not allow duplicates to be added 52 | ;; still need remove the existing value from the position (if its not the first position) 53 | (cons 6 54 | (cons 5 #{1 4 3 2})) 55 | ;; => (6 5 1 4 3 2) 56 | 57 | 58 | ;; sorted sets 59 | ;; actually we dont want clojure to order things for us though 60 | ;; seems a sorted set is not unique either 61 | (sorted-set '(1 2 3 4 3 2 1)) 62 | ;; => #{(1 2 3 4 3 2 1)} 63 | 64 | 65 | ;; finding an existing element in a collection 66 | 67 | ;; some 68 | ;; contains 69 | 70 | ;; or just filter the whole collection of songs, returning those that dont match the latest one 71 | ;; then the latest song can be added to the top of the song list. 72 | 73 | (def song-to-add "Love on the rocks") 74 | (def song-list '("Sususudio" "Love on the rocks")) 75 | 76 | ;; filter will map a predicate function over a collection of values 77 | ;; so filter returns all the songs not equal to the song to add 78 | 79 | (filter #(not= song-to-add %) song-list) 80 | ;; => ("Sususudio") 81 | 82 | ;; remove works just like filter, except it complements the predicate 83 | ;; so the = function can be used over not= functions - making the logic easier to read 84 | 85 | (remove #(= song-to-add %) song-list) 86 | ;; => ("Sususudio") 87 | -------------------------------------------------------------------------------- /test/socrate2017/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns socrate2017.core-test 2 | (:require [clojure.test :refer :all] 3 | [socrate2017.core :refer :all])) 4 | 5 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 | ;; Socrates 2017 Kata - Last night 7 | ;; 8 | ;; https://github.com/garora/TDD-Katas 9 | 10 | 11 | 12 | (deftest a-test 13 | (testing "FIXME, I fail." 14 | (is (= 1 1)))) 15 | 16 | (deftest get-song-list-test 17 | (testing "get empty recent song list" 18 | (is 19 | (= [] recent-songs))) 20 | (testing "check recent songs is empty" 21 | (is 22 | (empty? recent-songs)))) 23 | 24 | 25 | (deftest adding-songs-test 26 | 27 | (testing "add song returns a song list with entries" 28 | (is 29 | (not (empty? 30 | (add-song "Barry Manilow - Love on the rocks" recent-songs))))) 31 | 32 | (testing "add multiple song returns a song list with entries" 33 | (is 34 | (not (empty? 35 | (->> recent-songs 36 | (add-song "Barry Manilow - Love on the rocks") 37 | (add-song "Phil Colins - Sususudio" ))))))) 38 | 39 | 40 | (deftest recently-added-song-first-test 41 | 42 | (testing "most recent song should be first in the list when empty list" 43 | (is (= 44 | (first (add-song "Daft Punk - Get Lucky" recent-songs)) 45 | "Daft Punk - Get Lucky"))) 46 | 47 | (testing "most recent song should be first in list when adding multiple songs" 48 | (is (= 49 | (first 50 | (->> recent-songs 51 | (add-song "Daft Punk - Get Lucky") 52 | (add-song "Pharrell Williams - Happy"))) 53 | "Pharrell Williams - Happy"))) 54 | 55 | (testing "most recent song should be first in list when adding a repeated song" 56 | (is (= 57 | (first 58 | (->> recent-songs 59 | (add-song "Pharrell Williams - Happy") 60 | (add-song "Daft Punk - Get Lucky") 61 | (add-song "Pharrell Williams - Happy"))) 62 | "Pharrell Williams - Happy"))) 63 | 64 | (testing "most recent song should be first in list when adding a repeated song" 65 | (is (not= 66 | (last 67 | (->> recent-songs 68 | (add-song "Pharrell Williams - Happy") 69 | (add-song "Daft Punk - Get Lucky") 70 | (add-song "Pharrell Williams - Happy"))) 71 | "Pharrell Williams - Happy")))) 72 | 73 | 74 | 75 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 76 | ;; Song titles 77 | 78 | ;; "Daft Punk - Get Lucky" 79 | --------------------------------------------------------------------------------