From 51affc7c16fab8f56fe380ad5afad3390a8123b5 Mon Sep 17 00:00:00 2001 From: Alex Reynolds <50781608+reyncode@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:00:22 -0400 Subject: [PATCH] expand on maps delete to handle the case where word doesn't exist (#787) --- maps.md | 63 ++++++++++++++++++++++++++++++++++++-- maps/v6/dictionary.go | 4 +-- maps/v7/dictionary.go | 19 +++++++++--- maps/v7/dictionary_test.go | 24 ++++++++++++--- 4 files changed, 96 insertions(+), 14 deletions(-) diff --git a/maps.md b/maps.md index 222f9d9ff..b58897951 100644 --- a/maps.md +++ b/maps.md @@ -537,7 +537,7 @@ We get 3 errors this time, but we know how to deal with these. const ( ErrNotFound = DictionaryErr("could not find the word you were looking for") ErrWordExists = DictionaryErr("cannot add word because it already exists") - ErrWordDoesNotExist = DictionaryErr("cannot update word because it does not exist") + ErrWordDoesNotExist = DictionaryErr("cannot perform operation on word because it does not exist") ) func (d Dictionary) Update(word, definition string) error { @@ -631,9 +631,66 @@ func (d Dictionary) Delete(word string) { } ``` -Go has a built-in function `delete` that works on maps. It takes two arguments. The first is the map and the second is the key to be removed. +Go has a built-in function `delete` that works on maps. It takes two arguments and returns nothing. The first argument is the map and the second is the key to be removed. -The `delete` function returns nothing, and we based our `Delete` method on the same notion. Since deleting a value that's not there has no effect, unlike our `Update` and `Add` methods, we don't need to complicate the API with errors. +## Refactor +There isn't much to refactor, but we can implement the same logic from `Update` to handle cases where word doesn't exist. + +```go +func TestDelete(t *testing.T) { + t.Run("existing word", func(t *testing.T) { + word := "test" + dictionary := Dictionary{word: "test definition"} + + err := dictionary.Delete(word) + + assertError(t, err, nil) + + _, err = dictionary.Search(word) + + assertError(t, err, ErrNotFound) + }) + + t.Run("non-existing word", func(t *testing.T) { + word := "test" + dictionary := Dictionary{} + + err := dictionary.Delete(word) + + assertError(t, err, ErrWordDoesNotExist) + }) +} +``` + +## Try to run test + +The compiler will fail because we are not returning a value for `Delete`. + +``` +./dictionary_test.go:77:10: dictionary.Delete(word) (no value) used as value +./dictionary_test.go:90:10: dictionary.Delete(word) (no value) used as value +``` + +## Write enough code to make it pass + +```go +func (d Dictionary) Delete(word string) error { + _, err := d.Search(word) + + switch err { + case ErrNotFound: + return ErrWordDoesNotExist + case nil: + delete(d, word) + default: + return err + } + + return nil +} +``` + +We are again using a switch statement to match on the error when we attempt to delete a word that doesn't exist. ## Wrapping up diff --git a/maps/v6/dictionary.go b/maps/v6/dictionary.go index 084d9e600..4e5a558f8 100644 --- a/maps/v6/dictionary.go +++ b/maps/v6/dictionary.go @@ -7,8 +7,8 @@ const ( // ErrWordExists means you are trying to add a word that is already known ErrWordExists = DictionaryErr("cannot add word because it already exists") - // ErrWordDoesNotExist occurs when trying to update a word not in the dictionary - ErrWordDoesNotExist = DictionaryErr("cannot update word because it does not exist") + // ErrWordDoesNotExist occurs when trying to perform an operation on a word not in the dictionary + ErrWordDoesNotExist = DictionaryErr("cannot perform operation on word because it does not exist") ) // DictionaryErr are errors that can happen when interacting with the dictionary. diff --git a/maps/v7/dictionary.go b/maps/v7/dictionary.go index 513879877..6833d912b 100644 --- a/maps/v7/dictionary.go +++ b/maps/v7/dictionary.go @@ -7,8 +7,8 @@ const ( // ErrWordExists means you are trying to add a word that is already known ErrWordExists = DictionaryErr("cannot add word because it already exists") - // ErrWordDoesNotExist occurs when trying to update a word not in the dictionary - ErrWordDoesNotExist = DictionaryErr("cannot update word because it does not exist") + // ErrWordDoesNotExist occurs when trying to perform an operation on a word not in the dictionary + ErrWordDoesNotExist = DictionaryErr("cannot perform operation on word because it does not exist") ) // DictionaryErr are errors that can happen when interacting with the dictionary. @@ -64,6 +64,17 @@ func (d Dictionary) Update(word, definition string) error { } // Delete removes a word from the dictionary. -func (d Dictionary) Delete(word string) { - delete(d, word) +func (d Dictionary) Delete(word string) error { + _, err := d.Search(word) + switch err { + case ErrNotFound: + return ErrWordDoesNotExist + case nil: + delete(d, word) + default: + return err + + } + + return nil } diff --git a/maps/v7/dictionary_test.go b/maps/v7/dictionary_test.go index 570b253b0..15b8703d4 100644 --- a/maps/v7/dictionary_test.go +++ b/maps/v7/dictionary_test.go @@ -68,13 +68,27 @@ func TestUpdate(t *testing.T) { } func TestDelete(t *testing.T) { - word := "test" - dictionary := Dictionary{word: "test definition"} + t.Run("existing word", func(t *testing.T) { + word := "test" + dictionary := Dictionary{word: "test definition"} - dictionary.Delete(word) + err := dictionary.Delete(word) + + assertError(t, err, nil) + + _, err = dictionary.Search(word) + + assertError(t, err, ErrNotFound) + }) - _, err := dictionary.Search(word) - assertError(t, err, ErrNotFound) + t.Run("non-existing word", func(t *testing.T) { + word := "test" + dictionary := Dictionary{} + + err := dictionary.Delete(word) + + assertError(t, err, ErrWordDoesNotExist) + }) } func assertStrings(t testing.TB, got, want string) {