Open femtotrader opened 8 years ago
(You) should return an expression from macros. To make code an expression, decorate your code with either :(....) or quote ... end. Also, $ is valid only for expressions and strings. Lastly, there is a hygiene issue with macros. In order to keep $funcname intact you need esc around it. Here is corrected code
julia> macro GEN_FUNC(funcname)
fname=esc(funcname)
quote
function $fname(a, b, x=1, y=2)
return x
end
end
end
julia> macroexpand(:(@GEN_FUNC testing))
quote # none, line 4:
function testing(#21#a,#22#b,#23#x=1,#24#y=2) # none, line 5:
return #23#x
end
end
Update: Here is how myfunc can be manually constructed (Hint:I made it an expression with quote ... end and cheated from that)
julia> f_body=:(x+y)
:(x + y)
julia> f_parameters=Expr(:parameters, Expr(:kw,:x,Int64(1)), Expr(:kw,:y,Float64(2)))
:($(Expr(:parameters, :(x=1), :(y=2.0))))
julia> f_call=Expr(:call,:myfunc,f_parameters,:(a::Array{Float64,1}),:(b::Array{Float64,1}))
:(myfunc(a::Array{Float64,1},b::Array{Float64,1}; x=1,y=2.0))
julia> f_declare=Expr(:function,f_call,f_body)
:(function myfunc(a::Array{Float64,1},b::Array{Float64,1}; x=1,y=2.0)
x + y
end)
julia> eval(f_declare)
myfunc (generic function with 1 method)
julia> myfunc(2,3)
ERROR: MethodError: `myfunc` has no method matching myfunc(::Int64, ::Int64)
julia> myfunc([2.],[3.])
3.0
julia> myfunc([2.],[3.];x=4,y=8.)
12.0
Example of @eval usage
https://github.com/stevengj/DecFP.jl/blob/master/src/DecFP.jl
WIP
using TALib: get_dict_of_ta_func, d_typ_to_c
include("src/tools.jl")
using DataStructures: OrderedDict
d = get_dict_of_ta_func()
d_code = OrderedDict{Symbol,Expr}()
for (symb_func, func_info) in d
s_doc_Index = ""
s_doc_RequiredInputArguments = ""
s_doc_OptionalInputArguments = ""
s_doc_OutputArguments = ""
params = String[]
ctypes = String[]
for arg = ["startIdx", "endIdx"]
varname = uncamel(arg)
vartyp = "Cint"
push!(params, varname)
push!(ctypes, vartyp)
s_doc_Index *= "\n - $arg::$vartyp"
end
for arg = func_info["RequiredInputArguments"]
varname = replace_var(arg["Name"])
vartyp = d_typ_to_c[arg["Type"]]
push!(params, string(varname))
push!(ctypes, string(vartyp))
s_doc_RequiredInputArguments *= "\n - $varname::$vartyp"
end
for arg = func_info["OptionalInputArguments"]
varname = fix_varname(arg["Name"])
vartyp = d_typ_to_c[arg["Type"]]
push!(params, varname)
push!(ctypes, string(vartyp))
s_doc_OptionalInputArguments *= "\n - $varname::$vartyp"
end
for arg = ["outBegIdx", "outNbElement"]
varname = arg #uncamel(arg)
push!(params, varname)
push!(ctypes, "Ref{Cint}")
end
for arg = func_info["OutputArguments"]
varname = arg["Name"]
vartyp = d_typ_to_c[arg["Type"]]
push!(params, varname)
push!(ctypes, string(vartyp))
s_doc_OutputArguments *= "\n - $varname::$vartyp"
end
params = join(params, ", ")
ctypes = join(ctypes, ", ")
funcname = "_TA_" * string(symb_func)
symb_func = Symbol(funcname)
c_funcname = "TA_" * string(symb_func)
ret_typ = "TA_RetCode"
expression = quote
"""
$($funcname)(start_idx, end_idx, price_open, price_high, price_low, price_close, outBegIdx, outNbElement, outInteger)
Up/Down-gap side-by-side white lines (CdlGapSideSideWhite)
Pattern Recognition
Level: 0 - raw
Arguments:
Indexes:
- startIdx::Cint
- endIdx::Cint
RequiredInputArguments:$($s_doc_RequiredInputArguments)
OptionalInputArguments:$($s_doc_OptionalInputArguments)
OutputArguments:$($s_doc_OutputArguments)
Returns:
::$($ret_typ)
"""
function ($symb_func)()
"..."
end
end
d_code[symb_func] = expression # save expression to d_code dictionary (to see generated source code)
#eval(expression)
end
println(d_code)
println(repeat("=", 10))
println(d_code[:_TA_COS])
or
@eval function ($funcname)()
"..."
end
We might use macros instead of code generation using strings.
see http://docs.julialang.org/en/release-0.5/manual/metaprogramming/
http://stackoverflow.com/questions/37230071/metaprogramming-julia-functions-with-args-and-keyword-args/37230249#37230249