The Joy of Accidental Discoveries

When I was younger, I didn’t really communicate at all with the wider programming world. At the time, I was programming on an early 2010s iMac with a stock copy of Python 3 IDLE installed, trying to make games using Tkinter and PyGame. Most of the programs that I created at that time have now been lost. But, I recently did some digging back through many of my old hard drives, and discovered some fascinating things. It seems like the nine-year-old me had accidentally done some very interesting stuff, including some very interesting accidental discoveries. Here is a list of some of the highlights…

Object Oriented Programming

Now, nobody seems to agree on what OOP actually means, so I’ll do a quick definition of mine: the encapsulation of application state into re-usable objects with associated public methods to expose ways of mutating state and private methods for internal use of the class only.

Now, it seems that nine-year-old me had also thought that it might be a good idea to do something like this. I discovered files upon files of large amounts of Python modules containing just functions which would take in a “target” argument. I was intrigued, so I had a deeper dig. I found that the origin of these target objects was almost always a function called “create_”. This returned an array which contained data. At the time, I must have thought this was genius. Then, there were functions called things like “destroy_” or “remove_”. Basically, we had arrays (which are associative in Python) which were being treated like classes and mutated by what we may call methods. Brilliant!

Now, not to brag, but I even went as far as to invent singletons. There were some modules which contained an internal variable which contains a reference to the current instance of a “class” and would completely ignore the constructor if needbe and simply return the existing reference. Then, the single reference would be mutated from all around. I don’t know if this technically counts as a singleton (these definitions get mutated by corporate “best practices” every other year), but I’m taking credit anyway, dammit!

You might be thinking “Now, hang on a minute! Python is an OOP language, you liar!”. Well, it seems that nine-year-old me either didn’t know or didn’t understand how to use Python built-in OOP, so I just made my own. Funnily enough, this method is similar to how OOP works in Lua. Turns out that maturing as a programmer really does make you less creative. I could theorise that this is because you begin to expect the tools to do your work for you more than you are expected to just do it yourself.

Comma Separated Values

So, I wrote a program when I was about eleven called the “Turtle Factory. It is loosely based on the Turtle Factory used as one of the activities in the Carol Vorderman Coding Book (which is the book from which all by foundation in programming comes from) . However, I decided to take it a step further. It evolved, effectively, into a full on drawing program, with mouse support, scripting support and almost everything else you can think of, except actual good quality drawing. You see, this “drawing program” was using a 640x480 rasterised stock Python turtle canvas. Basically, the quality sucked. However, something that didn’t suck was the method of saving the file instructions.

You see, I couldn’t figure out how to save the drawn image as an actual image file. So, eventually, I must have given up and come up with my own solution (this seems to be a recurring pattern). What I was basically doing was saving all the drawing instructions in a file (for example, “down,10” or “goto,100,200”). Does that format look familiar? Well, good, because it’s basically just CSV without the column headers. Because Python had some really useful functions for splitting strings, I decided to use it to the best of my ability. I can remember distinctly spending hours debugging the format and accounting for all the errors that can happen and how to inform the user. I can’t remember how I initially came up with the format, but I can remember that I was very proud of my work when I was done.

Looking back, I really would not have done this today. The entire format was incredibly inefficient. Instead of storing the final result, we were instead storing the entire process for creating the file on disk. Imagine if we had to store every single brush stroke that DaVinci made while painting the Mona Lisa. We probably wouldn’t have enough storage space in the entire universe. Also, to reload the image, you have to redraw the entire image by going through the sequence of instructions, one at a time and wait for the time it takes for the turtle library to redraw and render the new image. This meant that the image instructions were also read only, or else the entire chain would be broken. So, once an image is saved, it is immutable unless the user suddenly learns to code and edits the file code themselves. It also meant that the image was only accessable linearly, making all random access impossible without breaking the entire image.

Basically, it sucked - BUT it was CSV and I invented it. So, again, I am taking credit for a bad invention for all the wrong reasons.

IRC

Now, this one is a bit of a stretch. I was experimenting with my new discovery, UNIX-style sockets! To this day, I am still very good at doing socket programming because of my experience with the Python socket library. At the time, I thought it was so cool that I could send text to other applications or (even!) other users on the network!

One day, my dad brought home a laptop that he said he wanted me to “road test” for the head of IT at his work. This was my chance! I quickly downloaded Python and wrote a real quick socket program. On my main laptop, I had written a “chat server”. This chat server would append your username to the start of your message, followed by a colon, and then the actual message text. Finally, the server would recieve the message and send back a response. Make sense? Well, it worked, but with some glaring flaws. For instance, you could crash the server by pressing Control-C or Control-D during program execution. The former would cause an IOException on attempting to read from a dead socket, the latter would cause an IOError when attempting to read from an EOF’d file stream. Because I didn’t really like this, I decided to add a command system. At the time, the only other chat I had ever used was the good old Roblox chat, so I used the same format: a forward slash followed by the command name. One of these was “/quit”, which would gracefully close the connection and allow the next person who wanted to chat to enter the server’s connection slot. Later, I added admin commands (still in the Roblox style: a colon followed by the command name). For instance, “:stop” would stop the server, “:kick” would clear the socket connection buffer (kick off all pending clients) and stuff like that.

So, I had basically drafted up my own version of the IRC protocol, but with a stupid, cringe command system and no actual IRC goodness (no channels, user-to-user etc.)

Finite State Machines

Now, you might start to shake your head at this point and wonder “Is he really trying to take credit for finite state machines?”. Well, no, of course not. But I sure am going to boast about the fact that I accidentally created one while attempting to do a LeetCode problem that I was not nearly qualified for.

When I was still learning Python, I was once linked the classic LeetCode “Simple” Calculator challenge. Now, whoever linked me this was probably just messing with me and didn’t actually expect me to actually attempt it. A whole load of attempts later, however, and I was there. I distinctly remember that, at the time, I was programming on an early-2013 iMac with a Python 3.4 install on it. Everything I tried seemed to come up false - until, that was, I came up with my revolutionary context system. You see, my version of the finite state machine was, basically, a load of variables laid out which I called the “calculator context”. Basically, the context would decide as to what was allowed next and what the meanings of numbers were in context. For instance, if the context said that we have just parsed a number, any operation (including subtraction) would require an operand and the context would shift (yes, I did use that terminology) over to “awaiting operand”. However, if the context was “awaiting operand” or “nil”, a subtraction or addition would modify the signature of the number. Genius! I thought that this was immensely clever. LeetCode, unfortunately, didn’t agree. Somewhere on the hard drive of the iMac is the hundreds of lines long solution that I wrote, filled with immense amounts of if, else-if and else statements for every state that wasn’t illegal. The solution is probably still at the bottom of the league table in terms of both space and time complexity.

In theory, the solution should have worked flawlessly. However, I kept finding corner cases based on the fact that my implementation of a finite state machine was completely broken and based around far too much junk. The most common bug in the code was me forgetting to toggle off one of the “state indicators” - as I called them - after a state shift. I could have abstracted this into a function. I could have just used a single state which changed to multiple different values. Instead, I used multiple different booleans.

A mess. But, I was still learning.

In conclusion

I could try to make some grand philosophical point here about how “nothing is truly unique” or “great minds think alike” or whatever - but, instead, I would just like to leave some words of encouragement for other programmers learning. Once, I could hardly write a simple Python application without it having ten thousand bugs. Now, I get annoyed at myself when my code doesn’t work first time. The messy and experimental process of learning is one which can never truly be reasoned with, in that you have to see where it takes you. If that takes you to a horrible re-invention of a finite state machine, a version of OOP that would probably make Bjarne Stroustrup throw up, or a parallel universe version of IRC, all of these things are valuable milestones in your programming journey. As soon as you have some parallel to these famous ideas in your own mind, you have reached your own personal milestone along the path that computer scientists took all those years ago. You stand on the shoulders of giants. One day, someone will stand on your shoulders. And, if that means a few more terrible Python scripts - so be it.

Ethan Marshall

A programmer who, to preserve his sanity, took refuge in electrical engineering. What an idiot.


First Published 2021-11-01

Categories: [ Old Blog ]