├── .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 | 
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 |
--------------------------------------------------------------------------------