Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expanding on maps delete to make it more consistent with add and update #787

Merged
merged 1 commit into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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