From 1a0c40b419ea804cc168f5812f08bcb146bf7614 Mon Sep 17 00:00:00 2001 From: "Dr. Carsten Leue" Date: Fri, 25 Aug 2023 22:53:09 +0200 Subject: [PATCH] fix: add helpers for reflect types Signed-off-by: Dr. Carsten Leue --- iterator/stateless/generic/reflect.go | 53 +++++++++++++++++++++++++++ iterator/stateless/reflect.go | 27 ++++++++++++++ iterator/stateless/reflect_test.go | 38 +++++++++++++++++++ reflect/generic/reflect.go | 31 ++++++++++++++++ reflect/reflect.go | 42 +++++++++++++++++++++ 5 files changed, 191 insertions(+) create mode 100644 iterator/stateless/generic/reflect.go create mode 100644 iterator/stateless/reflect.go create mode 100644 iterator/stateless/reflect_test.go create mode 100644 reflect/generic/reflect.go create mode 100644 reflect/reflect.go diff --git a/iterator/stateless/generic/reflect.go b/iterator/stateless/generic/reflect.go new file mode 100644 index 0000000..9ddc9d9 --- /dev/null +++ b/iterator/stateless/generic/reflect.go @@ -0,0 +1,53 @@ +// 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 ( + R "reflect" + + F "github.com/IBM/fp-go/function" + LG "github.com/IBM/fp-go/io/generic" + L "github.com/IBM/fp-go/lazy" + N "github.com/IBM/fp-go/number" + I "github.com/IBM/fp-go/number/integer" + O "github.com/IBM/fp-go/option" + T "github.com/IBM/fp-go/tuple" +) + +func FromReflect[GR ~func() O.Option[T.Tuple2[GR, R.Value]]](val R.Value) GR { + // recursive callback + var recurse func(idx int) GR + + // limits the index + fromPred := O.FromPredicate(I.Between(0, val.Len())) + + recurse = func(idx int) GR { + return F.Pipe3( + idx, + L.Of[int], + L.Map(fromPred), + LG.Map[L.Lazy[O.Option[int]], GR](O.Map( + F.Flow2( + T.Replicate2[int], + T.Map2(F.Flow2(N.Add(1), recurse), val.Index), + ), + )), + ) + } + + // start the recursion + return recurse(0) +} diff --git a/iterator/stateless/reflect.go b/iterator/stateless/reflect.go new file mode 100644 index 0000000..5ec1681 --- /dev/null +++ b/iterator/stateless/reflect.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 ( + R "reflect" + + G "github.com/IBM/fp-go/iterator/stateless/generic" +) + +// FromReflect creates an iterator that can iterate over types that define [R.Index] and [R.Len] +func FromReflect(val R.Value) Iterator[R.Value] { + return G.FromReflect[Iterator[R.Value]](val) +} diff --git a/iterator/stateless/reflect_test.go b/iterator/stateless/reflect_test.go new file mode 100644 index 0000000..eed6166 --- /dev/null +++ b/iterator/stateless/reflect_test.go @@ -0,0 +1,38 @@ +// 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 ( + "reflect" + "testing" + + A "github.com/IBM/fp-go/array" + F "github.com/IBM/fp-go/function" + "github.com/stretchr/testify/assert" +) + +func TestReflect(t *testing.T) { + ar := A.From("a", "b", "c") + + res := F.Pipe3( + reflect.ValueOf(ar), + FromReflect, + ToArray[reflect.Value], + A.Map(reflect.Value.String), + ) + + assert.Equal(t, ar, res) +} diff --git a/reflect/generic/reflect.go b/reflect/generic/reflect.go new file mode 100644 index 0000000..81b17ad --- /dev/null +++ b/reflect/generic/reflect.go @@ -0,0 +1,31 @@ +// 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 ( + R "reflect" +) + +func Map[GA ~[]A, A any](f func(R.Value) A) func(R.Value) GA { + return func(val R.Value) GA { + l := val.Len() + res := make(GA, l) + for i := l - 1; i >= 0; i-- { + res[i] = f(val.Index(i)) + } + return res + } +} diff --git a/reflect/reflect.go b/reflect/reflect.go new file mode 100644 index 0000000..5d021b3 --- /dev/null +++ b/reflect/reflect.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 option + +import ( + R "reflect" + + F "github.com/IBM/fp-go/function" + G "github.com/IBM/fp-go/reflect/generic" +) + +func ReduceWithIndex[A any](f func(int, A, R.Value) A, initial A) func(R.Value) A { + return func(val R.Value) A { + count := val.Len() + current := initial + for i := 0; i < count; i++ { + current = f(i, current, val.Index(i)) + } + return current + } +} + +func Reduce[A any](f func(A, R.Value) A, initial A) func(R.Value) A { + return ReduceWithIndex(F.Ignore1of3[int](f), initial) +} + +func Map[A any](f func(R.Value) A) func(R.Value) []A { + return G.Map[[]A](f) +}