Day in the Life - June 2023

I recently shared my morning / daily routine with a co-worker and that prompted me to write a quick post to share with the masses (or lack thereof, IDK how many folks come here). This current routine is the result of refining my daily routine over the last few years, especially as it relates to programming and continuing to grow my knowledge.

I used to put in hours upon hours, which was great when I didn't have much else to do. Ultimately it was not sustainable. These days I do more of an "atomic habits" approach I suppose. (I have the book but have yet to read it other than a coarse skim).

Without any further delay here it is:

  1. Practice Touch Typing - 5 minutes (For ferocious vimage and Rubyisms)
  2. Watch One RailsCast Video (Yes, I know they are old. I like history)
  3. Read Current Ruby Docs - 5 minutes (Diving deep - one method at a time)
  4. Watch One Ruby Kaigi 2023 Video (Gnarly technical talks for swelling your brain)
  5. CSS Course - 25 minutes (CSS was my enemy - but I wanted to become friends)
  6. C Programming Book - 25 minutes (I have a big goal of contributing to Ruby itself so I figured I should learn some C. It's been good fun honestly)

That's it. That's how I spread myself around learning about talking to computers day-to-day.

I like reading the Ruby docs and often get reminded of things I forgot. More often than not, I get turned on to new things.

With that I'll share a quick Ruby knowledge nugget I was reminded of today from my readings of the Ruby docs.

How many times have you called Array#flatten immediately followed by Array#join to turn potentially or known nested arrays of elements into a "flat" or single level array of elements and then convert them into a string joined by some separator? Perhaps something like this:

names = [
  "Eileen",
  "Gregory Brown",
  ["Jemma", "Jim Weirich"],
  "Katz (Yahuda)",
  "Matz",
  [["Rafael"], ["Tenderlove"]],
  "_why"
]

names.flatten.join(", ")
#=> "Eileen, Gregory Brown, Jemma, Jim Weirich, Katz (Yahuda), Matz, Rafael, Tenderlove, _why"

# Sorry to everyone I left out of this example but that would be far too large
# of an array. But know this, I love you all and thank you for being in this
# lovely community and (hopefully) my friend.

This works and is arguably more readable or "perhaps paints a clearer picture of what is occurring" than what I'm about to share next with you but of course I'm going to share it with you, dear friend. With that, we can actually achieve the same result with Array#join alone.

Per the method documentation:

Uses recursive element.join(separator) if element is a kind_of?(Array).

What this means is that when the Arrray#join method is going through the elements in main array, if it encounters other arrays it will essentially destructure the array element and insert its elements into the returned String object. It will do this for any and all nested arrays that it encounters.

So with that stated, the previous code can become:

names = [
  "Eileen",
  "Gregory Brown",
  ["Jemma", "Jim Weirich"],
  "Katz (Yahuda)",
  "Matz",
  [["Rafael"], ["Tenderlove"]],
  "_why"
]

names.join(", ")
#=> "Eileen, Gregory Brown, Jemma, Jim Weirich, Katz (Yahuda), Matz, Rafael, Tenderlove, _why"

This is nice but as stated prior, perhaps not as readable. This code requires that you know this detail about the Array#join method. If you don't you may have to dive into the docs (not a bad thing) to find this out if you encounter a similar example in the wild and care to know how a single call to join is accomplishing such a task.

Let's take this a step further and look at some numbers. We'll call upon our companion Benchmark IPS to assist us. We will use the same array from the previous examples and run each version in a benchmark block as shown next along with the resulting output that I received:

names = [
  "Eileen",
  "Gregory Brown",
  ["Jemma", "Jim Weirich"],
  "Katz (Yahuda)",
  "Matz",
  [["Rafael"], ["Tenderlove"]],
  "_why"
]

Benchmark.ips do |x|
  x.report("with flatten") do
    names.flatten.join(", ")
  end

  x.report("join only") do
    names.join(", ")
  end

  x.compare!
end



Warming up --------------------------------------
        with flatten    46.096k i/100ms
           join only    84.838k i/100ms
Calculating -------------------------------------
        with flatten    465.193k (± 1.2%) i/s -      2.351M in   5.054294s
           join only    849.588k (± 0.7%) i/s -      4.327M in   5.093008s

Comparison:
           join only:   849587.7 i/s
        with flatten:   465192.8 i/s - 1.83x  slower

And there you have it but try it for yourself and see what you get. Take it for what you will but for me I think I know what method I won't be calling next time.