What has been the worst Julia production code you have written?

Just a tongue in cheek topic. What has been the worst Julia production code you have written?

I kick it off with some of my recent “favourites”.

Converting a HTTP.Response to string

What is wrong with the following code? Looks good, I thought:

using HTTP

function obtain_unauthorized(url)
    [...]
    r = HTTP.get(url, headers)
    string(r)
end

The problem is that the output of r is truncated when a long response is converted to string:

julia> using HTTP

julia> r = HTTP.Response(200, string(zeros(1000)));

julia> s = string(r)
"HTTP.Messages.Response:\n\"\"\"\nHTTP/1.1 200 OK\r\n\r\n[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n⋮\n5000-byte body\n\"\"\""

Note the . So, my code worked as long as the response from the server wasn’t too long. Obviously, servers can send very long responses and, eventually, it all broke down when trying to parse the “stored” user data as JSON and again when trying to store the authentication for users.

Serializing strings of objects to a file

So, suppose you have a nice vector of pairs where pairs look like

Pair{AbstractString, AbstractString}("a", "b")

and you need to write this to a file and read from it again. Of course, you can use Serialization but that isn’t guaranteed to be stable over different Julia versions. Therefore, you just write this to a file and use x = Parse.eval(line) for each pair in the document. Super great idea; now Julia will give you super fresh methods, because a lot of methods are invalidated. Loading your package will take considerably longer due to this.

Writing to a database via a global variable

So, the database can handle concurrent writes, so as a developer you don’t need to think anymore, right? Well, if you conveniently add

const CONN = db_connect()

to your module, then it will work just fine during basic tests. Unfortunately, when real users start using your webserver at the same time, things will go haywire and you will, again, lose data.

I’m very curious what other great ideas other people have had, which turned out not to be so great :stuck_out_tongue:

EDIT: Added “production” to the question.

11 Likes

This:

data = vcat(map((a, b, c, d, e, f)->
                hcat(a, b, c', d', e', rad2deg(f[1]), rad2deg(f[2]), f[3]/1000),
                gps_time, utc_time, r_TOD, r_PEF_ace, r_ECEF, wgs84)...)

:smiley:

1 Like

I‘m affraid that I can’t follow. What does your code do exactly and why is it a bad idea? @Ronis_BR

1 Like

It takes a lot of vectors of vectors and tuples and create a matrix to write to a file using writedlm.

It is a bad idea because it is ugly and nobody can understand :slight_smile:

9 Likes

It seems you answered your own question. :smiley:

17 Likes

I wrote a piece of code that used collect:

:pensive:

9 Likes

I think I could find about 3-5 examples from the code I write every week.

I find it liberating to write bad code on a first iteration and not care. Best is the enemy of good, thinking about the perfect way to code something breaks the flow. I usually try to improve stuff before I merge a PR.

26 Likes

Probably this version of Ranges.jl: GitHub - mkitti/Ranges.jl: Additional range syntax for Julia

It breaks all the type piracy rules, but it was fun to see what was possible.

4 Likes

Yes, I agree.

I’ve updated the question since I was curious about production mistakes. So, where some piece of code seemed like a good idea but ended up breaking things.

1 Like

Found some code I wrote 4-5 years ago. Globals. Zillions of temporary arrays. Abstractly typed structs. It was otherworldly…

6 Likes

Not exactly production code because I have nothing that would qualify for this, but in the time between starting to learn Julia and actually understanding what I do (most of the time), I somehow came up with this beauty:

ntuple(t -> begin i,j = divrem(t+1,2); vals[i][j+1] end, 2*length(vals))

Which is a completely unintelligible and buggy way of expressing

Tuple(Iterators.flatten(vals))

(for a vector of 2-Tuples, that’s what vals is supposed to be)
But I forgot what it was supposed to do and was afraid to change it for a long time because it looked so brittle, lol.

8 Likes

If Division II league posts are allowed here, the naive solution to this integer decomposition problem, while simple and working fine for small N, its “algorithm” is so bad that the execution time increases exponentially with N (compare it to Gustaphe’s turbo solution).

A rough estimate is that the naive algorithm would take about 1 Million years to run for case N=100 in a normal laptop (if it wouldn’t run out of memory long before that).

NB:
It would be nice to have a package that estimates the run time and disk space required for such massive problems, where complexity increases dramatically with some parameter N.

What’s wrong with collect() in this case?

I’m still learning Julia, so I don’t quite see the problem.

collect materializes the results of an iterator. Using the iterator directly is usually sufficient and avoids the memory allocation.

4 Likes