Skip to content

Commit

Permalink
expand on maps delete to handle the case where word doesn't exist (#787)
Browse files Browse the repository at this point in the history
  • Loading branch information
primlock authored Nov 22, 2024
1 parent 6d7369e commit 51affc7
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 14 deletions.
63 changes: 60 additions & 3 deletions maps.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions maps/v6/dictionary.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 15 additions & 4 deletions maps/v7/dictionary.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
24 changes: 19 additions & 5 deletions maps/v7/dictionary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 51affc7

Please sign in to comment.