@madlep

10:28 It’s not so much that functional “gets a bit weird”, it’s more that this code doesn’t really make use of the language tools available. You almost never want to manually manage recursion when you’re iterating over a collection when you’re doing FP, and instead would want to use higher order `map` / `reduce`  etc functions provided by the language or a library. I’m not an expert on C#, but from what I understand `Select()` and `Aggregate()` function call would do the trick here.

@PatrickDeWind

This is a better explanation than most. I very much appreciate that it doesn't dim procedural programming to make OOP look better like most videos I've seen. 

Though "simple" isn't always a good word for procedural programming given that things like Linux are written that way.

@sawilliams

Most programs I have worked on uses a combination of all 3

@nonya69

1:06 the moment you're using the new keyword, you are dealing with object oriented programming - not strictly procedural.

@fungibungi5568

clear and straightforward  ❤

@Psi141

Underrated af

@Latticx

Your visuals are nice, good explanations!

@nasccped

Awesome video dude! ❤

@DavidSosa-n8u

Love these vids, idk how I stumped upon your account but it’s very helpful

@randomgamevideos241

i agree with you, normally i try to avoid recursion unless it is the only solution i see, i prefer loops over recursions,  i can definitely say my code  is a mix of all three styles ( when the style is needed ).

@DnBComplex

Amazing video.

@xzazen

fyi the function PrintNumbers(int i, int max) is not strictly a pure function (it does not give the same output for the same set of inputs) because you have a side-effect - Console.WriteLine() is IO bound and could cause an exception, in C# you probably would have to roll your own IO monad (essentially a container) and return the IO(result) or IO(error) to make it a pure function. 
The benefit is that you can remove stateful exception handling which is outside of the function and have "railway-oriented" exception handling.

@SchoolyB

Procedural FTW

@M_O-9081

man 12:00 is the best :)

@gJonii

Your fp example was oddly made in a way that seems harder to read than the default example everyone gives, where calculatetotal would take two parameters, list of numbers and total. You'd slice the first element off the list, add it to total, and do it like that.

There's also really no point in using recursion imo, the reason it's popular is because Haskell etc have first-class support for it. Language you used here doesn't have that(was it C#? I didn't recognize it). However, that language likely has built-in reduce-method. Universality of these operations is a big selling point of FP, and by specifically avoiding showcasing it, you're seemingly purposefully trying to make FP seem worse than it is, by doing the example code in bad style, insisting on recursion when it's not really needed, and insisting on not using the universal patterns when universality of those patterns is a big selling point of the language.

Also, the whole createoutput would've also been able to use the exact same reduce-operator, further showcasing this "simple universal tools serve you often quite well"

@Nellak2011

--------- My Procedural style: 4 LOC, with mutation and straightforward logic
const main = () => {
    const nums = std.getInput("enter array of numbers") // or however it is done
    let sum = 0
    for (const num of nums) { sum  += num }
    console.log(`Total: ${sum}\nAverage: ${sum / nums.length}`)
}

--------- My Functional style: 4 LOC, with no mutations and concise logic
const average = nums => nums.reduce((acc, el) => {sum: acc.sum + el, avg: (acc.sum + el)/nums.length}, {sum: 0, avg: 0})
const display = ({sum, avg}) => console.log(`Total: ${total}\nAverage: ${average}`)
const main = () => {
   const nums = std.getInput("enter array of numbers") // or however it is done
   display(average(nums))
}

--------- My OOP style (I never use it so it may have syntax issues):16 LOC, with mutations and convoluted logic
class displayNumber {
    let sum, average = 0
    constructor(nums) {
       let newSum = 0
       for (const num of nums) { newSum  += num }
       
       this.sum = newSum
       this.average = newSum / nums.length
    }
    display = () => console.log(`Total: ${this.sum}\nAverage: ${this.average}`)
}

const main = () => {
    const nums = std.getInput("enter array of numbers") // or however it is done??
    let displayNumber = new displayNumber(nums)
    displayNumber.display()
}
----------

FP > Procedural > OOP

@yes5421

I’m a freshman going into uni and I’ve studied for the Java oracle certification a couple years ago, so I am familiar with the concepts theoretically however never implemented them into an actual project. What project should I do with Java to be familiar and gain my memory back of Java as I am a bit rusty but remember concepts and am familiar with OOPS programming.

@paulzupan3732

The object-oriented example is not very good. I can't believe that you coupled the notion of summing numbers to the number data itself. I would have created a NumberSumCalculator class which takes in a NumberArray along with an implementation of a NumberAdder interface. What if you wanted different strategies for adding numbers together? After all, there are many different ways to combine two numbers, and you want your code to be flexible, maintainable, and readable. You'd probably also want a NumberAverageCalculator interface, since there are multiple ways to find the average of a list of numbers.
Not to mention that you coupled creating the output with the number data as well. I think the best solution would be a NumberDataOutputWriter class which takes in some sort of Writer interface (you might not want to print it to standard out, you could print to a file, write to a string, et cetera), as well as an object that implements both the NumberSumCalculator and NumberAverageCalculator interfaces so that you can get at that data.
Overall, your solution is not scalable, readable, maintainable, flexible, or robust. 0/10.

(edit) I’m sorry if this sounded too serious, I’m just kidding. I really enjoyed the video.

@nartoomeon9378

hmm... 6:35 there's something wrong here, because functional programming don't require immutable vars. Almost all functional lang-s are statically typed, but that doesn't mean they have immutable vars. The key feature is pure functions , higher order functions and possibly, monads. Pure function—is a function without side effects, in other words, same input—same output. Purity gives a more readable code, where user clearly see all possible outputs of a function. In the first example 6:58 we have a mutable variable, but it exist in separate name scope, so the function is pure! it doesnt change anything from outer scope.

@Jediahgames

Why the hell would you use Stringbuilder for that?