forked from golang/go
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
reflect: add iterative related methods
Fixes golang#66056 Change-Id: I1e24636e43e68cd57576c39b014e0826fb6c322c GitHub-Last-Rev: 319ad8e GitHub-Pull-Request: golang#66824 Reviewed-on: https://go-review.googlesource.com/c/go/+/578815 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
- Loading branch information
1 parent
49eedfb
commit 524a774
Showing
6 changed files
with
540 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pkg reflect, method (Value) Seq() iter.Seq[Value] #66056 | ||
pkg reflect, method (Value) Seq2() iter.Seq2[Value, Value] #66056 | ||
pkg reflect, type Type interface, CanSeq() bool #66056 | ||
pkg reflect, type Type interface, CanSeq2() bool #66056 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
The new methods [Value.Seq] and [Value.Seq2] return sequences that iterate over the value | ||
as though it were used in a for/range loop. | ||
The new methods [Type.CanSeq] and [Type.CanSeq2] report whether calling | ||
[Value.Seq] and [Value.Seq2], respectively, will succeed without panicking. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// Copyright 2024 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package reflect | ||
|
||
import "iter" | ||
|
||
// Seq returns an iter.Seq[reflect.Value] that loops over the elements of v. | ||
// If v's kind is Func, it must be a function that has no results and | ||
// that takes a single argument of type func(T) bool for some type T. | ||
// If v's kind is Pointer, the pointer element type must have kind Array. | ||
// Otherwise v's kind must be Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, | ||
// Array, Chan, Map, Slice, or String. | ||
func (v Value) Seq() iter.Seq[Value] { | ||
if canRangeFunc(v.typ()) { | ||
return func(yield func(Value) bool) { | ||
rf := MakeFunc(v.Type().In(0), func(in []Value) []Value { | ||
return []Value{ValueOf(yield(in[0]))} | ||
}) | ||
v.Call([]Value{rf}) | ||
} | ||
} | ||
switch v.Kind() { | ||
case Int, Int8, Int16, Int32, Int64: | ||
return func(yield func(Value) bool) { | ||
for i := range v.Int() { | ||
if !yield(ValueOf(i)) { | ||
return | ||
} | ||
} | ||
} | ||
case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: | ||
return func(yield func(Value) bool) { | ||
for i := range v.Uint() { | ||
if !yield(ValueOf(i)) { | ||
return | ||
} | ||
} | ||
} | ||
case Pointer: | ||
if v.Elem().kind() != Array { | ||
break | ||
} | ||
return func(yield func(Value) bool) { | ||
v = v.Elem() | ||
for i := range v.Len() { | ||
if !yield(ValueOf(i)) { | ||
return | ||
} | ||
} | ||
} | ||
case Array, Slice: | ||
return func(yield func(Value) bool) { | ||
for i := range v.Len() { | ||
if !yield(ValueOf(i)) { | ||
return | ||
} | ||
} | ||
} | ||
case String: | ||
return func(yield func(Value) bool) { | ||
for i := range v.String() { | ||
if !yield(ValueOf(i)) { | ||
return | ||
} | ||
} | ||
} | ||
case Map: | ||
return func(yield func(Value) bool) { | ||
i := v.MapRange() | ||
for i.Next() { | ||
if !yield(i.Key()) { | ||
return | ||
} | ||
} | ||
} | ||
case Chan: | ||
return func(yield func(Value) bool) { | ||
for value, ok := v.Recv(); ok; value, ok = v.Recv() { | ||
if !yield(value) { | ||
return | ||
} | ||
} | ||
} | ||
} | ||
panic("reflect: " + v.Type().String() + " cannot produce iter.Seq[Value]") | ||
} | ||
|
||
// Seq2 is like Seq but for two values. | ||
func (v Value) Seq2() iter.Seq2[Value, Value] { | ||
if canRangeFunc2(v.typ()) { | ||
return func(yield func(Value, Value) bool) { | ||
rf := MakeFunc(v.Type().In(0), func(in []Value) []Value { | ||
return []Value{ValueOf(yield(in[0], in[1]))} | ||
}) | ||
v.Call([]Value{rf}) | ||
} | ||
} | ||
switch v.Kind() { | ||
case Pointer: | ||
if v.Elem().kind() != Array { | ||
break | ||
} | ||
return func(yield func(Value, Value) bool) { | ||
v = v.Elem() | ||
for i := range v.Len() { | ||
if !yield(ValueOf(i), v.Index(i)) { | ||
return | ||
} | ||
} | ||
} | ||
case Array, Slice: | ||
return func(yield func(Value, Value) bool) { | ||
for i := range v.Len() { | ||
if !yield(ValueOf(i), v.Index(i)) { | ||
return | ||
} | ||
} | ||
} | ||
case String: | ||
return func(yield func(Value, Value) bool) { | ||
for i, v := range v.String() { | ||
if !yield(ValueOf(i), ValueOf(v)) { | ||
return | ||
} | ||
} | ||
} | ||
case Map: | ||
return func(yield func(Value, Value) bool) { | ||
i := v.MapRange() | ||
for i.Next() { | ||
if !yield(i.Key(), i.Value()) { | ||
return | ||
} | ||
} | ||
} | ||
} | ||
panic("reflect: " + v.Type().String() + " cannot produce iter.Seq2[Value, Value]") | ||
} |
Oops, something went wrong.