If you need a version that works on expressions instead of functions,
try something like:
/* We could just return limit(e,v,x). But then we'd have
save_sub(x,x,cot) --> 1/tan(x). Maybe that's ok, but
we'll do it this way. */
safe_sub(x,v,e) := block([f : errcatch(subst(x,v,e))],
if emptyp(f) then limit(e, v, x) else first(f));
fun_table(f, lo, hi, n) := block([h, l, listconstvars : false, v :
listofvars(f)],
v : if emptyp(v) then ?gensym() else if length(v) = 1 then first(v) else
error("The first argument to 'fun_table' must be an expression in
one or fewer variables"),
f : if listp(f) then f else [f],
h : (hi - lo) / n,
l : makelist(cons(lo + i * h, map(lambda([s], safe_sub(lo + i * h,v,s)),
f)), i, 0, n),
l : cons(cons(v,f),l),
funmake('matrix, l));
(%i4) fun_table([sin(x), tan(x)],0,%pi, 2);
Division by 0
(%o4) matrix([x,sin(x),tan(x)],[0,0,0],[%pi/2,1,und],[%pi,0,0])
Barton