These are chat archives for ramda/ramda

May 2019
May 02 10:07

Hi, I've got a question about writing pure functions. A problem I keep running into is I keep accidentally writing impure functions when attempting FP. For example, using reduce I find that the reducer function I pass in, invokes an external function (ie its not one of the parameters passed to it by reduce). This external function makes up part of the closure, but doing so make it impure, or does it?

I found an article that explains FP and if you take a look at the code at the end (the solution to the imperative code), you can see what I mean; getLastUpdatedAtForSuppliers invokes another function getDurationSinceLastUpdate. getDurationSinceLastUpdate is an external function, but in the closure. It is not passed in as a parameter to getLastUpdatedAtForSuppliers. So how does this qualify in being true functional code. (I'm not saying it isn't, I just want to understand what you can and can't do, and why this particular example is ok). Thanks

May 02 10:44
Functional code is any code that treats functions like values, so any code that even features callbacks is functional.
In the future you may learn about the IO and Task (aka Future) monads, but idiomatic FP is more a set of guidelines ("avoid side effects") than a set of rules ("never have side effects") and the writer probably didn't want to complicate things by introducing the IO monad to the table.
Rakesh Pai
May 02 11:14

I'd still call it functional, in the sense that it is side-effect free. Sure, you could argue that it's using code from outside its scope, and that might be a smell, depending on how you look at it. I think it's fine in this case, but I tend to be very pragmatic about such things. If you don't like that, you could always pass it in as an argument.

const createMapStateToProps = fn => ({ items }) => ({ ...fn(items) });
export default createMapStateToProps(getLastUpdatedAtForSuppliers);

This indirection, if you want to call it that, doesn't add much though IMHO, but its always contextual. It might be super-useful in some cases. So, it's a good thing to know and keep in your bag of tricks, but sometimes being religious about it is sometimes more trouble than it's worth. The answer is always 'it depends' :D

May 02 12:07
Ok great thanks @1point7point4 and @rakeshpai . I'm glad you both said that because I like the idea of being practical about these things rather than being dogmatic. I've hit this problem a few times, and let it go as a todo item in the future. But I also like your proposed solution @rakeshpai, because it shows me how to pass in the externally dependency which I was trying to do with the spread operator, but not quite getting it right, so cheers.
Rakesh Pai
May 02 12:29
(y) no problem.
May 02 14:26
I've realised that I've spent the last few days wasting my time trying to solve a particular problem (doing various different exercises, asking you guys questions) and it turns out that all I needed was a function that was already defined in Ramda: indexBy. Arghh
Fabien Bourgeois
May 02 15:21
I guess it's common, Ramda has extenstive API and it's not easy to know all functions :)