Q: Use R's Reduce to sum up identically named elements for each element in a list I have this list in R
> test
[[1]]
[[1]]$right
[1] FALSE

[[1]]$left
[1] FALSE


[[2]]
[[2]]$right
[1] TRUE

[[2]]$left
[1] FALSE

which can quickly be created with this dput
list(list(right = FALSE, left = FALSE), list(right = TRUE, left = FALSE))

Now I want to sum up the right and the left elements in each element of the test-list, so that I end up with a list of two elements like this:
> res
$right
[1] 1

$left
[1] 0

I thought R's Reduce would be a good option for that (although I'm open for any advice), but I could not figure out the code. I tried the following, yet it did not work...
Reduce(function(x){
     r = sum(x[["right"]]) 
     l = sum(x[["left"]]) 
     v = list(r, v)
 }, test)

I get this error
Error in f(init, x[[i]]) : unused argument (x[[i]])

And I think I am having some misconception in my head...

A: You could unlist the lists and coerce rowSums as.list, which might be more efficient.
as.list(rowSums(sapply(test, unlist)))
# $right
# [1] 1
# 
# $left
# [1] 0


Data:
test <- list(list(right=FALSE, left=FALSE), list(right=TRUE, left=FALSE))


A: Reduce expects a function that accepts two arguments. It will get the result of the previous value of Reduce and a new element from the vector you pass to Reduce
Reduce(\(x,y) list(left = x$left + y$left, right = x$right + y$right), test)

Personally, I would use sapply (or Map if you want) to first get the left/right elements and then pass those to sum:
sapply(test, \(x) x$left) |> sum()

A version with Map and Reduce would be:
Map(\(x) x$left, test) |> Reduce(f = \(x, y) x + y)

or
Map(\(x) x$left, test) |> Reduce(f = `+`)


A: Using purrr
library(purrr)
sides <- c("left", "right")

setNames(sides, sides) |>
    map(~(map_int(test, chuck, .x))) |>
    map(reduce, `+`)

##> $left
##> [1] 0
##> 
##> $right
##> [1] 1


A: Since you need to aggregate per names, you can unlist and use tapply to sum by names:
ll <- list(list(right = FALSE, left = FALSE), list(right = TRUE, left = FALSE))
un <- unlist(ll)
tapply(un, names(un), FUN = sum)
# left right 
#    0     1 


You can transpose first:
purrr::transpose(ll) |>
  lapply(Reduce, f = sum)

# $right
# [1] 1
# 
# $left
# [1] 0


A: These are the same except that they produce a named vector, an xtabs/table object or a data.frame respectively.  In all of them we unlist the input and stack it into a two column data frame.  Then we use xtabs() |> c(), xtabs() or aggregate.
# named vector output
L |>
  unlist() |>
  stack() |>
  xtabs() |>
  c()
## right  left 
##     1     0 

# xtabs/table output
L |>
  unlist() |>
  stack() |>
  xtabs()
## ind
## right  left 
##     1     0 

# data frame output
L |>
  unlist() |>
  stack() |>
  aggregate(values ~ ind, data = _, sum)
##     ind values
## 1 right      1
## 2  left      0

Note
L <- list(list(right = FALSE, left = FALSE), list(right = TRUE, left = FALSE))


A: I would use this approach to count the rights and lefts of the list
a_list <- list(list(right = FALSE, left = FALSE),
               list(right = TRUE, left = FALSE))

library(rlist)

(result <- sapply(c(
  "right",
  "left"
), function(x) {
  rlist::list.count(
    a_list,
    eval(parse(text = x))
  )
}))

right  left 
    1     0 

