Skip to content

Commit

Permalink
Merge pull request lindahua#6 from lindahua/yyc/hygienic-macro
Browse files Browse the repository at this point in the history
Make functors macros hygienic and works outside NumericFuncs module.
  • Loading branch information
yuyichao committed Oct 2, 2015
2 parents 947c61f + e3ff971 commit ff396c6
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 17 deletions.
47 changes: 30 additions & 17 deletions src/functors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,27 @@ typealias TernaryFunctor Functor{3}

## macros for defining functors

# On 0.4 we can do `function evaluate end` (althought it's probably better)
# to use the call overload when we require julia 0.4
function evaluate() end

macro functor1(F, fun, T)
eF = esc(F)
efun = esc(fun)
eT = esc(T)
quote
type $F <: Functor{1} end
global evaluate
evaluate(::$F, x::$T) = $(fun)(x)
type $eF <: Functor{1} end
NumericFuns.evaluate(::$eF, x::$eT) = $efun(x)
end
end

macro functor2(F, fun, T)
eF = esc(F)
efun = esc(fun)
eT = esc(T)
quote
type $F <: Functor{2} end
global evaluate
evaluate(::$F, x::$T, y::$T) = $(fun)(x, y)
type $eF <: Functor{2} end
NumericFuns.evaluate(::$eF, x::$eT, y::$eT) = $efun(x, y)
end
end

Expand All @@ -33,32 +41,37 @@ default_functorsym(f::Symbol) =

macro functor1a(fun, T)
F = default_functorsym(fun)
eF = esc(F)
efun = esc(fun)
eT = esc(T)
quote
type $F <: Functor{1} end
global evaluate
evaluate(::$F, x::$T) = $(fun)(x)
type $eF <: Functor{1} end
NumericFuns.evaluate(::$eF, x::$eT) = $efun(x)
end
end

macro functor2a(fun, T)
F = default_functorsym(fun)
eF = esc(F)
efun = esc(fun)
eT = esc(T)
quote
type $F <: Functor{2} end
global evaluate
evaluate(::$F, x::$T, y::$T) = $(fun)(x, y)
type $eF <: Functor{2} end
NumericFuns.evaluate(::$eF, x::$eT, y::$eT) = $efun(x, y)
end
end

macro functor1a_ord(fun, T)
F = default_functorsym(fun)
eF = esc(F)
efun = esc(fun)
eT = esc(T)
quote
global $(F)
immutable $F{OT<:Real} <: Functor{1}
immutable $eF{OT<:Real} <: Functor{1}
order::OT
end
$(F){OT<:Real}(ord::OT) = $(F){OT}(ord)
global evaluate
evaluate(f::$F, x::$T) = $(fun)(f.order, x)
$eF{OT<:Real}(ord::OT) = $eF{OT}(ord)
NumericFuns.evaluate(f::$eF, x::$eT) = $efun(f.order, x)
end
end

Expand Down
9 changes: 9 additions & 0 deletions test/functors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ using NumericFuns
using Base.Test
using Compat

println(" macros")
test_unary(x) = -x
test_binary(x, y) = x + y
@functor1(TestUnary, test_unary, Number)
@functor2(TestBinary, test_binary, Number)

@test evaluate(TestUnary(), 3) == -3
@test evaluate(TestBinary(), 3, 4) == 7

println(" arithmetic operators")

@test evaluate(Negate(), 2) == -2
Expand Down

0 comments on commit ff396c6

Please sign in to comment.