I’m trying to enter the Metaprogramming world, and I decided to convert some functions into a macro.
I have one function get_return
, that depending on one parameter , call two other functions. One that returns a sum, and other function that returns an array with all values.
function get_return(a,B,c; whatToDo=:sum)
if whatToDo==:sum
return _return_a_sum(a, B, c)
elseif whatToDo==:vec
return _return_a_vec(a, B, c)
else
@error "wrong input"
end
end
function _return_a_sum(a, B, c)
E = zero(ComplexF64)
j = 1
for b in eachcol(B)
temp = rand(ComplexF64)*sum(b)
E += temp * c[j]
j += 1
end
return E
end
function _return_a_vec(a, B, c)
E = Array{eltype(c)}(undef, length(c))
j = 1
for b in eachcol(B)
temp = rand(ComplexF64)*sum(b)
E[j] = temp * c[j]
j += 1
end
return E
end
Now, I want to write two macros, one that creates an array, and other the access its elements. My best code so far is:
macro fix1(scalar_or_vector, original_code)
quote
local the_command_string = $(string(original_code))
local the_command_expression = Base.Meta.parse(the_command_string)
var_E = the_command_expression.args[1]
var_name = the_command_expression.args[2].args[2].args[2]
if $(esc(scalar_or_vector)) == :sum
return eval(Base.Meta.parse("$(var_E) = zero( eltype($(var_name)) )"))
return $(esc(original_code))
elseif $(esc(scalar_or_vector)) == :vec
return eval(Base.Meta.parse("$(var_E) = Array{eltype($(var_name))}(undef, length($(var_name)))"))
end
end
end
macro fix2(scalar_or_vector, original_code)
quote
local the_command_string = $(string(original_code))
local the_command_expression = Base.Meta.parse(the_command_string)
var_E = the_command_expression.args[1]
var_fixed = the_command_expression.args[2].args[2]
var_array = the_command_expression.args[2].args[3].args[1]
var_fillA = the_command_expression.args[2].args[3].args[2]
if $(esc(scalar_or_vector)) == :sum
return Base.Meta.parse("$(var_E) += $(var_fixed) * $(var_array)[$(var_fillA)]")
elseif $(esc(scalar_or_vector)) == :vec
return Base.Meta.parse("$(var_E)[$(var_fillA)] = $(var_fixed) * $(var_array)[$(var_fillA)]")
end
end
end
Then I apply these new macros :
function _return_a_sum(a, B, c; whatToDo = :sum)
@fix1 whatToDo E = zero(eltype(c))
j = 1
for b in eachcol(B)
temp = rand(ComplexF64)*sum(b)
@fix2 whatToDo E += temp * c[j]
j += 1
end
return E
end
Now I run the code:
a, B, c = rand(3), rand(3,40), rand(ComplexF64, 40)
_return_a_sum(a, B, c; whatToDo = :sum)
The answer is not an error message, but the value is zero (or empty array).
I have no idea how to debug this code, because I cannot print anything inside the _return_a_sum
. I need help to understand why .
If possible, I would like to someone tell me all the conceptual errors that I’m doing here too.
Thank you in advance.