docs: DeleteFunc, Collect
This commit is contained in:
@@ -319,7 +319,19 @@ The following changes will be made to accomodate for congruency:
|
||||
To solve this, we need a new function:
|
||||
|
||||
```go
|
||||
func EqualFunc[K, V1, V2 any](t1 *Table[K, V1], t2 *Table[K, V2], eq func(V1, V2) bool) bool
|
||||
func EqualFunc[K, V1, V2 any](t1 *Table[K, V1], t2 *Table[K, V2], eq func(V1, V2) bool) bool {
|
||||
if t1.Size() != t2.Size() {
|
||||
return false
|
||||
}
|
||||
|
||||
for k, v1 := range t1.Entries() {
|
||||
if v2, ok := t2.Get(k); !ok || eq(v1, v2) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
This function is free, and not bound as a receiver function.
|
||||
@@ -339,6 +351,10 @@ So, we must assume that:
|
||||
- Both tables have `EqualFunc`'s which 'agree' on the identity of the keys present in the tables.
|
||||
Agreement is defined as: if two keys are distinct in one table, they are distinct in the other.
|
||||
|
||||
The name `EqualFunc` is already taken by `EqualFunc[K, V]`: an alias for `func(a, b K) bool`.
|
||||
Inlining `EqualFunc[K, V]` would solve this problem.
|
||||
The documentation attached to it would be moved to `DefaultEqualFunc`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -363,25 +379,38 @@ Once again, the function is free because it is symmetric.
|
||||
This functionality requires a new receiver:
|
||||
|
||||
```go
|
||||
func (t *Table[K, V]) Insert(seq *iter.Seq2[K, V]) error
|
||||
func (t *Table[K, V]) Insert(seq iter.Seq2[K, V]) error {
|
||||
for k, v := range seq {
|
||||
if err := t.Put(k, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
A receiver fits better even though `maps.Insert` is a free function, because copying it is asymmetric.
|
||||
Map `dst` receives entries from map `src`.
|
||||
It is only free because Go's standard map is built into the language, and so cannot have receivers.
|
||||
It's only free because Go's standard map is built into the language, and so cannot have receivers.
|
||||
|
||||
In terms of naming, `t.Extend` is more accurate, and has precedent in [Python](docs.python.org/3/tutorial/datastructures.html#more-on-lists) and [Rust](https://doc.rust-lang.org/std/iter/trait.Extend.html).
|
||||
Ultimately, `t.Insert()` is a better choice because of
|
||||
When [adding iterator function](https://github.com/golang/go/issues/61900) to the `maps` package, the Go team chose to frame it as 'sources' and 'sinks'.
|
||||
With this model, `maps.Insert` made more sense than `maps.Extend`.
|
||||
Ultimately, `t.Insert()` is a better choice to be consistent with `maps`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><code>maps.Copy(dst, src)</code></summary>
|
||||
|
||||
To solve this, we must implement a new receiver:
|
||||
To solve this, we must implement a new receiver.
|
||||
Luckily, `t.Insert` makes it trivial:
|
||||
|
||||
```go
|
||||
func (t *Table[K, V]) Copy(src *Table[K, V]) error
|
||||
func (t *Table[K, V]) Copy(src *Table[K, V]) error {
|
||||
return t.Insert(src.Entries())
|
||||
}
|
||||
```
|
||||
|
||||
A receiver fits better even though `maps.Copy` is a free function, 'copying' it is asymmetric: `dst` is writen into by `src`.
|
||||
@@ -395,3 +424,54 @@ The name `t.Merge()` might be more accurate, but it does work because:
|
||||
It simply overwrites the values.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><code>maps.DeleteFunc(m, fn)</code></summary>
|
||||
|
||||
A few function can fill this gap:
|
||||
|
||||
```go
|
||||
func (t *Table[K, V]) DeleteFunc(del func(K, V) bool) {
|
||||
for k, v := range t.Entries() {
|
||||
if del(k, v) {
|
||||
t.Drop(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It would have the same functionality as `maps.DeleteFunc`.
|
||||
|
||||
A free function could work here, but `t` has clear authority over `del`.
|
||||
Other than being consistent with the `maps` package, `t.DeleteFunc` follows the Go convention of appending `Func` to higher-order equivalents of functions.
|
||||
This trumps names like `t.DeleteIf`, which lend more to [Java](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#removeIf-java.util.function.Predicate-) or [C++](https://en.cppreference.com/cpp/algorithm/remove).
|
||||
The word `Delete` is also convention, tying back to the built-in `delete()`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><code>m := maps.Collect(seq)</code></summary>
|
||||
|
||||
This functionality would benefit from a new constructor.
|
||||
Luckily, `t.Insert` makes this easy:
|
||||
|
||||
```go
|
||||
func Collect[K comparable, V any](seq iter.Seq2[K, V]) (*Table[K, V], error) {
|
||||
t := New[K, V]()
|
||||
err := t.Insert(seq)
|
||||
return t, err
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><code>m := map[K]V{...}</code></summary>
|
||||
|
||||
This functionality is complicated, because entries are generic; their addition cannot be through table options.
|
||||
A new constructor must support this functionality.
|
||||
|
||||
Should it support options or custom hashes or `keyFunc`'s?
|
||||
No, because
|
||||
|
||||
</details>
|
||||
|
||||
Reference in New Issue
Block a user