Skip to content

Commit

Permalink
Added map helpers (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
marrow16 authored Dec 24, 2022
1 parent 6ce6f0c commit c297cd4
Show file tree
Hide file tree
Showing 5 changed files with 363 additions and 70 deletions.
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,15 @@ func main() {
<th>Method and description</th>
<th>Returns</th>
</tr>
<tr></tr>
<tr>
<td>
<code>AsEmpty()</code><br>
returns a new empty optional of the same type
</td>
<td><code>*Optional[T]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>Clear()</code><br>
Expand All @@ -144,6 +146,15 @@ func main() {
</td>
<td><code>*Optional[T]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>Default(v T)</code><br>
returns the value if present, otherwise returns the provided default value
</td>
<td><code>T</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>Filter(f func(v T) bool)</code><br>
Expand All @@ -152,13 +163,15 @@ func main() {
</td>
<td><code>*Optional[T]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>Get()</code><br>
returns the value and an error if the value is not present
</td>
<td><code>(T, error)</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>GetOk()</code><br>
Expand All @@ -167,6 +180,7 @@ func main() {
</td>
<td><code>(T, bool)</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>IfElse(condition bool, other T)</code><br>
Expand All @@ -175,6 +189,7 @@ func main() {
</td>
<td><code>T</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>IfPresent(f func(v T))</code><br>
Expand All @@ -183,6 +198,7 @@ func main() {
</td>
<td><code>*Optional[T]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>IfPresentOtherwise(f func(v T), other func())</code><br>
Expand All @@ -191,6 +207,7 @@ func main() {
</td>
<td><code><code>*Optional[T]</code></code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>IfSet(f func(v T), notPresent func())</code><br>
Expand All @@ -201,6 +218,7 @@ func main() {
</td>
<td><code>*Optional[T]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>IfSetOtherwise(f func(v T), notPresent func(), other func())</code><br>
Expand All @@ -211,13 +229,15 @@ func main() {
</td>
<td><code><code>*Optional[T]</code></code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>IsPresent()</code><br>
returns true if the value is present, otherwise false
</td>
<td><code>bool</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>Map(f func(v T) any)</code><br>
Expand All @@ -227,6 +247,7 @@ func main() {
</td>
<td><code>*Optional[any]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>MarshalJSON()</code><br>
Expand All @@ -236,27 +257,31 @@ func main() {
</td>
<td><code>([]byte, error)</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>OrElse(other T)</code><br>
returns the value if present, otherwise returns other
</td>
<td><code>T</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>OrElseError(err error)</code><br>
returns the supplied error if the value is not present, otherwise returns nil
</td>
<td><code>error</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>OrElseGet(f func() T)</code><br>
returns the value if present, otherwise returns the result of calling the supplied function
</td>
<td><code>T</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>OrElsePanic(v any)</code><br>
Expand All @@ -265,20 +290,23 @@ func main() {
</td>
<td><code>*Optional[T]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>OrElseSet(v T)</code><br>
if the value is not present it is set to the supplied value
</td>
<td><code>*Optional[T]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>Scan(value interface{})</code><br>
implements sql.Scan
</td>
<td><code>error</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>UnSet()</code><br>
Expand All @@ -287,6 +315,7 @@ func main() {
</td>
<td><code>*Optional[T]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>UnmarshalJSON(data []byte)</code><br>
Expand All @@ -297,6 +326,7 @@ func main() {
</td>
<td><code>error</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>WasSet()</code><br>
Expand All @@ -306,13 +336,15 @@ func main() {
</td>
<td><code>bool</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>WasSetElse(other T)</code><br>
returns the value if present and set, otherwise returns other
</td>
<td><code>T</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>WasSetElseError(err error)</code><br>
Expand All @@ -321,6 +353,7 @@ func main() {
</td>
<td><code>error</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>WasSetElseGet(f func() T)</code><br>
Expand All @@ -329,6 +362,7 @@ func main() {
</td>
<td><code>T</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>WasSetElsePanic(v any)</code><br>
Expand All @@ -337,6 +371,7 @@ func main() {
</td>
<td><code>*Optional[T]</code></td>
</tr>
<tr></tr>
<tr>
<td>
<code>WasSetElseSet(v T)</code><br>
Expand Down Expand Up @@ -398,7 +433,7 @@ func main() {
<tr>
<td>
<code>EmptyInt8() *Optional[int8]</code><br>
7 returns an empty optional of type <code>int8</code>
returns an empty optional of type <code>int8</code>
</td>
</tr>
<tr>
Expand Down
104 changes: 83 additions & 21 deletions maps.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,94 @@
package gopt

// Extract extracts an optional value, of the specified type, from a map
//
// If the key is present (and the value is non-nil and of the specified type) then an optional with the value is returned, otherwise an empty optional is returned
func Extract[K comparable, T any](m map[K]any, key K) *Optional[T] {
result := Empty[T]()
if rv, ok := m[key]; ok && isPresent(rv) {
if v, ok := rv.(T); ok {
result = Of[T](v)
}
}
return result
}

// ExtractJson extracts an optional value, of the specified type, from a map[string]interface{}
//
// If the key is present (and the value is non-nil and of the specified type) then an optional with the value is returned, otherwise an empty optional is returned
func ExtractJson[T any](m map[string]interface{}, key string) *Optional[T] {
result := Empty[T]()
if rv, ok := m[key]; ok && isPresent(rv) {
if v, ok := rv.(T); ok {
result = Of[T](v)
}
}
return result
}

// Get obtains an optional from a map
//
// If the key is present (and the value is non-nil) then an optional with the value is returned, otherwise an empty optional is returned
func Get[K comparable, T any](m map[K]T, key K) *Optional[T] {
if v, ok := m[key]; ok && isPresent(v) {
return Of(v)
}
return Empty[T]()
}

// OptMap can be used to cast an existing map for optional/functional methods
type OptMap[K comparable, V any] map[K]V

// Get returns an optional of the value in the map
//
// If the value is not present (or is nil) then an empty optional is returned
func (m OptMap[K, V]) Get(k K) *Optional[V] {
return Map(m, k)
func (m OptMap[K, V]) Get(key K) *Optional[V] {
return Get(m, key)
}

// Default returns the value (if present and non-nil) otherwise returns the default value
func (m OptMap[K, V]) Default(k K, def V) V {
return Map(m, k).Default(def)
func (m OptMap[K, V]) Default(key K, def V) V {
return Get(m, key).Default(def)
}

// IfPresent if the key is present (and the value is non-nil) calls the supplied function with the key and value
//
// otherwise does nothing
func (m OptMap[K, V]) IfPresent(key K, f func(key K, v V)) OptMap[K, V] {
if f != nil {
if v, ok := m[key]; ok && isPresent(v) {
f(key, v)
}
}
return m
}

// IfPresentOtherwise if the key is present (and the value is non-nil) calls the supplied function with the key and value
//
// otherwise calls the other function with they key
func (m OptMap[K, V]) IfPresentOtherwise(key K, f func(key K, v V), other func(key K)) OptMap[K, V] {
if v, ok := m[key]; ok && isPresent(v) {
if f != nil {
f(key, v)
}
} else if other != nil {
other(key)
}
return m
}

// ComputeIfAbsent if the specified key is not present (or the value is nil) sets the value according to the specified function
//
// returns either the existing value or the newly set value
func (m OptMap[K, V]) ComputeIfAbsent(k K, f func(k K) V) V {
if v, ok := m[k]; ok && isPresent(v) {
func (m OptMap[K, V]) ComputeIfAbsent(key K, f func(key K) V) V {
if v, ok := m[key]; ok && isPresent(v) {
return v
}
var rv V
if f != nil {
rv = f(k)
rv = f(key)
if isPresent(rv) {
m[k] = rv
m[key] = rv
}
}
return rv
Expand All @@ -35,14 +97,14 @@ func (m OptMap[K, V]) ComputeIfAbsent(k K, f func(k K) V) V {
// ComputeIfPresent if the specified key is present (and the value is non-nil) attempts to compute a new mapping using the supplied function
//
// If the supplied function is called but returns a nil value, the key is deleted
func (m OptMap[K, V]) ComputeIfPresent(k K, f func(k K, v V) V) V {
func (m OptMap[K, V]) ComputeIfPresent(key K, f func(key K, v V) V) V {
var rv V
if v, ok := m[k]; ok && isPresent(v) && f != nil {
rv = f(k, v)
if v, ok := m[key]; ok && isPresent(v) && f != nil {
rv = f(key, v)
if isPresent(rv) {
m[k] = rv
m[key] = rv
} else {
delete(m, k)
delete(m, key)
}
}
return rv
Expand All @@ -51,9 +113,9 @@ func (m OptMap[K, V]) ComputeIfPresent(k K, f func(k K, v V) V) V {
// PutIfAbsent if the specified key if absent (not present or nil-value) it is set to the specified value
//
// returns true if the value was set
func (m OptMap[K, V]) PutIfAbsent(k K, v V) bool {
if ov, ok := m[k]; !ok || !isPresent(ov) {
m[k] = v
func (m OptMap[K, V]) PutIfAbsent(key K, v V) bool {
if ov, ok := m[key]; !ok || !isPresent(ov) {
m[key] = v
return true
}
return false
Expand All @@ -64,14 +126,14 @@ func (m OptMap[K, V]) PutIfAbsent(k K, v V) bool {
// returns true if the value was replaced
//
// If the specified replacement value is nil and
func (m OptMap[K, V]) ReplaceIfPresent(k K, v V) bool {
func (m OptMap[K, V]) ReplaceIfPresent(key K, v V) bool {
if isPresent(v) {
if ov, ok := m[k]; ok && isPresent(ov) {
m[k] = v
if ov, ok := m[key]; ok && isPresent(ov) {
m[key] = v
return true
}
} else if _, ok := m[k]; ok {
delete(m, k)
} else if _, ok := m[key]; ok {
delete(m, key)
return true
}
return false
Expand Down
Loading

0 comments on commit c297cd4

Please # to comment.