00:00:00.560
Okay, my screen isn't working, no problem. I'm using Vim, so you don't need to worry about that.
00:00:07.919
Okay, so my name is Ju. I want to do a very easy sort of talk today, just one simple exercise.
00:00:15.799
You know, we have a lot of programmers in the room, so we should be able to handle this exercise, right? It's not too difficult.
00:00:24.080
We're going to do it together and see how what seems to be an easy problem can be quite hard to get right.
00:00:29.160
Then, I would like to try solving the same problem using some patterns and techniques from the functional programming world.
00:00:34.960
I've been doing a fair amount of functional programming, so we can just take a look at it.
00:00:58.920
One thing I really wanted to make clear is to feel free to interrupt me at any point. No need for microphones; just yell if you see a typo or think we could do something better. I'm very happy to take it easy.
00:01:16.920
There's no script apart from this one.
00:01:23.640
So, let me set the scene. First of all, let's generate some random numbers in Ruby and save them to a file.
00:01:38.600
I'm going to say 'store' and just save it as 'numbers' so we can refer to them later. I'll generate 100 random numbers using 'map' with 'rand 10'. Once I've done this, I'll join them with a newline character.
00:01:56.360
And that's it.
00:02:01.920
To keep the exercise meaningful, I'll do it only once. So I'm going to say 'unless file.exists? store'.
00:02:21.840
You see, no copilot here, it's all done manually.
00:02:32.480
Now that I have this, I'm going to run the script.
00:02:43.959
If I look, we have some numbers. If I run 'head of numbers', tada! Random numbers!
00:02:55.080
So, we have these random numbers. What do we want to do with them? As I said, it's a very simple exercise; we're going to create a histogram.
00:03:01.959
For each of these numbers, I want to write the index of that number and then as many hashes as the number itself.
00:03:08.920
So for the first number, we write zero hashes; for the second number, we write one hash, and if there are eight hashes, we write eight hashes.
00:03:16.360
Let's do that.
00:03:22.239
So, I'm going to actually read these numbers. I'll use 'file.read store', and I can now split them over newline characters.
00:03:28.120
I can do something a little tricky, which is to use a magic proc. Basically, you can write a block without actually indenting the block. You can say, 'I want to map over this function' and just pass in the symbol.
00:03:41.200
Anyways, I've spoken too much. You read the files, split them over the new lines, and convert them to integers.
00:03:59.680
Now, once I have that, I can loop through each number using 'each_with_index', which is part of the Enumerable module. You will get the value plus the index, which is convenient.
00:04:15.319
So, I get the number and the index; for each of these, I can say I want to print the index.
00:04:20.519
Then, for each of my numbers, I can say the hash symbol and repeat it as many times as the number itself.
00:04:25.639
This is one of the beauties of Ruby. Now if I run the script, tada!
00:04:36.600
When we check the numbers, it looks about right: six here, seven, five. Yeah, it seems correct.
00:05:05.160
Any questions about this code? It's pretty easy, right? Let's make a little change and see how much more difficult this exercise gets.
00:05:20.000
The one change I'd like to make is to group consecutive rows that have the same number and write a nice summary. For example, on rows 93 and 94, I would like to display a summary instead.
00:05:36.360
Instead of just showing this directly, I would like to show something like 'D94' instead.
00:05:52.319
How would you do it?
00:05:58.479
Think about it, but in silence, like this very old ancient Chinese proverb.
00:06:01.479
Okay, I'm sure you have some ideas. Start talking, but for now, think about it.
00:06:07.520
We're going to try to solve it in a random way, and I think it would be fun to use just imperative code. We're going to rely on good old variables, and we will do some messy stuff to see how we can arrive at a solution using traditional imperative code.
00:06:36.360
What makes this problem different and more complicated is that we have introduced some sort of state. Previously, we could just consider each row individually, but now we have to delay actions until that group of the same number is fully processed.
00:06:47.400
So if I were to be explicit about it, I would say, 'Okay, I need to keep track of the previous number and only print when needed'.
00:06:54.600
If the current number is the same as the previous, I know the group is continuing, so I will continue without printing. If the current is different from the previous, I can print a summary of the previous group.
00:07:19.799
Now, I will say that the previous number is initially nil, and we'll start going through the numbers using each with index. The first problem we face is that if the previous number is nil, we can't compare it directly.
00:07:40.000
So we have to initialize it with the current number for the first iteration. In the next iteration, we will check if the current number equals the previous number.
00:08:09.440
If they are the same, we can just continue. If they are different, we can print a summary of that previous group.
00:08:38.760
We forgot to keep track of the previous index, which is important because for example, in the group, we should have noted 93, but we forgot to do that. No problem, we can just add a new variable for the previous index.
00:08:58.120
This is the beauty of programming. You create things on the fly.
00:09:23.600
So we set previous_index to the current index. Now, I'll say that if the previous_index equals index minus one.
00:09:52.560
If it is a group of only one, we will print something slightly different with the correct formatting.
00:10:00.800
We will also have to ensure we handle the last group correctly.
00:10:10.960
We always print the previous group, so once the iteration is done, we need to ensure there are no lingering values in the temporary variables.
00:10:41.840
If previous_index is equal to last_index, this is enough. Otherwise, we need to print the more complicated version.
00:11:03.680
Okay, let's try running this. All looks good; commit and push!
00:11:40.000
Now, any observations? We just spent some time on a piece of code that looks like this, and I've tried ChatGPT to generate similar code, which often results in very similar specifications.
00:12:02.000
However, I am quite unhappy with how this code looks. After writing it together, I've already forgotten the numerous problems we encountered.
00:12:32.000
If we consider this code a bit more critically, we could evaluate its problems without changing it. We could say it has high cognitive complexity and is, indeed, ugly.
00:12:49.360
When we talk about functional programming, we often think about how it helps us write cleaner, more understandable code by avoiding mutations and state.
00:13:14.000
Imagine just having a fritto misto like deep-fried fish for lunch and then trying to digest all this code.
00:13:24.000
This demonstrates how much brain power is consumed by intricacies in imperative code. We can approach it differently by transforming our data.
00:14:08.000
So, let’s talk about the vital principle of functional programming and how it focuses on data transformation. Instead of printing while coding logic, we can separate these two concerns.
00:14:55.200
Everyone has written code that resembles the imperative version— it's practical, but we often need to represent logic for future understanding.
00:15:18.000
Thus, discussing the data transformation approach allows us to consider how we can use it to create intuitive logic instead.
00:15:44.000
Now, let’s implement a clear data structure that can address our tasks directly. This way, we will handle how we would approach printing, keeping track of elements and values.
00:16:30.000
We create pairs of numbers and indices; this way, transformation comes first. Our issue of needing to print can then happen on a separate method.
00:17:17.300
I will use each_with_index for my original list and establishes groups using functional principles.
00:17:50.000
Using a tuple here will help manage the transformation, emphasizing what we are trying to accomplish with greater clarity.
00:18:19.000
Now that we've established this pairing concept, let’s focus on grouping based on previous numbers and handle necessary conditions.
00:19:03.000
If we maintain clarity so that the data transformation aspect acts independently from the output-dependent logic then it will simplify change management in future revisions.
00:19:40.000
It's critical we focus on how to make sure functionality isn't overlooked due to lack of cleanliness in code.
00:20:00.000
After restructuring the logical partition, we can acknowledge that the requirements regularly change and updating the transformation aspect can be done rapidly.
00:20:32.000
To summarize, recognizing how functional programming frameworks can assist us in not just clarity, but efficiency in translation to practical implementations becomes a distinct advantage.
00:21:05.000
In five minutes, let’s touch briefly on how we can understand clearer programming paradigms through conversation and integrated frameworks.
00:21:45.000
The goal is to use functional methods rather than imperative to enhance understanding.
00:22:10.000
Prompt transformation will help deepen both individual comprehension as well as collaborative processes.
00:23:00.000
By adhering to these conversion aspects, we can leverage distinct programming advantages that functional programming provides.
00:24:00.000
If we consciously re-examine our inquiries in development, through every iteration and prompt, we reach more fluid, flexible, and robust foundations.
00:25:00.000
Every step we take towards functional principles affords us incredible avenues for growth and understanding. It’s this machine of thought that can elevate our development with elegant solutions.
00:26:00.000
Let’s keep discussing how implementation through conversation and logic can be assisted by shared practices and clean structures.
00:27:20.000
When working with structures that evolve, it’s crucial to be able to denote patterns to facilitate clear epochs in code writing.
00:29:00.000
Thanks for participating; I hope these concepts offer you guidance in navigating your coding environment and extracting value from logical structures.
00:31:00.000
Let's transition to some live demos, culminating in a Q&A.
00:32:00.000
By allowing time for inquiry, we can explore even more dimensions of our practice.
00:33:00.000
Thanks for your contributions and attention throughout the discussion!