lo icon indicating copy to clipboard operation
lo copied to clipboard

Add lo.MapByPtr

Open afadeevz opened this issue 1 year ago • 3 comments

When we use lo.Map elements are passed by value. That's not OK in some cases:

  • It's expensive to copy elements
  • Elements are "not copyable". For example, there is an embedded mutex.

I propose to add new function lo.MapByPtr (or some other name) with implementation pretty much similar to lo.Map:

func MapByPtr[T any, R any](collection []T, iteratee func(item *T, index int) R) []R {
	result := make([]R, len(collection))

	for i, item := range collection {
		result[i] = iteratee(&item, i)
	}

	return result
}

afadeevz avatar Feb 01 '24 20:02 afadeevz

I can create a PR if proposal will be approved

afadeevz avatar Feb 01 '24 20:02 afadeevz

But as you said, it's expensive and some elements aren't copyable - so if (especially the latter one) thats the case, why are you not using pointers in the first case? By having an slice of pointers to your struct, you avoid ever copying your elements, and you can use lo.Map without any issues.

If you really have a use case where it's necessary to use a non-pointer slice of something, than sure, that'd be a valid use case for such a MapByPtr func — it's just that I almost never use an slice of some struct, but almost always a pointer. And with that, the following works just fine.

type Account struct { Id int }
slice := []*Account{{Id: 1}, {Id: 2}, {Id: 3}}

accountIds := lo.Map(slice, func(item *Account, index int) int {
	return item.Id
})

d0x7 avatar Mar 16 '24 06:03 d0x7

I had a real use case. I needed to iterate over slice of structs which was created in generated code from protobuf. Those structs have embedded mutex. Linters went crazy with warnings. It was somewhat painful to copypaste code with small changes to my own package just to avoid those warnings.

afadeevz avatar Mar 16 '24 22:03 afadeevz