$ v1=$(seq 1 3); v2=$(seq 2 4)
$ comm /dev/fd/3 3<<<"$v1" /dev/fd/4 4<<<"$v2"
1
2
3
4
In the above 3<<<"$v1" and 4<<<"$v2" is making file descriptors 3 and 4 point to the temp files generated by the <<<s and then running comm on those file descriptors. Using awk you can see that happens:
$ awk 'BEGIN{for (i in ARGV) print i, ARGV[i]} {print FILENAME, $0}' /dev/fd/3 3<<<"$v1" /dev/fd/4 4<<<"$v2"
0 awk
1 /dev/fd/3
2 /dev/fd/4
/dev/fd/3 1
/dev/fd/3 2
/dev/fd/3 3
/dev/fd/4 2
/dev/fd/4 3
/dev/fd/4 4
You can change the command line order of FD assignment vs usage if you find some other arrangement more readable and you can keep going, e.g.:
$ v3=$(seq 4 6); v4=$(seq 6 8)
$ paste /dev/fd/3 3<<<"$v1" /dev/fd/4 4<<<"$v2" /dev/fd/5 5<<<"$v3" /dev/fd/6 6<<<"$v4"
1 2 4 6
2 3 5 7
3 4 6 8
but you should really question why you're doing that if you do find yourself considering it as chances are there's a better approach for whatever it is you really need to do.
See https://unix.stackexchange.com/a/148153/133219 for more info.
printf, not really. However, it's worth checking if this data should be in variables in the first place. Storing files and large outputs in variables is a common antipattern.