mirror of
https://github.com/IBM/fp-go.git
synced 2025-09-01 19:56:12 +02:00
Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1d02f21ff5 | ||
|
e82575fe08 | ||
|
5fcd0b1595 | ||
|
5caabf478c |
@@ -308,10 +308,16 @@ func SliceRight[A any](start int) func([]A) []A {
|
||||
return G.SliceRight[[]A](start)
|
||||
}
|
||||
|
||||
// Copy creates a shallow copy of the array
|
||||
func Copy[A any](b []A) []A {
|
||||
return G.Copy(b)
|
||||
}
|
||||
|
||||
// Clone creates a deep copy of the array using the provided endomorphism to clone the values
|
||||
func Clone[A any](f func(A) A) func(as []A) []A {
|
||||
return G.Clone[[]A](f)
|
||||
}
|
||||
|
||||
// FoldMap maps and folds an array. Map the Array passing each value to the iterating function. Then fold the results using the provided Monoid.
|
||||
func FoldMap[A, B any](m M.Monoid[B]) func(func(A) B) func([]A) B {
|
||||
return G.FoldMap[[]A](m)
|
||||
|
@@ -304,6 +304,11 @@ func Copy[AS ~[]A, A any](b AS) AS {
|
||||
return buf
|
||||
}
|
||||
|
||||
func Clone[AS ~[]A, A any](f func(A) A) func(as AS) AS {
|
||||
// implementation assumes that map does not optimize for the empty array
|
||||
return Map[AS, AS](f)
|
||||
}
|
||||
|
||||
func FoldMap[AS ~[]A, A, B any](m M.Monoid[B]) func(func(A) B) func(AS) B {
|
||||
return func(f func(A) B) func(AS) B {
|
||||
return func(as AS) B {
|
||||
|
47
endomorphism/generic/monoid.go
Normal file
47
endomorphism/generic/monoid.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package generic
|
||||
|
||||
import (
|
||||
F "github.com/IBM/fp-go/function"
|
||||
M "github.com/IBM/fp-go/monoid"
|
||||
S "github.com/IBM/fp-go/semigroup"
|
||||
)
|
||||
|
||||
// Of converts any function to an [Endomorphism]
|
||||
func Of[ENDO ~func(A) A, F ~func(A) A, A any](f F) ENDO {
|
||||
return func(a A) A {
|
||||
return f(a)
|
||||
}
|
||||
}
|
||||
|
||||
func Identity[ENDO ~func(A) A, A any]() ENDO {
|
||||
return Of[ENDO](F.Identity[A])
|
||||
}
|
||||
|
||||
func Compose[ENDO ~func(A) A, A any](f1, f2 ENDO) ENDO {
|
||||
return Of[ENDO](F.Flow2(f1, f2))
|
||||
}
|
||||
|
||||
// Semigroup for the Endomorphism where the `concat` operation is the usual function composition.
|
||||
func Semigroup[ENDO ~func(A) A, A any]() S.Semigroup[ENDO] {
|
||||
return S.MakeSemigroup(Compose[ENDO])
|
||||
}
|
||||
|
||||
// Monoid for the Endomorphism where the `concat` operation is the usual function composition.
|
||||
func Monoid[ENDO ~func(A) A, A any]() M.Monoid[ENDO] {
|
||||
return M.MakeMonoid(Compose[ENDO], Identity[ENDO]())
|
||||
}
|
@@ -16,17 +16,30 @@
|
||||
package endomorphism
|
||||
|
||||
import (
|
||||
F "github.com/IBM/fp-go/function"
|
||||
G "github.com/IBM/fp-go/endomorphism/generic"
|
||||
M "github.com/IBM/fp-go/monoid"
|
||||
S "github.com/IBM/fp-go/semigroup"
|
||||
)
|
||||
|
||||
// Endomorphism is a function that
|
||||
type Endomorphism[A any] func(A) A
|
||||
|
||||
// Of converts any function to an [Endomorphism]
|
||||
func Of[F ~func(A) A, A any](f F) Endomorphism[A] {
|
||||
return G.Of[Endomorphism[A]](f)
|
||||
}
|
||||
|
||||
// Identity returns the identity [Endomorphism]
|
||||
func Identity[A any]() Endomorphism[A] {
|
||||
return G.Identity[Endomorphism[A]]()
|
||||
}
|
||||
|
||||
// Semigroup for the Endomorphism where the `concat` operation is the usual function composition.
|
||||
func Semigroup[A any]() S.Semigroup[func(A) A] {
|
||||
return S.MakeSemigroup(F.Flow2[func(A) A, func(A) A])
|
||||
func Semigroup[A any]() S.Semigroup[Endomorphism[A]] {
|
||||
return G.Semigroup[Endomorphism[A]]()
|
||||
}
|
||||
|
||||
// Monoid for the Endomorphism where the `concat` operation is the usual function composition.
|
||||
func Monoid[A any]() M.Monoid[func(A) A] {
|
||||
return M.MakeMonoid(F.Flow2[func(A) A, func(A) A], F.Identity[A])
|
||||
func Monoid[A any]() M.Monoid[Endomorphism[A]] {
|
||||
return G.Monoid[Endomorphism[A]]()
|
||||
}
|
||||
|
71
http/form/form.go
Normal file
71
http/form/form.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package form
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
A "github.com/IBM/fp-go/array"
|
||||
ENDO "github.com/IBM/fp-go/endomorphism"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
L "github.com/IBM/fp-go/optics/lens"
|
||||
LA "github.com/IBM/fp-go/optics/lens/array"
|
||||
LRG "github.com/IBM/fp-go/optics/lens/record/generic"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
type (
|
||||
// Endomorphism returns an [ENDO.Endomorphism] that transforms a form
|
||||
Endomorphism = ENDO.Endomorphism[url.Values]
|
||||
)
|
||||
|
||||
var (
|
||||
// Default is the default form field
|
||||
Default = make(url.Values)
|
||||
|
||||
noField = O.None[string]()
|
||||
|
||||
// FormMonoid is the [M.Monoid] for the [Endomorphism]
|
||||
Monoid = ENDO.Monoid[url.Values]()
|
||||
|
||||
// AtValues is a [L.Lens] that focusses on the values of a form field
|
||||
AtValues = LRG.AtRecord[url.Values, []string]
|
||||
|
||||
composeHead = F.Pipe1(
|
||||
LA.AtHead[string](),
|
||||
L.ComposeOptions[url.Values, string](A.Empty[string]()),
|
||||
)
|
||||
|
||||
// AtValue is a [L.Lens] that focusses on first value in form fields
|
||||
AtValue = F.Flow2(
|
||||
AtValues,
|
||||
composeHead,
|
||||
)
|
||||
)
|
||||
|
||||
// WithValue creates a [FormBuilder] for a certain field
|
||||
func WithValue(name string) func(value string) Endomorphism {
|
||||
return F.Flow3(
|
||||
O.Of[string],
|
||||
AtValue(name).Set,
|
||||
ENDO.Of[func(url.Values) url.Values],
|
||||
)
|
||||
}
|
||||
|
||||
// WithoutValue creates a [FormBuilder] that removes a field
|
||||
func WithoutValue(name string) Endomorphism {
|
||||
return AtValue(name).Set(noField)
|
||||
}
|
93
http/form/form_test.go
Normal file
93
http/form/form_test.go
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package form
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
A "github.com/IBM/fp-go/array"
|
||||
"github.com/IBM/fp-go/eq"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
LT "github.com/IBM/fp-go/optics/lens/testing"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
RG "github.com/IBM/fp-go/record/generic"
|
||||
S "github.com/IBM/fp-go/string"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
sEq = eq.FromEquals(S.Eq)
|
||||
valuesEq = RG.Eq[url.Values](A.Eq(sEq))
|
||||
)
|
||||
|
||||
func TestLaws(t *testing.T) {
|
||||
name := "Content-Type"
|
||||
fieldLaws := LT.AssertLaws[url.Values, O.Option[string]](t, O.Eq(sEq), valuesEq)(AtValue(name))
|
||||
|
||||
n := O.None[string]()
|
||||
s1 := O.Some("s1")
|
||||
|
||||
v1 := F.Pipe1(
|
||||
Default,
|
||||
WithValue(name)("v1"),
|
||||
)
|
||||
|
||||
v2 := F.Pipe1(
|
||||
Default,
|
||||
WithValue("Other-Header")("v2"),
|
||||
)
|
||||
|
||||
assert.True(t, fieldLaws(Default, n))
|
||||
assert.True(t, fieldLaws(v1, n))
|
||||
assert.True(t, fieldLaws(v2, n))
|
||||
|
||||
assert.True(t, fieldLaws(Default, s1))
|
||||
assert.True(t, fieldLaws(v1, s1))
|
||||
assert.True(t, fieldLaws(v2, s1))
|
||||
}
|
||||
|
||||
func TestFormField(t *testing.T) {
|
||||
|
||||
v1 := F.Pipe1(
|
||||
Default,
|
||||
WithValue("h1")("v1"),
|
||||
)
|
||||
|
||||
v2 := F.Pipe1(
|
||||
v1,
|
||||
WithValue("h2")("v2"),
|
||||
)
|
||||
|
||||
// make sure the code does not change structures
|
||||
assert.False(t, valuesEq.Equals(Default, v1))
|
||||
assert.False(t, valuesEq.Equals(Default, v2))
|
||||
assert.False(t, valuesEq.Equals(v1, v2))
|
||||
|
||||
// check for existence of values
|
||||
assert.Equal(t, "v1", v1.Get("h1"))
|
||||
assert.Equal(t, "v1", v2.Get("h1"))
|
||||
assert.Equal(t, "v2", v2.Get("h2"))
|
||||
|
||||
// check getter on lens
|
||||
|
||||
l1 := AtValue("h1")
|
||||
l2 := AtValue("h2")
|
||||
|
||||
assert.Equal(t, O.Of("v1"), l1.Get(v1))
|
||||
assert.Equal(t, O.Of("v1"), l1.Get(v2))
|
||||
assert.Equal(t, O.Of("v2"), l2.Get(v2))
|
||||
}
|
@@ -21,6 +21,7 @@ import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
ENDO "github.com/IBM/fp-go/endomorphism"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
IOE "github.com/IBM/fp-go/ioeither"
|
||||
IOEH "github.com/IBM/fp-go/ioeither/http"
|
||||
@@ -39,8 +40,8 @@ type (
|
||||
body O.Option[IOE.IOEither[error, []byte]]
|
||||
}
|
||||
|
||||
// BuilderBuilder returns a function that transforms a builder
|
||||
BuilderBuilder = func(*Builder) *Builder
|
||||
// Endomorphism returns an [ENDO.Endomorphism] that transforms a builder
|
||||
Endomorphism = ENDO.Endomorphism[*Builder]
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -49,6 +50,9 @@ var (
|
||||
|
||||
defaultMethod = F.Constant(http.MethodGet)
|
||||
|
||||
// Monoid is the [M.Monoid] for the [Endomorphism]
|
||||
Monoid = ENDO.Monoid[*Builder]()
|
||||
|
||||
// Url is a [L.Lens] for the URL
|
||||
Url = L.MakeLensRef((*Builder).GetUrl, (*Builder).SetUrl)
|
||||
// Method is a [L.Lens] for the HTTP method
|
||||
@@ -66,15 +70,25 @@ var (
|
||||
noBody = O.None[IOE.IOEither[error, []byte]]()
|
||||
|
||||
// WithMethod creates a [BuilderBuilder] for a certain method
|
||||
WithMethod = Method.Set
|
||||
WithMethod = F.Flow2(
|
||||
Method.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
// WithUrl creates a [BuilderBuilder] for a certain method
|
||||
WithUrl = Url.Set
|
||||
WithUrl = F.Flow2(
|
||||
Url.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
// WithHeaders creates a [BuilderBuilder] for a set of headers
|
||||
WithHeaders = Headers.Set
|
||||
WithHeaders = F.Flow2(
|
||||
Headers.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
// WithBody creates a [BuilderBuilder] for a request body
|
||||
WithBody = F.Flow2(
|
||||
WithBody = F.Flow3(
|
||||
O.Of[IOE.IOEither[error, []byte]],
|
||||
Body.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
// WithContentType adds the content type header
|
||||
WithContentType = WithHeader("Content-Type")
|
||||
@@ -92,7 +106,11 @@ var (
|
||||
Requester = (*Builder).Requester
|
||||
|
||||
// WithoutBody creates a [BuilderBuilder] to remove the body
|
||||
WithoutBody = Body.Set(noBody)
|
||||
WithoutBody = F.Pipe2(
|
||||
noBody,
|
||||
Body.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
)
|
||||
|
||||
func (builder *Builder) clone() *Builder {
|
||||
@@ -208,20 +226,21 @@ func Header(name string) L.Lens[*Builder, O.Option[string]] {
|
||||
}
|
||||
|
||||
// WithHeader creates a [BuilderBuilder] for a certain header
|
||||
func WithHeader(name string) func(value string) BuilderBuilder {
|
||||
return F.Flow2(
|
||||
func WithHeader(name string) func(value string) Endomorphism {
|
||||
return F.Flow3(
|
||||
O.Of[string],
|
||||
Header(name).Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
}
|
||||
|
||||
// WithoutHeader creates a [BuilderBuilder] to remove a certain header
|
||||
func WithoutHeader(name string) BuilderBuilder {
|
||||
func WithoutHeader(name string) Endomorphism {
|
||||
return Header(name).Set(noHeader)
|
||||
}
|
||||
|
||||
// WithFormData creates a [BuilderBuilder] to send form data payload
|
||||
func WithFormData(value url.Values) BuilderBuilder {
|
||||
func WithFormData(value url.Values) Endomorphism {
|
||||
return F.Flow2(
|
||||
F.Pipe4(
|
||||
value,
|
||||
@@ -235,7 +254,7 @@ func WithFormData(value url.Values) BuilderBuilder {
|
||||
}
|
||||
|
||||
// WithJson creates a [BuilderBuilder] to send JSON payload
|
||||
func WithJson[T any](data T) BuilderBuilder {
|
||||
func WithJson[T any](data T) Endomorphism {
|
||||
return F.Flow2(
|
||||
F.Pipe3(
|
||||
data,
|
||||
|
39
optics/lens/array/generic/head.go
Normal file
39
optics/lens/array/generic/head.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package generic
|
||||
|
||||
import (
|
||||
AA "github.com/IBM/fp-go/array/generic"
|
||||
L "github.com/IBM/fp-go/optics/lens"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
// AtHead focusses on the head of an array. The setter works as follows
|
||||
// - if the new value is none, the result will be an empty array
|
||||
// - if the new value is some and the array is empty, it creates a new array with one element
|
||||
// - if the new value is some and the array is not empty, it replaces the head
|
||||
func AtHead[AS []A, A any]() L.Lens[AS, O.Option[A]] {
|
||||
return L.MakeLens(AA.Head[AS, A], func(as AS, a O.Option[A]) AS {
|
||||
return O.MonadFold(a, AA.Empty[AS], func(v A) AS {
|
||||
if AA.IsEmpty(as) {
|
||||
return AA.Of[AS, A](v)
|
||||
}
|
||||
cpy := AA.Copy(as)
|
||||
cpy[0] = v
|
||||
return cpy
|
||||
})
|
||||
})
|
||||
}
|
30
optics/lens/array/head.go
Normal file
30
optics/lens/array/head.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package array
|
||||
|
||||
import (
|
||||
L "github.com/IBM/fp-go/optics/lens"
|
||||
G "github.com/IBM/fp-go/optics/lens/array/generic"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
// AtHead focusses on the head of an array. The setter works as follows
|
||||
// - if the new value is none, the result will be an empty array
|
||||
// - if the new value is some and the array is empty, it creates a new array with one element
|
||||
// - if the new value is some and the array is not empty, it replaces the head
|
||||
func AtHead[A any]() L.Lens[[]A, O.Option[A]] {
|
||||
return G.AtHead[[]A]()
|
||||
}
|
40
optics/lens/array/head_test.go
Normal file
40
optics/lens/array/head_test.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package array
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
A "github.com/IBM/fp-go/array"
|
||||
"github.com/IBM/fp-go/eq"
|
||||
LT "github.com/IBM/fp-go/optics/lens/testing"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
S "github.com/IBM/fp-go/string"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
sEq = eq.FromEquals(S.Eq)
|
||||
)
|
||||
|
||||
func TestLaws(t *testing.T) {
|
||||
headLaws := LT.AssertLaws(t, O.Eq(sEq), A.Eq(sEq))(AtHead[string]())
|
||||
|
||||
assert.True(t, headLaws(A.Empty[string](), O.None[string]()))
|
||||
assert.True(t, headLaws(A.Empty[string](), O.Of("a")))
|
||||
assert.True(t, headLaws(A.From("a", "b"), O.None[string]()))
|
||||
assert.True(t, headLaws(A.From("a", "b"), O.Of("c")))
|
||||
}
|
@@ -531,3 +531,12 @@ func MonadFlap[GFAB ~map[K]func(A) B, GB ~map[K]B, K comparable, A, B any](fab G
|
||||
func Flap[GFAB ~map[K]func(A) B, GB ~map[K]B, K comparable, A, B any](a A) func(GFAB) GB {
|
||||
return FC.Flap(MonadMap[GFAB, GB], a)
|
||||
}
|
||||
|
||||
func Copy[M ~map[K]V, K comparable, V any](m M) M {
|
||||
return duplicate(m)
|
||||
}
|
||||
|
||||
func Clone[M ~map[K]V, K comparable, V any](f func(V) V) func(m M) M {
|
||||
// impementation assumes that map does not optimize for the empty map
|
||||
return Map[M, M](f)
|
||||
}
|
||||
|
@@ -284,3 +284,13 @@ func MonadFlap[B any, K comparable, A any](fab map[K]func(A) B, a A) map[K]B {
|
||||
func Flap[B any, K comparable, A any](a A) func(map[K]func(A) B) map[K]B {
|
||||
return G.Flap[map[K]func(A) B, map[K]B](a)
|
||||
}
|
||||
|
||||
// Copy creates a shallow copy of the map
|
||||
func Copy[K comparable, V any](m map[K]V) map[K]V {
|
||||
return G.Copy[map[K]V](m)
|
||||
}
|
||||
|
||||
// Clone creates a deep copy of the map using the provided endomorphism to clone the values
|
||||
func Clone[K comparable, V any](f func(V) V) func(m map[K]V) map[K]V {
|
||||
return G.Clone[map[K]V](f)
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
A "github.com/IBM/fp-go/array"
|
||||
"github.com/IBM/fp-go/internal/utils"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
S "github.com/IBM/fp-go/string"
|
||||
@@ -131,3 +132,20 @@ func ExampleValuesOrd() {
|
||||
// Output: [c b a]
|
||||
|
||||
}
|
||||
|
||||
func TestCopyVsClone(t *testing.T) {
|
||||
slc := []string{"b", "c"}
|
||||
src := map[string][]string{
|
||||
"a": slc,
|
||||
}
|
||||
// make a shallow copy
|
||||
cpy := Copy(src)
|
||||
// make a deep copy
|
||||
cln := Clone[string](A.Copy[string])(src)
|
||||
|
||||
assert.Equal(t, cpy, cln)
|
||||
// make a modification to the original slice
|
||||
slc[0] = "d"
|
||||
assert.NotEqual(t, cpy, cln)
|
||||
assert.Equal(t, src, cpy)
|
||||
}
|
||||
|
Reference in New Issue
Block a user