Metaprogramming: create function for different ops, +, -, * etc

question

#1

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

thanks


#2

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.


#3
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)

#4

To turn the :+ into a :.+ symbol, this works but looks ugly: :($(Symbol("."*string(:+)))). Is there a better way?


#5
julia> op = :+
:+

julia> Symbol(".", op)
:.+

#6

Cool. Can even shave one more char off: Symbol(:.,:+)