library(tidyverse)
set.seed(20250104)
A <- data.frame(id = 1:3, x = rnorm(3))
B <- data.frame(id = c(2, 3), y = rnorm(2))
C <- data.frame(id = c(1, 3), z = rnorm(2))
A
B
C

Alexander Krannich’s example:

list(A, B, C) |>
  reduce(full_join, by = "id")

Using only {base} (mild edit of David Souza’s reply):

list(A, B, C) |>
  Reduce(\(x, y) merge(x, y, by = "id", all = TRUE), x = _)

Getting silly – this all reminded me of Haskell’s foldr1, implemented (without the Currying) as:

foldr1 <- \(f, xs) {
  if (length(xs) == 1)
    xs[[1]]
  else
    f(xs[[1]], foldr1(f, tail(xs, length(xs) - 1)))
}

foldr1(\(x, y) merge(x, y, by = "id", all = TRUE), list(A, B, C))

Here is an easier example:

foldr1(`+`, 1:10)
[1] 55

Which is the same as:

sum(1:10)
[1] 55
LS0tDQp0aXRsZTogIlBsYXlpbmcgYXJvdW5kIHdpdGggcmVkdWNlLCBSZWR1Y2UsIGFuZCBmb2xkcjEiDQphdXRob3I6IEFuZGkgRnVnYXJkDQpkYXRlOiA1IEphbiAyMDI1DQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOiANCiAgICBjb2RlX2ZvbGRpbmc6IG5vbmUNCi0tLQ0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpgYGANCg0KDQpgYGB7cn0NCnNldC5zZWVkKDIwMjUwMTA0KQ0KQSA8LSBkYXRhLmZyYW1lKGlkID0gMTozLCB4ID0gcm5vcm0oMykpDQpCIDwtIGRhdGEuZnJhbWUoaWQgPSBjKDIsIDMpLCB5ID0gcm5vcm0oMikpDQpDIDwtIGRhdGEuZnJhbWUoaWQgPSBjKDEsIDMpLCB6ID0gcm5vcm0oMikpDQpgYGANCg0KYGBge3J9DQpBDQpCDQpDDQpgYGANCg0KQWxleGFuZGVyIEtyYW5uaWNoJ3MgW2V4YW1wbGVdKGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9wb3N0cy9hbGV4YW5kZXIta3Jhbm5pY2hfcnN0YXRzLXN0YXRpc3RpY3MtcnN0dWRpby1hY3Rpdml0eS03MjgxNjcwODA1ODc5NDU5ODQwLXpWWk8pOg0KDQpgYGB7cn0NCmxpc3QoQSwgQiwgQykgfD4NCiAgcmVkdWNlKGZ1bGxfam9pbiwgYnkgPSAiaWQiKQ0KYGBgDQoNClVzaW5nIG9ubHkge2Jhc2V9IChtaWxkIGVkaXQgb2YgRGF2aWQgU291emEncyBbcmVwbHldKGh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS9mZWVkL3VwZGF0ZS91cm46bGk6YWN0aXZpdHk6NzI4MTY3MDgwNTg3OTQ1OTg0MD9jb21tZW50VXJuPXVybiUzQWxpJTNBY29tbWVudCUzQSUyOGFjdGl2aXR5JTNBNzI4MTY3MDgwNTg3OTQ1OTg0MCUyQzcyODE4MTQ2NTkwNzI5NzA3NTMlMjkmZGFzaENvbW1lbnRVcm49dXJuJTNBbGklM0Fmc2RfY29tbWVudCUzQSUyODcyODE4MTQ2NTkwNzI5NzA3NTMlMkN1cm4lM0FsaSUzQWFjdGl2aXR5JTNBNzI4MTY3MDgwNTg3OTQ1OTg0MCUyOSkpOg0KDQpgYGB7cn0NCmxpc3QoQSwgQiwgQykgfD4NCiAgUmVkdWNlKFwoeCwgeSkgbWVyZ2UoeCwgeSwgYnkgPSAiaWQiLCBhbGwgPSBUUlVFKSwgeCA9IF8pDQpgYGANCg0KR2V0dGluZyBzaWxseSAtLSB0aGlzIGFsbCByZW1pbmRlZCBtZSBvZiBIYXNrZWxsJ3MgW2ZvbGRyMV0oaHR0cHM6Ly9oYWNrYWdlLmhhc2tlbGwub3JnL3BhY2thZ2UvYmFzZS00LjIxLjAuMC9kb2NzL1ByZWx1ZGUuaHRtbCN2OmZvbGRyMSksIGltcGxlbWVudGVkICh3aXRob3V0IHRoZSBDdXJyeWluZykgYXM6DQoNCmBgYHtyfQ0KZm9sZHIxIDwtIFwoZiwgeHMpIHsNCiAgaWYgKGxlbmd0aCh4cykgPT0gMSkNCiAgICB4c1tbMV1dDQogIGVsc2UNCiAgICBmKHhzW1sxXV0sIGZvbGRyMShmLCB0YWlsKHhzLCBsZW5ndGgoeHMpIC0gMSkpKQ0KfQ0KDQpmb2xkcjEoXCh4LCB5KSBtZXJnZSh4LCB5LCBieSA9ICJpZCIsIGFsbCA9IFRSVUUpLCBsaXN0KEEsIEIsIEMpKQ0KYGBgDQoNCkhlcmUgaXMgYW4gZWFzaWVyIGV4YW1wbGU6DQoNCmBgYHtyfQ0KZm9sZHIxKGArYCwgMToxMCkNCmBgYA0KDQpXaGljaCBpcyB0aGUgc2FtZSBhczoNCg0KYGBge3J9DQpzdW0oMToxMCkNCmBgYA0KDQoNCg==