News for hackers. Stuff that matters.
Re:Functional programming is not popular because it is weird... by magicalhippo on Tuesday September 14, 2021 @09:29AM (#28524473)
> I can refactor without any fear of side effects.

Can you? Like say you changed you sum() function to only sum every other element, because for the code you're working on right now that made sense. Well now you've screwed up the other places which relied on sum() summing all the elements.

Dumb example because you'd know better, but surely you can still shoot your foot off like that with FP?

And yeah I know that's not the side effects you were talking about, but when I'm changing my OOP stuff, that's the kind of side effect I'm most worried about.

I've never really used a proper functional language though, so it's certainly possible I'm unenlightened.

Re:Functional programming is not popular because it is weird... by cardanome on Tuesday September 14, 2021 @10:07AM (#28525039)
> Can you? Like say you changed you sum() function to only sum every other element, because for the code you're working on right now that made sense. Well now you've screwed up the other places which relied on sum() summing all the elements.

I would not change sum but just filter out every other element and feed that new list to the sum function. (If you need it often, write a new helper.)

Your sum function should not decide which elements should or should not be added, that is the callers job. It doesn't even have the context to decide on that.

So yes, I would have the guarantee that nothing would break because I did not change sum in the first place.

In practice you probably wouldn't even start with that sum function but simply implement a function that takes two numbers and adds them together. Then the caller can use higher order function like fold and filter to do whatever it needs.

(Of course we assume it is not literally adding two numbers but some complicated logic, otherwise don't even write a helper for it, just sum your stuff when you need it.)

And yes, you can still have logic bugs in functional programming languages and it can't really protect yourself from that when refactoring but I wanted to note how keeping your design simple and having easy to understand composable functions can help avoid bugs.

Re:Functional programming is not popular because it is weird... by magicalhippo on Tuesday September 14, 2021 @11:02AM (#28525917)
> I would not change sum but just filter out every other element and feed that new list to the sum function.

Of course, and I would do the same in my imperative program. A dumb example like I said.

> Then the caller can use higher order function like fold and filter to do whatever it needs.

Right but then at some point you have a chain of ten of these calls, and you have it _all over_, and so you figure hmm lets make a separate function out of that, code duplication is bad after all.

And then you find your new function has a bug and you need to change it... Will all the users of this new function be OK with that bugfix?

If you don't wrap up these chains into new functions, how do find all the places you need to change once you need to make that bugfix?

> having easy to understand composable functions can help avoid bugs

Sure this I get, which is why my imperative code also contains lots of "do one thing" methods that is used as Lego bricks. And I use a fair bit of functional-ish code, ala LINQ, where it makes sense.

I wish I had discovered functional programming at an earlier stage, where I had more time to experiment. I think it would be very informative to make two non-trivial feature-equal programs in either style so I could compare.

Re:Functional programming is not popular because it is weird... by ItsMonkk on Tuesday September 14, 2021 @07:59PM (#28533238)
One thing I want to point out is that when I first read "do one thing", I thought I knew what they were saying and I didn't. It took a long time for me to finally grasp that message.

One of the ways I finally learned that was after learning async/await in C#. Every beginner to async methods dread in fear once they realize the "zombification" of the Task<T> return type, where if you call an async function 6 layers deep into your program you need to change the return type all the way up the stack. Almost always now I call the async function at the very top layer. If I need some value or list I compute that list or value and return that all the way up then make the async call at the top based on it.

I learned to split my functions into two types, pure functions and impure functions. Async functions are an example of an impure function. The only thing those functions are allowed to do is their impure thing. Make a web call, push a value into a database, whatever. The pure functions are where you actually do your computations and transformations.

If you have a pure function that has a bug and you need to change it, because it's a pure function it is inherently testable. Just run it and see. If you're not sure, it's trivial to create a new function with the bugfix and only call that function from the places that you are sure of. But then try to make sure.

Re:Functional programming is not popular because it is weird... by matt_kantor on Tuesday September 14, 2021 @09:58AM (#28524900)
> I know that's not the side effects you were talking about, but when I'm changing my OOP stuff, that's the kind of side effect I'm most worried about.

That's not a "side effect"[1] at all. It's a logical bug in the implementation that only affects the function's return value. You absolutely still have to worry about those sorts of bugs in FP, which is why you still need tests or a fancy enough type system to prove the bug cannot happen (for your example that is unlikely to be practical).

"Without any fear of side effects" doesn't mean you don't have to fear anything at all, but it's one less thing to worry about.

[1]: https://en.wikipedia.org/wiki/Side_effect_(computer_science)

Re:Functional programming is not popular because it is weird... by magicalhippo on Tuesday September 14, 2021 @10:36AM (#28525481)
> That's not a "side effect"[1] at all.

Yes, like I said. Point is, in my imperative OOP code, I'm relatively seldom worried about actual side effects, and more worried about introducing bugs due to me not fully grasping all the interactions of the code I'm changing.

Did someone somewhere make an assumption about how this code works (sums all numbers), and am I breaking that assumption when I'm making this change (summing every other number)?

Re:Functional programming is not popular because it is weird... by Tainnor on Tuesday September 14, 2021 @11:01AM (#28525900)
> I'm relatively seldom worried about actual side effects

I'll give you one concrete example: In a number of ORMs, I have no idea when database calls actually happen and this can lead to a) subtle logic bugs (inconsistent state), or b) bad performance (N+1 queries).

I've had such problems both with Ruby's Active Record and Hibernate, two of the most popular ORMs. I've even deployed code that had subtle bugs, even though I wrote tests, because while my tests verified that the correct state of the object was written to the DB, the updated state was not reflected in the JSON response object. I'm sure similar things happen in other frameworks as well.

A PFP can prevent that sort of craziness from happening.

Re:Functional programming is not popular because it is weird... by magicalhippo on Tuesday September 14, 2021 @11:53AM (#28526655)
Fair point, though I'd say such ORMs are broken by design by the sound of things.
Re:Functional programming is not popular because it is weird... by Tainnor on Tuesday September 14, 2021 @11:57AM (#28526706)
I agree that Hibernate in particular is broken by design, but it is what it is...
Re:Functional programming is not popular because it is weird... by Tainnor on Tuesday September 14, 2021 @09:59AM (#28524905)
Confidence in a program's behaviour is not an all-or-nothing proposition. You can statically verify certain properties of your program (through immutability, type systems, linters etc.) without having to write a full formal proof of your program's entire behaviour, and you can gain more confidence in the entire program working correctly.

In the example you just gave (summing over a list of numbers), in almost all programming languages you'd resort to runtime verification instead, i.e. tests, just because it's so much more practical. But if you have a PFP language, you still have the confidence that the behaviour of the inputs and outputs is the only thing you have to test, since the function cannot do anything else.* Even in a non-pure FP language, you know that it cannot mutate other variables, although it might have side effects.

* Ok, it might loop forever or crash, but that's comparatively rare.