Skip to content

proposal: slices: MutableValues iterator #70813

Open
@pkierski

Description

@pkierski

Proposal Details

It's a common task to iterate over a slice and modify its elements. For the following structure:

type element struct {
	field int
}

var (
	elements = []element{
		{field: 1},
		{field: 2},
		{field: 3},
	}

	doubledElements = []element{
		{field: 2},
		{field: 4},
		{field: 6},
	}
)

we have to use one of:

func TestDoubleWithRangeAndIndex(t *testing.T) {
	// change base elements without MutableValues
	// using indexing
	for i, e := range elements {
		e.field *= 2
		elements[i] = e
	}

	if !slices.Equal(elements, doubledElements) {
		t.Fail()
	}
}

or

func TestDoubleWithRangeAndPointer(t *testing.T) {
	// change base elements without MutableValues
	// using pointer to element (useful in case of neested loops
	// or operations on more than one field)
	for i := range elements {
		e := &elements[i]
		e.field *= 2
	}

	if !slices.Equal(elements, doubledElements) {
		t.Fail()
	}
}

The proposal is to add MutableValues iterator to slices package:

func MutableValues[Slice ~[]E, E any](s Slice) iter.Seq[*E] {
	return func(yield func(*E) bool) {
		for i := range s {
			if !yield(&s[i]) {
				return
			}
		}
	}
}

Mutating of all elements of the slice can looks like:

func TestDoubleWithMutableValuesIterator(t *testing.T) {
	// values in elements will be changed
	for e := range slices.MutableValues(elements) {
		// we can directly change element via pointer
		e.field *= 2
	}

	if !slices.Equal(elements, doubledElements) {
		t.Fail()
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Incoming

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions