diff --git a/iterator/stateless/generic/scan.go b/iterator/stateless/generic/scan.go new file mode 100644 index 0000000..a930a72 --- /dev/null +++ b/iterator/stateless/generic/scan.go @@ -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 ( + F "github.com/IBM/fp-go/function" + O "github.com/IBM/fp-go/option" + T "github.com/IBM/fp-go/tuple" +) + +func Scan[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(V, U) V, U, V any](f FCT, initial V) func(ma GU) GV { + // pre-declare to avoid cyclic reference + var recurse func(ma GU, v V) GV + + recurse = func(ma GU, current V) GV { + return F.Nullary2( + ma, + O.Map(func(t T.Tuple2[GU, U]) T.Tuple2[GV, V] { + v := f(current, t.F2) + return T.MakeTuple2(recurse(t.F1, v), v) + }), + ) + } + + return F.Bind2nd(recurse, initial) +} diff --git a/iterator/stateless/generic/take.go b/iterator/stateless/generic/take.go new file mode 100644 index 0000000..5e0a1f8 --- /dev/null +++ b/iterator/stateless/generic/take.go @@ -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" + N "github.com/IBM/fp-go/number/integer" + O "github.com/IBM/fp-go/option" + T "github.com/IBM/fp-go/tuple" +) + +func Take[GU ~func() O.Option[T.Tuple2[GU, U]], U any](n int) func(ma GU) GU { + // pre-declare to avoid cyclic reference + var recurse func(ma GU, idx int) GU + + fromPred := O.FromPredicate(N.Between(0, n)) + + recurse = func(ma GU, idx int) GU { + return func() O.Option[T.Tuple2[GU, U]] { + return F.Pipe2( + idx, + fromPred, + O.Chain(F.Ignore1of1[int](F.Nullary2( + ma, + O.Map(func(t T.Tuple2[GU, U]) T.Tuple2[GU, U] { + return T.MakeTuple2(recurse(t.F1, idx+1), t.F2) + }), + ))), + ) + } + } + + return F.Bind2nd(recurse, 0) +} diff --git a/iterator/stateless/scan.go b/iterator/stateless/scan.go new file mode 100644 index 0000000..7b3fc2e --- /dev/null +++ b/iterator/stateless/scan.go @@ -0,0 +1,27 @@ +// 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 stateless + +import ( + G "github.com/IBM/fp-go/iterator/stateless/generic" +) + +// Scan takes an [Iterator] and returns a new [Iterator] of the same length, where the values +// of the new [Iterator] are the result of the application of `f` to the value of the +// source iterator with the previously accumulated value +func Scan[FCT ~func(V, U) V, U, V any](f FCT, initial V) func(ma Iterator[U]) Iterator[V] { + return G.Scan[Iterator[V], Iterator[U], FCT](f, initial) +} diff --git a/iterator/stateless/scan_test.go b/iterator/stateless/scan_test.go new file mode 100644 index 0000000..e39b617 --- /dev/null +++ b/iterator/stateless/scan_test.go @@ -0,0 +1,42 @@ +// 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 stateless + +import ( + "testing" + + F "github.com/IBM/fp-go/function" + T "github.com/IBM/fp-go/tuple" + "github.com/stretchr/testify/assert" +) + +func TestScan(t *testing.T) { + + src := From("a", "b", "c") + + dst := F.Pipe1( + src, + Scan(func(cur T.Tuple2[int, string], val string) T.Tuple2[int, string] { + return T.MakeTuple2(cur.F1+1, val) + }, T.MakeTuple2(0, "")), + ) + + assert.Equal(t, ToArray(From( + T.MakeTuple2(1, "a"), + T.MakeTuple2(2, "b"), + T.MakeTuple2(3, "c"), + )), ToArray(dst)) +} diff --git a/iterator/stateless/take.go b/iterator/stateless/take.go new file mode 100644 index 0000000..5e6be2b --- /dev/null +++ b/iterator/stateless/take.go @@ -0,0 +1,25 @@ +// 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 stateless + +import ( + G "github.com/IBM/fp-go/iterator/stateless/generic" +) + +// Take limits the number of values in the [Iterator] to a maximum number +func Take[U any](n int) func(ma Iterator[U]) Iterator[U] { + return G.Take[Iterator[U]](n) +} diff --git a/iterator/stateless/take_test.go b/iterator/stateless/take_test.go new file mode 100644 index 0000000..70dbf2b --- /dev/null +++ b/iterator/stateless/take_test.go @@ -0,0 +1,36 @@ +// 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 stateless + +import ( + "testing" + + F "github.com/IBM/fp-go/function" + "github.com/stretchr/testify/assert" +) + +func TestTake(t *testing.T) { + + total := MakeBy(100, F.Identity[int]) + + trimmed := F.Pipe1( + total, + Take[int](10), + ) + + assert.Equal(t, ToArray(MakeBy(10, F.Identity[int])), ToArray(trimmed)) + +}