Given:
abstract ABSGene
type NuGene <: Genetic.ABSGene
fqnn::ANN
dcqnn::ANN
score::Float32
end
function mutate_copy{T<:ABSGene}(gene::T)
all_fields_except_score = filter(x->x != :score, names(T))
all_fields_except_score = map(x->("mutate_copy(gene.$x)"),all_fields_except_score)
eval(parse("$(T)("*join(all_fields_except_score,",")*")"))
end
ng = NuGene()
mutated_ng = mutate_copy(ng)
results in:
ERROR: gene not defined
in mutate_copy at none:4
If I just look at it as a string (prior to running parse and eval) it looks fine:
"NuGene(mutate_copy(gene.fqnn),mutate_copy(gene.dcqnn))"
However, eval doesn't seem to know about gene that has been passed into the mutate_copy function.
How do I access the gene argument that's been passed into the mutate copy?
I tried this:
function mutate_copy{T<:ABSGene}(gene::T)
all_fields_except_score = filter(x->x != :score, names(T))
all_fields_except_score = map(x-> ("mutate_copy($gene.$x)"),all_fields_except_score)
eval(parse("$(T)("*join(all_fields_except_score,",")*")"))
end
But that expands the gene in the string which is not what I want.
Don't use
eval
! In almost all cases, unless you really know what you're doing, you shouldn't be usingeval
. And in this case,eval
simply won't work because it operates in the global (or module) scope and doesn't have access to the variables local to the function (like the argumentgene
).While the code you posted isn't quite enough for a minimal working example, I can take a few guesses as to what you want to do here.
Instead of
map(x->("mutate_copy(gene.$x)"),all_fields_except_score)
, you can dynamically look up the field name:This is a special syntax that may eventually be replaced by
getfield(gene, x)
. Either one will work right now, though.And then instead of
eval(parse("$(T)("*join(all_fields_except_score,",")*")"))
, callT
directly and "splat" the field values:I think the field order should be stable through all those transforms, but it looks a pretty fragile (you're depending on the score being the last field, and all constructors to have their arguments in the same order as their fields). It looks like you're trying to perform a
deepcopy
sort of operation, but leaving the score field uninitialized. You could alternatively use Base'sdeepcopy
and then recursively set the scores to zero.