It’s when we take our perspective to higher grounds in an attempt to see ahead that things get more abstracted and complicated. But, down below with the bugs, it all tends to be a lot simpler.
There’s usually a next step encoded in our minds in the form of an intuition or a hunch. Maybe there's a couple, but I venture to say one is usually the optimal. We draw the head, then the neck, then the torso, then the arms, then the hands, and little by little we make a human. We write the helper method, then the other method, then the outer method, and line by line, we write a program.
Sometimes I wonder what would happen to life, as I know it, if I lived only from that small and intimate space of knowing. No grandeur, no being this or that type of person, just a continuous dialogue between the inner and outer self. What’s the next step… and after that, what’s the step after that?
Hunch by hunch, on I’d go, like the beatle making its way up the mountain.
Most of our upbringing is rooted in a dynamic where our learning about the world around us is mediated by adult approval. We learn what to do and not do through our caregiver’s acceptancing of it. As a result, doing something badly must be encoded in some primal part of our brain as something to avoid. By the time we become adults, it’s ingrained in the very foundation of who we are.
Most likely, we’re not raised to know or appreciate the value of being able to be bad at something. Unless we had a parent able to distill this nuance for us, most of us grew up not knowing how to be bad at something and it being ok.
But, in an adult world, a world of sophisticated skills and abilities, there’s virtually no way to become good at something without traversing through the desert of being bad at it and not having a clue. You can’t become really fit without first being a schlub, you can’t be a great programmer without first being embarrassingly bad at it, you can’t become a talented artist without first making bad drawings.
My intuition, here, is that grit, hustle, persistence, are qualities rooted in this idea, in this ability to override the primal instinct to want to be accepted, validated, and good. Overriding it with a new kind of ability to be bad at it and it being OK. Being embarassingly bad, asking dumb questions, seeming unintelligent; until, little by little, step by step, bird by bird, it all starts to come together..
This is the antithesis of ‘Oh, he was just always so talented’; it’s the discovery that everyone who has ever done something well started, first, by doing it not well at all.
Give me a sheet of paper and something to write with, and I'll turn the world upside down — NietzscheProgramming2021
I’ve had a somewhat liberating epiphany recently: The methods built-in to a programming language can also be written using simple procedures like if-else statements and loops. Built-in methods exist to bundle complicated procedures into one simple function — this makes programming easier. But they are also simply solutions to common problems, so a programmer doesn’t have to program them over and over again.
In design, there are thousands of nuts and bolts to every tool. Sketch and Figma are full of smart details meant to make a designer’s life easier. But I also know, by virtue of my experience, that all I need is a blank canvas, the rectangle tool, type and color. Not to be overly simplistic, but even that could be reduced to a sheet of paper and a pen.
Tools are helpful, but the work happens in thinking about and experimenting on a problem enough that eventually a solution starts to emerge — despite the tool. My crazy insight is that programming seems to be the same.
Splice is a robust method. With one single line of code, I can shorten an array, remove items at specific index positions, or even insert multiple new items at a location. It works in place and therefore on the array itself.
In my own version of splice, I built a couple of smaller methods that perform all the major procedures like shorten an array, delete an item(s) at a particular location, and insert as many elements as passed onto the function sequentially into the array.
A method to shorten the array
Methods to delete an item(s)
A method to insert an item(s)
All in all, lot’s to learn – but that was fun.
I have often reverted to Googled to get a quick random number generating function; without investing a moment to understand its simple mechanic and saving myself future searches. Being a little dyslexic, I'd get all confused with the max - min + 1 + min portion of the function. Well, today is the day I untangle this mess of mins and maxes.
If I were looking for a number between 0 and 9, I could simply shift that comma by 1 decimal place by multiplying it by 10.
To make the 10 inclusive, I could increase it by 1; or simply multiply it by 10 + 1. This would increase the range of possible random numbers from 0-9 to 0-10.
What this means, is that I'm multiplying the result of the random function by the range of possible numbers I'm looking for, and adding one so as to make it inclusive.
To get a random number between 0 and 75, I can:
What if I want a number between a minimum and a maximum, say between 25 and 150? There are two parts to the process. First, I need to determine the range of numbers I want my number to be in between of — that is the range of numbers between 25 and 150. That can be achieved by subtracting 25 from 150. I'm therefore looking for one random number out of 75 possible numbers.
Then, I want my possible random number to be in between 25 and 150. To get one of 75 random numbers that start at least at 25, all I have to do is add 25 to my random number. 🤯
In essence, this is a random number multiplied by a range of numbers and bumped up by the starting point number.
Good news is that the sort function does take a callback function with two arguments representing the two items being compared. In an array of numbers, if the difference between the two arguments is a positive number, that means that the first is bigger than the second. If the difference is a negative number, the second is bigger than the first.
This approach can also be harnessed for more unique examples. Below, for example, I have an array of human needs that I want to sort, and in the callback I provide a correct order template that is then used for the sorting:
Part of learning to program is to progressively develop the sensibility to stop writing the same things over and over again, and know when to abstract portions of code that run multiple of times into their own dedicated container; a container I can reference to multiple times in the future.
Good programming lies in a person’s ability to identify and work with ever more sophisticated versions of this idea of abstraction, optimization, and simplification. While also keeping in mind the program’s efficiency (how many steps are taken) and how much space it requires (space meaning literal memory). The careful balance of these forces is the life-long learning experience of programming.
One of the tools used to achieve this is the idea of memoization. In short, memoization is the idea of storing the result of a procedure — a piece of code — so that if, while the program is being run, that procedure needs to run again and again to yield the same result, I can rather store it somewhere and access that same result as many times as needed without having to run the code again.
Calculating a Fibonacci number — a number that results from the sum of its previous two counterparts — is a good example to demonstrate the utility of memorization. In essence, the Fibonacci sequence:
The process of traversing through this sequence is most efficiently done using a recursive function.
But, this recursive solution even though simple in design, creates a multiple function calls on the same number to yield the same result. Take fib(5):
In a simple fib(5), there are multiple calls on 3, 2, and 1. Now imagine calling fib(546731). This is where memoization comes in. To reiterate, memoization is the idea of storing the result of a function call for later use. This can be done with a simple key/value dictionary where, every time I call fib on a number for the first time, I’ll store the number and its result in the dictionary for later.
That means that each number will, now, only be called once. In all future calls after the first one, the fib function will use the value already stored without running itself again.
In a nutshell, that’s it. The idea of memoization isn’t exclusive to Fibonacci. It rather comes down to grasping it as an approach to be used in problems where the same piece of code is being run again and again to yield the same result.