I would like to understand how to generate functions programmatically.

basically how to do this (nevermind if this example is sensible):

function -(d1::DataFrame,d2::DataFrame)
if !(nrow(d1)==nrow(d2))
error("need same num of rows")
end
if !(names(d1).==names(d2))
error("need same colnames")
end
df = DataFrame(df1)
for n in names(d1)
df[n] = df1[n] .- df2[n]
end
end
function +(d1::DataFrame,d2::DataFrame)
if !(nrow(d1)==nrow(d2))
error("need same num of rows")
end
if !(names(d1).==names(d2))
error("need same colnames")
end
df = DataFrame(df1)
for n in names(d1)
df[n] = df1[n] .+ df2[n]
end
end
# would like to do something like
# for op = (:+,:-, :*, :/,)
# eval(:(($op)(a,b) = ... )
# end

I am not sure about your use. Here is an example of generating arithmetic functions in a loop (from Base/float.jl)

for op in (:+,:-,:*,:/,:\,:^)
@eval ($op)(a::Float16, b::Float16) = Float16(($op)(Float32(a), Float32(b)))
end

The @eval lets ($op) be replaced with the appropriate token for each of the symbols in (:+,:-,:*,:/,:,:^) .
For a longer “program”

for op in (:+,:-,:*,:/,:\,:^)
@eval begin
# ...
end
end

If this is helpful to you, feel welcome to ask follow on questions. If your question is about creating functions through developing Expr[essions], let us know that.

import Base: +, -, *, /
type A
v::Int
end
for op = (:+,:-, :*, :/,)
@eval begin
($op)(a::A, b::A) = A($op(a.v, b.v))
end
end
julia> A(1) + A(2)
A(3)
julia> A(1) - A(2)
A(-1)