
# Simple example ====
x <- array(1:20, c(5, 4))
y <- array(-1:-15, c(5, 3))
z <- array(21:40, c(5, 4))
input <- list(x, y, z)
# column binding:
bind_array(input, 2L)


################################################################################


# Broadcasting example ====
x <- array(1:20, c(5, 4))
y <- array(-1:-5, c(1, 5)) # rows will be broadcasted from 1 to 5
z <- array(21:40, c(5, 4))
input <- list(x, y, z)
bind_array(input, 2L)


################################################################################


# Mixing types ====
# here, atomic and recursive arrays are mixed,
# resulting in recursive arrays

# creating the arrays:
x <- c(
  lapply(1:3, \(x)sample(c(TRUE, FALSE, NA))),
  lapply(1:3, \(x)sample(1:10)),
  lapply(1:3, \(x)rnorm(10)),
  lapply(1:3, \(x)sample(letters))
) |> matrix(4, 3, byrow = TRUE)
dimnames(x) <- list(letters[1:4], LETTERS[1:3])
print(x)

y <- matrix(1:12, 4, 3)
print(y)
z <- matrix(letters[1:12], c(4, 3))

# column-binding:
input <- list(x = x, y = y, z = z)
bind_array(input, along = 2L)


################################################################################


# Illustrating `along` argument ====
# using recursive arrays for clearer visual distinction
input <- list(x = x, y = y)

bind_array(input, along = 0L) # binds on new dimension before first
bind_array(input, along = 1L) # binds on first dimension (i.e. rows)
bind_array(input, along = 2L)
bind_array(input, along = 3L) # bind on new dimension after last

bind_array(input, along = 0L, TRUE) # binds on new dimension after last
bind_array(input, along = 1L, TRUE) # binds on last dimension (i.e. columns)
bind_array(input, along = 2L, TRUE)
bind_array(input, along = 3L, TRUE) # bind on new dimension before first


################################################################################


# binding, with empty arrays ====
emptyarray <- array(numeric(0L), c(0L, 3L))
dimnames(emptyarray) <- list(NULL, paste("empty", 1:3))
print(emptyarray)
input <- list(x = x, y = emptyarray)
bind_array(input, along = 1L, comnames_from = 2L) # row-bind


################################################################################


# Illustrating `name_along` ====
x <- array(1:15, c(5, 3), list(NULL, LETTERS[1:3]))
y <- array(-1:-15, c(5, 3))
z <- array(-1:-15, c(5, 3))

bind_array(list(a = x, b = y, z), 2L)
bind_array(list(x, y, z), 2L)
bind_array(list(a = unname(x), b = y, c = z), 2L)
bind_array(list(x, a = y, b = z), 2L)
input <- list(x, y, z)
names(input) <- c("", NA, "")
bind_array(input, 2L)


################################################################################


# binding vectors and arrays ====
x <- setNames(1:4, letters[1:4]) |> vector2array(direction = 2L, ndim = 2L)
y <- array(1:20, c(5, 4), list(NULL, LETTERS[1:4]))
input <- list(x, y)
bind_array(input, 1L, comnames_from = 1L) # row-bind, with names from vector `x`


################################################################################


# start with empty vector, and bind arrays from there (handy in loops) ====
y <- array(-1:-15, c(5, 3))
z <- array(-1:-15, c(5, 3))
input <- list(y, z)
init <- vector2array(raw(0L), 1L, 2L)
for(i in input) {
  init <- bind_array(list(init, i), 2L)
}
print(init)



################################################################################


# type of the result is independent of the types of empty arrays ====
# make regular arrays of type `integer`:
y <- array(-1:-15, c(5, 3))
z <- array(-1:-15, c(5, 3))

# make empty array of type `list`:
emptyarray <- array(vector("list", 0L), c(0L, 3L))
dimnames(emptyarray) <- list(NULL, paste("empty", 1:3))
print(emptyarray)
typeof(emptyarray) # type of list, the highest type
length(emptyarray) # but also empty, so it's type does NOT affect result type!

# bind results:
input <- list(y = y, z = z, e = emptyarray)
out <- bind_array(input, along = 1L, comnames_from = 2L) # row-bind
typeof(out) # `integer`, NOT `list`, because empty arrays don't count


