4 ms·
I would state it slightly differently: Closures are for FP what objects are for OOP. When you create a closure you are in fact creating an instance of a Functi
by galaxyLogic 4y ago
I would state it slightly differently: Closures are for FP what objects are for OOP.
When you create a closure you are in fact creating an instance of a Function. In FP functions are "first class citizens", therefore it must be easy to create new (instances of) Functions. In FP you can do that by calling some code that creates a closure, not only by providing new source-code for a new Function-definition.
Note Function Definition is not a function.
What can you do with a closure? You can call it. What can you do with an object? You can not call it. You can only call one of its methods.
- Kamq 4y agoI believe the equivalent here means formally equivalent. But, really, you can use each of them to emulate the other. If you want to emulate objects with functions, you just have your function return a bag of closures over the state. Your first function is effectively a constructor. To emulate functions with objects, you just create a single method class. Or do something real fancy with Scala's apply and/or C++'s ClassName::operator()() so it looks like a normal call, if you are so inclined.
- galaxyLogic 4y ago> To emulate functions with objects, you just create a single method class. You still can not "call the object" you can only call its single method. But I see what you are saying I think. You can accomplish similar things with closures and objects. For them to be "equivalent" I think should mean there is nothing you can do with closures that you can not do with objects, and vise versa. I don't know if that is the case, is it?
- Kamq 4y agoThat's what the term "formally equivalent" means here. You can do whatever you can do with one of them, with the other one. Actors as well.
- galaxyLogic 4y agoRight but then we get back to the Turing completeness. You can do with any Turing machine whatever you can do with any other Turing machine. You just have to do it a little differently. I'm not sure if https://wiki.c2.com/?ClosuresAndObjectsAreEquivalent https://wiki.c2.com/?ClosuresAndObjectsAreEquivalent gives us a constructive proof however. There is a poll in there. Let's vote if this is so, or not. :-) Interesting discussion however in there.
- Kamq 4y ago> You just have to do it a little differently. No, my point is that you don't have to do it any differently (unless you mean the machine does different things, in which case that really depends on your compiler). The note here is that depending on your language, syntax may make the emulation difficult/cumbersome. If you have classes, you can emulate closures by creating a class that takes the state to close over as constructor arguments, and executes the body of the function as a single method. If you have closures, you can emulate objects by taking state and returning a bag of functions, which emulate methods. If you need polymorphism, you can call the "parent" closure and just replace the closures in the resulting bag that you need to override. You can use these to solve problems without altering your approach (though, once again, syntax may be burdensome depending on the language).
- galaxyLogic 4y ago> you don't have to do it any differently The code you write must be different, depending on if you write closures or objects. The way you call upon closures vs. objects also requires different syntax. You must write different code, you must "do it differently". But I agree they do pretty much a similar thing. You however must write different code depending on which approach you choose, and depending on your language there are pros and cons to each.
- Kamq 4y ago> The way you call upon closures vs. objects also requires different syntax. The syntax isn't what I'm talking about. I'm talking about the patterns. > You however must write different code depending on which approach you choose Only code that is different in syntax, not code that is conceptually different.
- inopinatus 4y ago> What can you do with a closure? You can call it. What can you do with an object? You can not call it. You can only call one of its methods. These are congruent, assuming an Alan Kay-ish definition of OOP (as per Smalltalk and Ruby et al). A collaborator object does not call another object's methods, but rather sends it a message. Consequently, there is only one logical interface. This is one reason that Erlang is sometimes described as one of the most OOP languages, despite possessing distinctly functional fundamentals.
- samatman 4y ago> What can you do with a closure? You can call it. What can you do with an object? You can not call it. It's a good thing Lua doesn't have objects! Because in Lua, you can call a table if it has a `__call` metamethod, this is valid Lua: (setmetatable({a = 5}, {__call = function(t) return t.a end}))() which returns 5.