The commonality between [N]T, []T and [dynamic]T is that they are all sliceable. So I believe you could squash it to just 4 procs.
Something like this:
package slicefmt
import "core:fmt"
import "base:intrinsics"
dimslice_1D :: proc(s: []$T, begin := "[", end := "]")
where !intrinsics.type_is_sliceable(T) // edit: missed this
{
fmt.print(begin)
for t, i in s {
fmt.printf("%v", t)
if i != len(s) - 1 do fmt.printf(", ")
}
fmt.println(end)
}
dimslice_2D :: proc(s: []$T)
where intrinsics.type_is_sliceable(T)
{
for &row in s {
dimslice_1D(row[:], begin = "|", end = "|")
}
}
dimslice :: proc(s: $S/[]$T) {
when intrinsics.type_is_sliceable(T) {
dimslice_2D(s)
} else {
dimslice_1D(s)
}
}
sliceable :: proc(s: $S)
where intrinsics.type_is_sliceable(S)
{
s := s
sx := s[:]
dimslice(sx)
}
main :: proc() {
xs : [][]int = {{1,2,3}, {4,5,6}, {7,8,9}}
ys : [3][3]int = {{1,2,3}, {4,5,6}, {7,8,9}}
zs : [dynamic][dynamic]int = make([dynamic][dynamic]int)
for i in 0..<3 {
z := make([dynamic]int)
append(&z, i+1, i+2, i+3)
append(&zs, z)
}
qs : [][2]int = {{1,2}, {3,4}, {5,6}}
fmt.println("XS:")
sliceable(xs)
fmt.println("YS:")
sliceable(ys)
fmt.println("ZS:")
sliceable(zs)
fmt.println("QS:")
sliceable(qs)
// edit: prove it won't go above 2D, uncomment results in err
// ws : [][2][dynamic]int = {{make([dynamic]int), make([dynamic]int)}}
// sliceable(ws)
}
Will produce this:
XS:
|1, 2, 3|
|4, 5, 6|
|7, 8, 9|
YS:
|1, 2, 3|
|4, 5, 6|
|7, 8, 9|
ZS:
|1, 2, 3|
|2, 3, 4|
|3, 4, 5|
QS:
|1, 2|
|3, 4|
|5, 6|