currently .args in do.call2 gets evaluated so using .args instead of the ... doesn't really give a speed boost.
EDIT2: The solution used to be a lot more complicated. I'd completely forgotten that I'd already solved the same problem months ago. Benchmarks are for the old version but the differences are miniscule.
Speed comparison (code below). do.call3 is do.call2 with the above modification:
Unit: microseconds
expr min lq mean median uq max neval cld
do.call("head", list(DT)) 3660.877 3881.071 18856.1073 10748.9050 12374.700 73379.548 10 ab
do.call("head", list(quote(DT))) 599.625 756.372 787.4424 776.4325 821.062 984.653 10 a
do.call2("head", DT) 825.105 861.182 894.3355 877.1990 926.805 994.293 10 a
do.call2("head", args = list(DT)) 4088.513 7095.027 23175.9467 11260.6695 14250.389 100241.001 10 b
do.call3("head", DT) 611.443 814.842 850.4215 858.6945 869.269 1065.826 10 a
do.call3("head", args = list(DT)) 829.771 865.847 918.1589 920.1185 956.661 1016.376 10 a
N<-1e6
DT<-data.table(x=rnorm(N),y=runif(N),z=rpois(N,1))
microbenchmark(
do.call("head", list(DT)),
do.call("head", list(quote(DT))),
do.call2("head", DT),
do.call2("head", args=list(DT)),
do.call3("head", DT),
do.call3("head", args=list(DT)),
times=1e1
)