tidyverse / purrr

A functional programming toolkit for R
https://purrr.tidyverse.org/
Other
1.27k stars 274 forks source link

A map/zip function with implicit binding #1126

Closed twhitehead closed 3 months ago

twhitehead commented 5 months ago

Was writing this sort of code

map(x,\(x) f(...,x,...))

and got thinking it would be really nice to just be able to write it as

map(f(...,x,...))

where the fact that I used x in f(x) implies that f(x) is to be applied element wise to x.

In essence, I was imagining a more implicit function, call it zip, in keeping with standard functional naming, that would automatically vectorize the passed expression. That is, it would take all the free variables in the expression passed to it, look them up in it's environment, expand them all to equal length vectors, and map across them all.

In terms of the wider tidyverse, you could replace this sort how-many-times-do-I-have-to-type-xyz code

data |> mutate(r = pmap_vec(list(x,y,z), \(x,y,z) f(...,x,y,z,...)))

or this less verbose but more sinfully-stateful code

data |> rowwise() |> mutate(r = f(...,x,y,z,...)) |> ungroup()

with just

data |> mutate(r = zip(f(..,x,y,z,...)))

Hopefully that makes sense. Have no idea if this is even practical, but figured I would suggest it. Maybe it it would make sense for the mutate .by option to also accept 'row' too to avoid stateful grouping/ungrouping.

Feel free to just close this if you want.

hadley commented 3 months ago

I think this is a cool idea, but it just feels a bit too magical for purrr, which has generally been moving away from "magic" and towards explicitness.