>Objects DO NOT HAVE to be mutable. As I have _repeatedly_ stated, you are building a straw-man. That is, you are creating your _own_ definition of OOP (objects and to some degree FP) and using it to support your argument about modularity. Refer to the "Specialized Objects" section of:
https://en.wikipedia.org/wiki/Object_(computer_science)I don't know how to get it through to you what I'm talking about. You fail to understand repeatedly.
In procedural programming YOU CAN MAKE values immutable. Mutability is not a requirement. You don't even have to have procedures in procedural programming. Your functions can be singular expressions of one procedure, equivalent to a functional function. Additionally you can attach all your first class functions in lists, dictionaries or namespaces which makes it equivalent to an OBJECT.
So why even have the words "procedural program" when it has utterly no requirement and can mutate to fit any form of programming? Above I describe using procedural programming to fit OOP and to fit functional programming. It's THE SAME STORY for OOP.
OOP can be used to imitate what we traditionally call functional programming and even procedural programming. Thus everything has an isomorphism.
THEREFORE: When you compare procedural programming and functional programming you HAVE to COMPARE the variant features. PROCEDURAL PROGRAMMING has procedures, while functional programs have expressions.
What does this mean with OOP and all other forms of PROGRAMMING? Mutability. Technically YOU DON'T HAVE TO use mutability, but it's pretty pointless if you DON'T and you can pretty much call your programming style functional if you don't. Mutability is one of THE CORE FEATURES that separates it from other forms of programming. The reason why is because having every single method in an OOP program be a method that mutates its own state leads to horrible design so people usually use it with a combination of both stateless functions and mutating methods. The issue is Almost NOBODY realizes this.
The logic is inescapable: THE CORE DIFFERENTIATOR IS MUTABILITY.
>Crystal clear. Even the single sentence in which you are basing this entire waste-of-time argument on:
No man. It's my time that you are wasting here.
>in no way supports your conclusion with any rational reading. A "feature" of objects is procedures that can "often" modify fields. It takes some serious gymnastics to read that as "mutability is a required property of OOP". I have yet to find a resource that supports your definition of OOP (and I'm looking!).
Read my explanation above. Procedural programming, for loops and while loops DO NOT REQUIRE Muteable values. Yet try to write a for loop without a mutable value see how far you can go in writing a closed function like that without IO.
You won't find anything on the topic JUST LIKE you won't find anything talking about methods and functions being ONLY semantically equivalent. If you do find some idiot blogger who actually supports this claim without mentioning immutability then he likely doesn't know what he's talking about.
>Being isomorphic to a functional program doesn't mean the program isn't OOP. From the same page above:
It's LITERALLY equivalent ACCORDING TO YOU. You called it only a SEMANTIC DIFFERENCE. And I said the SEMANTIC DIFFERENCE ONLY EXISTS if the values are immutable but to you they ARE ALL THE SAME.
>OOP is an approach. It is the _approach_ one takes when designing a system that determines whether or not that system should be understood as OOP. If the approach uses the "Features" of OOP (listed on the wiki), then the system is OOP.
The approach according to you is basically the SAME THING as everything else. I mean verb1(noun1) verb2(noun2) is the same damn thing as noun2.verb2() and noun1.verb1(). There is literally NO DIFFERENCE from this APPROACH to any other APPROACH according to your misguided logic.
>Your entrenchment on this topic is astounding. Again, I don't have to be wrong about `noun.verb` vs `verb(noun)` for your conclusions about how we abstract software to stand. My intention wasn't to disagree with you, it was simply to point out that all paradigms suffer from modularity problems as they relate to functions acting on state.
What's astounding is your lack of understanding. You're intentions don't matter, the topic that I am pointing out is that you are completely and utterly WRONG. You being RIGHT has incredibly absurd consequences.
>No, but we have. And I've clearly demonstrated that same problem presents itself. That's how we got here. You needed to change the constraints of the problem (that objects _must_ mutate) in order to make a coherent argument (the straw-man). That got us to this separate argument about the definition of OOP (moved goal posts). Here is the moment above when you played your hand (and lost the argument):
You've clearly demonstrated a LACK of understanding. AGAIN, what you see as an unnecessary constraint is NECESSARY.
Let me use a more clear analogy. How do you compare the difference between a MAN and a WOMAN? Why you compare the color of their hair, eyes and the amount of fingers they have. Do you really? Or is it a complete act of stupidity to compare the properties THAT ARE NOT EXCLUSIVE TO EITHER?
Let me use a more clear analogy. How do you compare the difference between OOP and FP_______? Why you compare how OOP can be immuteable and how FP can be immutable, you compare how methods and functions can return values... Do you really? Or is it a complete act of stupidity to compare the properties THAT ARE NOT EXCLUSIVE TO EITHER?
Read the above to paragraphs. This is what your entire illogical argument looks like. The only person who lost is you.
>Instead of doubling down and starting this dumper-fire of a discussion, you could have simply responded with something like:
>"That's correct. Which makes it even more pragmatic that we strive to abstract the server model into code, because the problems with modularity/distribution cannot be avoided in _any_ programming paradigm. That is, the level of abstraction where we WRITE code is not the same, or appropriate level of abstraction used to modularize/distribute code. If, instead of explicitly hard-coding the boundaries of communication into a system, we could abstract the boundaries into compilation as a matter of configuration, it would allow for any arbitrary level of modularization/distrubution without the need to change the source code itself".
The above is completely wrong. The problems with modularity AND distribution CAN be avoided but it comes at a cost. You're just too blind to see it. Modularity is actually a very clear concept that is quantifiable.
If every single possible primitive in your program was a immutable module THAT is the MAXIMUM modularity your program can afford. If your program has 5 primitives then 5 is the maximum amount of modules you can have. At a modularity of 5 modules can be composed into higher level modules of your choosing building a pyramid of modules where each level has less modularity then the level below it.
IF your entire program was one single MODULE that could not be reused that is the LOWEST possible level of modularity your program can achieve. In short 1 is the lowest number of modules a program can have.
The only thing we are doing with modularity is picking arbitrary walls and grouping arbitrary amounts of primitives. It's a multidimensional gradient. In a program with ABC primitives you have this many possible groupings (A)(B)(C), (AB)(C), (AC)(B), (BC)(A), (ABC). So 5 possible ways with 3-1 groupings.
What FP does is eliminate arbitrary walls by eliminating mutations.
F(x) = (x + 1 + 2) is easily factored into
F(x) = G(H(X))
Where G(X) = x + 1 and H(X) = x + 2
whereas
Object F {
int val
H(){val += 1}
G(){val += 2}
}
cannot be decomposed.
Both programs have two primitive concepts: the addition of 1 and the addition of 2. That means it has a maximum modularity of 2 modules. However only function F can be decomposed into two modules without changing the nature/signature/interface of F itself. Object F cannot be decomposed without changing what F is.
So in short if your FP program was modularized via (HG) it can easily be broken down to (H)(G) in which case modules can be recomposed however you like... The OOP version cannot be decomposed it is (HG) forever because mutability ties both methods to state.
The problem that exists at the infrastructure level is that MUTABILITY must exist. It's called databases. No server is an F(X) but rather it is a method H or G that is coupled with val (the database).
>The above makes a great point (your point), and has actually served as inspiration for my latest side-project. So kudos to you for that.
You mean taking my idea of writing code or a framework that compiles into servers? Having decorators on functions that specify what part of the infrastructure a function is located in? Composing two functions in code and having that compile into two servers communicating?
It's sort of been done. See RPC frameworks like thrift and gRPC. If you use the same language for all your servers with something like thrift as the connector between all the servers then you achieve roughly the same effect as a language that compiles into servers. The only difference is that your code won't influence the infrastructure, RPC only removes the walls between servers.