# Hunting Bang! Function Bugs

**URL:** <https://discourse.julialang.org/t/hunting-bang-function-bugs/10771>\
**Category:** New to Julia\
**Created:** [May 7, 2018, 11:57pm UTC](https://discourse.julialang.org/t/hunting-bang-function-bugs/10771 "2018-05-07T23:57:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![iwelch](https://avatars.discourse-cdn.com/v4/letter/i/8c91f0/32.png) [@iwelch](https://discourse.julialang.org/u/iwelch)\
**Post date:** [May 7, 2018, 11:57pm UTC](https://discourse.julialang.org/t/hunting-bang-function-bugs/10771/1 "2018-05-07T23:57:31Z")

</div>

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:

```julia
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

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 8, 2018, 12:24am UTC](https://discourse.julialang.org/t/hunting-bang-function-bugs/10771/2 "2018-05-08T00:24:11Z")

</div>

> [@iwelch](#):
>
> I now understand that the problem was that the sort! function does not sort the contents of ps,

What is the problem? The `ps`’s content should have been mutated. The content of the contents (i.e. the content of the objects in `ps` are not).

From the way you are talking, it seems that you’ve just got a very deep misunderstanding of objects and variables in julia since you are thinking them as c++ objects and variables. In C++ objects are their storage, which can be variables, fields, array element etc. In julia (and basically **ALL** scripting languages), objects are just object. Variables, fields, array elements are just how these objects are referenced. In C++ assigning to variables, fields etc is a mutation of the object stored in there. However, in julia (and other scripting languages) it is just a change of reference (point to a different object) and **NEVER** has any effect on the object. (Or to summarize it, `operator=` does not make any sense semantically in julia.)

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [May 8, 2018, 12:29am UTC](https://discourse.julialang.org/t/hunting-bang-function-bugs/10771/3 "2018-05-08T00:29:01Z")

</div>

> [@iwelch](#):
>
> 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.

And definitely no.

Also note that this problem is more or less specific to C and especially C++ programmers (I don’t know what go/rust etc is like but I assume those users have either used C/C++ or have seen enough languages to not have this problem). Some very experienced MATLAB users that haven’t used anything else could also have a slightly different version of it.

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [May 8, 2018, 12:51am UTC](https://discourse.julialang.org/t/hunting-bang-function-bugs/10771/4 "2018-05-08T00:51:09Z")

</div>

Maybe an analogy to sorting a vector of integers is helpful:

```julia
mutable struct Point2
    x::Int
    f::Int
end

manglemydata!(is::Vector{Int}) = sort!(is)
manglemydata!(ps::Vector{Point2}) = sort!(ps, by=p->p.x)

ints = [3, 1, 2]
manglemydata!(ints)

left = Point2(+26,+41)
mid = Point2(-4,+25)
right = Point2(+16,+1721)

points = [left, mid, right]
manglemydata!(points)

```

---

<div class="post-metadata">

**Author:** ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)\
**Post date:** [May 8, 2018, 5:19am UTC](https://discourse.julialang.org/t/hunting-bang-function-bugs/10771/5 "2018-05-08T05:19:31Z")

</div>

> [@iwelch](#):
>
> 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.)

Maybe I don’t understand what do you mean but I think your assumption is mistaken and this is (your) problem:

```julia
julia> [left , mid , right] === [left , mid , right]
false

```

so

```julia
manglemydata!( [left , mid , right] ) # parameter here is in different object 
returncheckback( [left, mid, right] ) # than parameter here

```

So you compare different objects not because sort! change one behind the curtain but because you call functions with different parameters.

And everything is OK here when we use same object for sort and for check:

```julia
julia> points = [left, mid, right]
3-element Array{Point2,1}:
 Point2(26, 41)  
 Point2(-4, 25)  
 Point2(16, 1721)

julia> manglemydata!( points)
3-element Array{Point2,1}:
 Point2(-4, 25)  
 Point2(16, 1721)
 Point2(26, 41)  

julia> returncheckback( points)
INFO: -- want to check that my post-function data contents are still changed to Point2[Point2(-4, 25), Point2(16, 1721), Point2(26, 41)]

julia> 

```
