code kata: recent song playlist
Solve this challenge using a project in your editor
Create a recent song list to hold a unique set of songs that have been played.
The most recently played song is at the start of the list, the least recently played song is the last in the list.
- A recently-used-list is initially empty.
- Songs in the list are unique, so repeatedly played songs should only appear once in the list
- Songs can be looked up by index, which counts from zero.
- Empty song names are not allowed.
- Add a limit to the number of songs the list contains, with the least recently added items dropped when that limit is reached.
Add two files to the playground project
Open the playground project you created at the start of the workshop. Or create it now with the command line
lein new playground.
Add the following two files to the project
We are writing our tests with the
clojure.test library so we need to include that first
test/playground/recent-song-list-test.clj file in your editor and update the namespace definition to include
(ns playground.recent-song-list-test (:require [clojure.test :refer :all] [playground.recent-song-list :refer :all]))
At any time we can use the
run-tests function to get a report back on all of the tests in our current namespace (
Define a recent song list
In the source file,
src/playground/recent-song-list.clj, define a name for your collection of recent songs
You can use an empty collection to start with. Which collection type will you use though?
Write a test to check a song-list exists
Write a test to see if a recent song list exists.
This is an opportunity to think about what kind of data structure you want to use to hold your recent song list.
Write a test to check the song-list is empty
The recent song list should be empty to start with.
A simple test that compares an empty vector with the value of
(deftest song-list-empty-test (testing "Is song list empty if we haven't added any songs" (is (=  recent-songs))))
Here is the same test using the
empty? function instead of the
(deftest song-list-empty-test-2 (testing "Is song list empty if we haven't added any songs" (is (empty? recent-songs))))
You could use either of these tests to replace the song list exists test, as these tests would fail if the song list did not exist.
Write a test to add a song to the list
Add a song to the collection, for example
Tubular Bells - Mike Oldfield
(deftest adding-songs-test (testing "add song returns a song list with entries" (is (not (empty? (add-song "Barry Manilow - Love on the rocks" recent-songs))))) (testing "add multiple song returns a song list with entries" (is (not (empty? (->> recent-songs (add-song "Barry Manilow - Love on the rocks") (add-song "Phil Colins - Sususudio" )))))))
This suggested solution defines our recent songs as an empty vector.
add-song function takes the name of a song and the song list to which it will be added.
A Thread-last macro
->> is used to pass the song list over two functions.
song-list is first passed to the
remove expression as its last argument. This expression will remove any occurrence of the new song we want to add from the
The results of the
remove expression are then passed to the
cons expression as its last argument. The
cons expression simply adds the new song to the start of the list, making it the most recent song.
(def recent-songs ) (defn add-song [song song-list] (->> song-list (remove #(= song %)) (cons song)))