lo
lo copied to clipboard
Add lo.MapByPtr
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
}
I can create a PR if proposal will be approved
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
})
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.