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.

Optional extras:

  • 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

  • src/playground/recent-song-list.clj
  • test/playground/recent-song-list-test.clj

Include clojure.test

We are writing our tests with the clojure.test library so we need to include that first

Open test/playground/recent-song-list-test.clj file in your editor and update the namespace definition to include clojure.test

(ns playground.recent-song-list-test
  (:require [clojure.test :refer :all]
            [playground.recent-song-list :refer :all]))

Run Tests

At any time we can use the run-tests function to get a report back on all of the tests in our current namespace (recent-song-list)

(run-tests)

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?

Reveal answer...
(def recent-songs [])

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.

Suggested test...

A simple test that checks for a recent-songs list, checking

(deftest song-list-exists-test
  (testing "Does a recent song list exist"
    (is (vector? recent-songs))))

Write a test to check the song-list is empty

The recent song list should be empty to start with.

Suggested test...

A simple test that compares an empty vector with the value of recent-songs

(deftest song-list-empty-test
  (testing "Is song list empty if we havent added any songs"
    (is
     (= [] recent-songs))))

Here is the same test using the empty? function instead of the = function.

(deftest song-list-empty-test-2
  (testing "Is song list empty if we havent added any songs"
    (is
     (empty? recent-songs))))

Hint

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

Suggested test...
(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" )))))))
Suggested Code Solution...

This suggested solution defines our recent songs as an empty vector.

The 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.

The 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 song-list.

The results of the remove expression are then passed to the cons expressoin 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)))

results matching ""

    No results matching ""