Apologies for this long description with question. I tried to narrow it down as much as I could.
I find it difficult to think well in terms of passing contents. Worse, I am not sure how to debug this well. From a complex and much longer code set, I narrowed down my bug, and my debugging-method, to the following illustration:
mutable struct Point2; x::Int; f::Int; end#struct
################ my custom-rolled way of figuring out where exactly I no longer return the correct thing
gvec= Vector{Point2}(3) ## storage space
function returncheckin( ps::Vector{Point2}, s::String="" )
info("$s -- want to bang-change external data to $(ps)")
global gvec= deepcopy(ps)
end#function##
function returncheckback( ps::Vector{Point2}, s::String="" )
allx(ps::Vector{Point2})::Vector = [ ps[i].x for i=1:length(ps) ]
global gvec
info("$s -- want to check that my post-function data contents are still changed to $gvec")
@assert( allx( ps ) == allx( gvec ), "\n\tNon-Matching Ret Passers:\n\t\t$ps\n\tvs\t$gvec\n\n" )
end#function
################ my bug example
function manglemydata!( ps::Vector{Point2} )
dump(ps)
sort!( ps, by= p -> p.x ) ## does not change the contents inside ps, but ps itself
dump(ps) ## I think this ps is not the same storage location as the original ps
returncheckin( ps )
end#function
left= Point2(+26,+41)
mid= Point2(-4,+25)
right= Point2(+16,+1721)
manglemydata!( [ left , mid , right ] )
returncheckback( [ left, mid, right ] )
info("ok")
ok. sigh. I now understand that the problem was that the sort!
function does not sort the contents of ps, but probably replaces ps…or something like it. (Subtle? Maybe.)
if julia had a keyword like const
or immutable
that I could place onto the function formal parameters (here, ps
) that would flag changes to ps, this sort of bug would be much easier to spot. but julia does not.
so, what is a good practice to recognize such problems early on? the best I could come up with was my returncheckin()
and returncheckback()
. ugly, handrolled, specific. and in this case, my lifesaver…after a few hours of staring at code that bombed somewhere else because of it. the dump output wasn’t really that useful, because it did not tell me that the storage location of ps
had changed.
but it’s not about this particular bug of mine. it’s about something else.
I am wondering whether the best recommendation to julia newbies is to stay clear of writing bang functions (except trivial ones), deepcopy arguments on entry, and pass back all changes as tuples. but that seems like a step back from C/C++, not a step forward.
has something been done (or can something be done) to make such reference bug hunting simpler?
apologies for the long description here…
regards, /iaw