I suggest that you use Outer, which enables you to get rid of dummy indexes. By just using @user21 's table1 and table2,
table1 = {1, 2, 3, 4};
table2 = {10, 20, 30};
Outer[f, table1, table2]
returns
{{f[1, 10], f[1, 20], f[1, 30]},
{f[2, 10], f[2, 20], f[2, 30]},
{f[3, 10], f[3, 20], f[3, 30]},
{f[4, 10], f[4, 20], f[4, 30]}}
Pay attention to how Outer distributes table1 and table2; and I think this is one of the typical examples to avoid explicit loops in Wolfram language.
If you want a 1D vector output rather than a 2D matrix, check Tuples (or just Transpose) and Apply to level one (shorthanded as @@@).
Update
In the previous last paragraph, I mean, if your two tables have equal length and you want just to pick corresponding entries from them as the function's arguments, you could use:
tables = {{a, b, c}, {x, y, z}};
f @@@ Transpose@tables
returns
{f[a, x], f[b, y], f[c, z]}
But I find a better alternative, MapThread:
MapThread[f, tables]
Evaluatein this code snippet is most likely not necessary or even desirable.Evaluateis a symbol you should only start using when you get a good feel for how the Mathematica evaluator works and understand how attributes likeHoldAllwork. – Sjoerd Smit Apr 18 '18 at 13:32