"What Alan Kay Got Wrong About Objects" - <AUTHOR> https://blog.metaobject.com/2019/11/what-alan-kay-got-wrong-about-objects.html <comment><USER2> Kay was at least as inspired by _biological_ processes -- bacteria transmitting chemical signals to one another, for instance -- as he was by computer networks.

I think the big thing that Kay missed was asynchronicity. What Kay was thinking of when he coined the term "object oriented" \-- rather than C++ -- was a sort of synchronous actor model in which the actor would always wait for a response after sending a message. This maps nicely onto function calls, but considerably more power can be had by letting the actor optionally continue doing stuff while awaiting a response. Bacteria continue to metabolize after sending chemical signals to their brethren after all!

As I've seen it said, Erlang is Smalltalk done right.

<comment><USER3> What's interesting is that there's no "destination" for these chemical signals, they're just emitted into the void. There's no sense of sender/receiver, which has some correspondence to the blackboard model[1,2].

1\. [https://en.wikipedia.org/wiki/Blackboard_system](https://en.wikipedia.org/wiki/Blackboard_system) 2\. [https://en.wikipedia.org/wiki/Blackboard_(design_pattern)](https://en.wikipedia.org/wiki/Blackboard_\(design_pattern\))

<comment><USER4> Yeah, exactly. The synchronous, one-to-one method calls of C++ or Java bare basically no resemblance at all to bacteria chemical signals. The former are essentially functions which dispatch on the first parameter.

The blackboard model isn't quite accurate though. Chemical signals have spatial locality, propagation delay, and half-lives. An asynchronous, peer-to- peer mesh network of actors would be a closer approximation to the bacterial signal model.

<comment><USER3> Something like a "place-based" tuple space would be more accurate, yeah.

</comment></comment></comment></comment><comment><USER5> While it's always dangerous to criticize a computer legend, I would add one more thing that I believe Alan Kay "got wrong about objects": objects are extremely bad at representing most types of problems in business software.

I mean this in regards to the "true" message-passing type of actor objects, and not OO as it came to be post-C++ and Java. The reason being is that actors 1) fundamentally involve themselves with state and time, and 2) connect subject and recipient together directly.

In relation to 1), most business problems involve _data_ processing, and the thing about data is it is immutable. It's essentially a solid state type of activity, and bears no resemblance to the organic, messy world of biology where things are changing. For problems like these, you really want to avoid state in your program, and persist state after data transformation in an actual database. Concepts like stateful actor supervision hierarchies, and what to do with clearing mailbox state when something goes wrong are fundamentally complex. Those concepts are also broadly unnecessary (and arguably harmful) for most request/response or async pub-sub type software. I can't count the amount of time I've wasted redoing systems on an actor model to be a simple "stateless" request model. On all of those occasions, the model that didn't persist state in-app was more reliable, easier to understand, less code, and more maintainable.

With respect to 2), actors basically violate all concepts of dependency injection. Actors need to know exactly where they're going (or you can add a proxy, and now your state graph is even more complicated), and even with message passing, program flow is dependent upon _time_ and the order in which a program is run. This is a large step backwards in my opinion.

I feel that languages like Elixir that pride themselves on stateless, immutable functions, have a deep contradiction internally embracing the actor model, because it is none of those things. Sadly, I also predict that this generation of Elixir programmers will learn the lessons of the Waldo paper the hard way: you can't just throw an actor model over the network and have it work great. (I think it's especially interesting that most of the success stories around modern day actor systems involve problems that can withstand data loss: telephones, IOT, content, media streaming, games, etc.)

<comment><USER6> > most business problems involve _data_ processing

To quote two other computer legends, Fred Brooks and Linus Torvalds are right: data not behavior is the more crucial part of programming.

Actors focus on the behavior, whereas the data is the part that is _really_ important.

What `git log` does isn't all that important relative to how the git object model is structured, as the latter dictates the former.

> I can't count the amount of time I've wasted redoing systems on an actor > model to be a simple "stateless" request model.

So much this. So often people forget that "it's just code". It can run on a toaster, or a mainframe, or a VPS, or a Docker container, or a Lambda function. The lion's share of code should be structured as input => output in the most straightforward way possible.

<comment><USER7> «What if "data" is a really bad idea?» — Alan Kay, [https://news.ycombinator.com/item?id=11945722](https://news.ycombinator.com/item?id=11945722)

<comment><USER6> Ah, it would seem that is in fact an underlying point of disagreement.

</comment></comment></comment></comment><comment><USER8> Kay was into discrete-event simulation. There's a nice example of that on an Alto, a little hospital queuing simulation, in "Personal Dynamic Media". That concept comes from Simula-67, a variant of Algol-60 used for simulation.

It turns out that discrete-event simulation isn't used much, and that async model isn't all that useful for other things. If you've never seen a discrete- event simulation, here are some in Flash, of Disney ride line management.[1]

[1] [https://www.themagical.nl/simulations](https://www.themagical.nl/simulations)

<comment><USER9> You maybe right about discrete event simulation, having created one for my academic research years ago, I had the feeling it wasn't as useful (there are so many things you might tune to make it spit out what you want), but the same model is fun for making random simulations (games).

</comment></comment><comment><USER10> Actor-based programming really interests me. The concepts behind erlang and smalltalk seem to be the closest to an ideal model for the amount of distributed computing power we have today.

It seems like we should be able to formalize a generic meta-programming language that describes discrete components. 'actors' would be concepts close to functions that receive inputs and return outputs, everything inside would be generally considered synchronous. These actors speak to other actors via addresses. That idea was all outlined by alan kay. Furthermore, these actors can live anywhere. They can be running on a single CPU, live across multiple threads, cores, processors. Ideally you just throw more processors or remove processors from the mix and the system distributes.

Where the rubber meets the road is all the communication mediums. The lowest abstraction is your actor return address is a stack pointer. The highest is the return address is another system (what we currently do with RESTful communications).

Once all the inter-actor controls are sorted out, there would need to be a system of dynamic resource distribution. The profiler/scheduler should be able to identify things like \- this actor is handling 85% of traffic, distribute the actor to 6 cores \- the cost of the route from a core to a core on the same processor is X, the cost of the route to a core across a network is Y \- distribute actors that have the most cross communication as closely as possible \- payload size would also need to come into account

on top of that, tooling that identifies workload-specific needs could also be identified: \- this set of actors should be considered critical and available on % processors \- take into account things like inter-region availability.

A lot of these concepts have already been hashed out and you notice the parallels to things like network architecture. Ideally in the end a 'system' would simply be a pool of usable resources e.g. SYSTEM1: my laptop, an AWS server, my phone, my watch. Computation work is unevenly distributed to the system based on route costs, computational power...even storage capabilities and peripheral access (printers, cameras, etc). A new actor would get initialized in the network and it could be scheduled on your desktop or your tablet. Eventually your system would just become an amorphous workload.

My desktop might begin distributing subsets of things that currently run locally to my AWS server because it's closer to the public API i'm accessing. If actors were generic enough they might be identified and made a reusable pool for multiple applications.

Sorry for the stream of consciousness.

<comment><USER11> > Once all the inter-actor controls are sorted out, there would need to be a > system of dynamic resource distribution. The profiler/scheduler should be > able to identify things like - this actor is handling 85% of traffic, > distribute the actor to 6 cores - the cost of the route from a core to a > core on the same processor is X, the cost of the route to a core across a > network is Y - distribute actors that have the most cross communication as > closely as possible - payload size would also need to come into account

It's not that simple. Objects that can assume locality are written differently than those that can't. The optimize for fate sharing, low latency, etc. If you have just have a mesh of floating objects, you must remove all of those optimizations.

</comment></comment><comment><USER12> The title of this post is _very unfair_ to Alan, who has made important contributions. For example the SmallTalk browser was extremely innovative leading to modern Integrated Development Environments that have taken over software development. Also, SmallTalk was the first to use Simula class hierarchies for graphics, which are now used everywhere.

Objects as conceived in Simula-67 are _not_ universal primitives of digital computation. However this was remedied in 1972 with the invention of Actors.

 _It is very important that Actors rigorously formalize the rules for digital computation._ See the following:

        https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3418003

        https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3459566

In this way, computer systems _themselves_ can participate in discourse with humans about the nature of digital computation and associated software systems.

Every important scientist (including Einstein) made numerous errors. Fermi received the 1938 Nobel prize [Fermi 1938] for the discovery of the _nonexistent_ elements "Ausonium" and "Hesperium", which were actually mixtures of barium, krypton and other elements. I have made quite a number of errors myself, although I am certainly _not_ of the caliber of Einstein or Fermi! It is important to find and rectify errors ASAP. In order to make progress, we _must_ make errors.

Reusable Scalable Intelligent Systems _cannot_ be implemented using the current common programming practice of stateless sever code + relational data base. See the following:

        https://papers.ssrn.com/abstract=3428114

<comment><AUTHOR> Hello Professor Hewitt,

Hmm...I don't quite understand your criticism, particularly as you yourself point out that "every important scientist (including Einstein) made numerous errors", and go on to describe some of those errors.

The fact that Alan is a towering figure who has contributed more to this field than I (and most people) can ever hope shouldn't mean that we cannot point out where we believe such an error was made, should it? That's not how science, even computer science, is supposed to work.

As a matter of fact, it seems even _more_ important in the case of such an influential figure.

Of course the article points out that it was (a) a "brilliant" (quote from the article) construction and (b) the fact that it was wrong wasn't really Alan's fault, because he didn't have any large computer networks to look at, so (c) using the same brilliant construction with up-to-date inputs gets you a better answer.

The claims you make about the impossibility of things that are clearly being done seem a bit strange.

</comment></comment><comment><USER11> Doesn't scaling network interfaces down to be used in local processes present all the same problems as scaling procedure interfaces up? You still have to be aware of which objects are remote and which are local.

<comment><USER12> Runtime system knows approximate latency to intended recipient Actor of a message, e.g., this core, nearby core, nearby chip on the package, nearby chip in the same server, nearby server in the same rack, nearby server in the same datacenter, another datacenter, another IoT, etc. However, Actors can dynamically move and so the answer can change over time.

<comment><USER11> Latency differences aren't just a difference in degree. They're a difference in kind. Some interactions have to be sufficiently fast or they shouldn't happen at all. A runtime that minimizes global latency guarantees isn't sufficient. You also need to guarantee that certain individual Actor interactions are sufficiently fast, which is only possible through colocation. You could add a colocation constraint to your Actor scheduler, but now you're pretty much back to where you started.

And latency is only one of the problems. Partial failure is another. It's often convenient for authors of colocated actors to assume fate sharing. If they can't, they have to handle a much wider set of failure modes.

<comment><USER12> Do you think that the "difference in kind" should be frozen in application source code?

I agree that latency needs to be carefully controlled. But the software engineering can be complex!

<comment><USER11> Often, yes. Parameterization adds complexity, so for interactions I _know_ must always be colocated, it makes sense to hard code the provisioning of a local actor.

<comment><USER12> Good luck finding all the places that various kinds of colocation have been hard-coded, e.g., same core, nearby core, same chip, same package, same rack, same datacenter, etc.

</comment></comment></comment></comment></comment></comment><comment><USER13> Interesting post OP. From reading your paper about storage combinators it seems to suggest that this has been used in the Wunderlist app.

It sounds quite promising in theory but more people would need to try it before we know how beneficial it is.

Would it be possible to open source the library or be able to read an actual code sample ?

Might help popularize it better than if this knowledge were in a paper.

<comment><AUTHOR> Thanks!

The paper actually talks a little about results: reports were of code size and productivity improvements in the 50% / 2x region.

I actually met one of the guys who had provided that written feedback a little later, and he told me that although he had written 2x, the actual results were more like 10x. The reason he wrote 2x was that he thought 10x would not be believable/believed. I have a feeling he is right about that ;-)

The libraries _are_ open source, at [https://github.com/mpw/MPWFoundation](https://github.com/mpw/MPWFoundation) (The lively project also has a version [https://lively- web.org](https://lively-web.org))

The Stores/Storage Combinator base implementation is in the Stores subproject, so [https://github.com/mpw/MPWFoundation/tree/master/Stores.subp...](https://github.com/mpw/MPWFoundation/tree/master/Stores.subproj)

There are quite a few more stores in Objective-Smalltalk ([http://objective.st](http://objective.st), [https://github.com/mpw/Objective-Smalltalk](https://github.com/mpw/Objective- Smalltalk)), which provides linguistic support for stores/storage combinators with Polymorphic Identifiers.

The Objective-Smalltalk project also has a number of example compositions, but I do need more sample code.

</comment></comment><comment><USER14> FWIW, in re: distributed Smalltalk, check out Croquet.

> Implemented in Squeak Smalltalk, Croquet supports communication, > collaboration, resource sharing, and synchronous computation among multiple > users. Applications created with the Croquet software development kit (SDK) > can be used to support highly scalable collaborative data visualization, > virtual learning and problem solving environments, 3D wikis, online gaming > environments (massively multiplayer online role-playing games (MMORPGs)), > and privately maintained or interconnected multiuser virtual environments.

> Since release of the Croquet SDK in 2007, the SDK has not been under active > development. All further development of the technology has occurred under > the Open Cobalt effort.

[https://en.wikipedia.org/wiki/Croquet_Project](https://en.wikipedia.org/wiki/Croquet_Project)

</comment><comment><USER11> > each Smalltalk object is a recursion on the entire possibilities of the > computer.

I've heard Kay say this a few times, but it's always seemed wrong. Self similarity is a powerful scaling mechanism, yes, but Smalltalk objects and computers aren't self-simlar. Computers are Turing complete. They can become any machine. That's what they're good for. Objects can't.

<comment><USER12> Objects as originally conceived in Simula left out concurrency, i.e., region of mutual exclusion of an Actor.

See the following: [https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3418003](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3418003)

<comment><USER11> I'm unsure what this has to do with my comment.

<comment><USER12> Simula originated the terminology "object", which was then adopted in later versions of SmallTalk. Objects differ in fundamental ways from Actors.

<comment><USER11> What does this have to do with Kay's claim that objects are "mini-computers"?

<comment><USER12> What is your precise definition of "object"?

<comment><USER11> I don't have a precise definition, but regardless which of the many candidate definitions you choose, none are "mini-computers". A computer, if that term is to mean anything at all, is Turing Complete. It's a machine that can become any other type of machine. And unless your object (or actor) happens to be emulating a Turing Complete machine, it's not a "mini-computer".

The only self-similar architecture we have in computing is the virtual machine, not the "object", whatever that word means.

<comment><USER12> What exactly do you think that an Actor cannot do? Trivially, an Actor can implement a Turing Machine. However, there are some Actors that _cannot_ be implemented using a Turing Machine, e.g., an Actor with unbounded nondeterminism.

<comment><USER11> Yes, an Actor (or object) can implement a Turing Machine. But most don't. Most are simpler machines. So this statement by Kay, for instance:

"each Smalltalk object is a recursion on the entire possibilities of the computer."

is incorrect.

<comment><USER12> Difficult to know since you don't specify exactly what an "object" is. Seems more reasonable that "Actors are a recursion on concept of interacting computers."

<comment><USER11> As I said, pick your definition of object (Java objects, Smalltalk objects, actor, etc.). Unless it's "Turing Complete machine", which isn't anyone's definition of object, you can't equate objects with computers. Saying objects are computers is like saying objects are bicycles. Some of them are, yes, but that's not the point.

What's your definition of computer?

<comment><USER15> I think that was Alan's original conception of objects (at least as could could be implemented in Smalltalk-72).

<comment><USER11> No, most Smalltalk objects were not Turing Complete. Take numbers. Numbers are objects in Smalltalk. They're not Turing Complete.

<comment><USER15> He seems to hint a bit what he meant in this HN comment - [https://news.ycombinator.com/item?id=11946935](https://news.ycombinator.com/item?id=11946935).

Also remember that what most people think of Smalltalk (ie Smalltalk-80) doesnt seem to be what AK thinks of Smalltalk (I get the feeling that the Smalltalk-72 approach is closer to the ideals he had in mind).

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER16> In-process REST sounds horrible inefficient.

<comment><USER6> [https://en.wikipedia.org/wiki/Microkernel](https://en.wikipedia.org/wiki/Microkernel)

</comment></comment><comment><USER11> Can you briefly describe what you mean by "In-Process REST" and what the benefits are? I tried to read your slides but couldn't understand them. Are these new in-process interfaces asynchronous? Or are they synchronous interfaces that adhere to REST principles?

<comment><AUTHOR> I talk about this in the _Storage Combinators_ paper[1]

In-Process REST essentially means applying the applicable mechanisms of REST in-process:

1) URIs

2) a few well-defined verbs

Benefits:

1) Common, concise and familiar API for talking about storage. (Check how much API surface there is for talking about storage variations in typical OO libraries. In Cocoa, for example, it's atrocious).

2) Paths. For some of the benefits of paths in general purpose programming, see _The Programming Language Aspects of ThingLab_ [2]

3) Avoidance of the architectural mismatch between storage-oriented problem domains (most of them), and procedurally-based implementation technologies.

4) Composability: this is the heart of the _Storage Combinators_ paper, you can plug these things together to obtain the desired functionality.

5) Performance, at least compared to other ways of getting similar benefits, such as (over-)used of filesystems, FUSE, Microservices for architectural reasons etc.

...

[1] [https://www.hpi.uni- potsdam.de/hirschfeld/publications/media...](https://www.hpi.uni- potsdam.de/hirschfeld/publications/media/WeiherHirschfeld_2019_StorageCombinators_AcmDL_Preprint.pdf)

[2] [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.90...](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.90.2858&rep=rep1&type=pdf)

<comment><USER11> I'll check out the paper, but at a glance, "a few well-defined verbs" seems to just mean you've introduced a set of standard storage interfaces, right? If so, calling this REST, to the extent which that word means anything at all, seems a bit of a stretch.

<comment><USER17> I just finished reading the paper and that's what it looks like to me. It's a CRUD interface w/ multiple implementations (proxy, cache, route, serialize, filesystem store, memory store), which they create pipelines out of using some syntactic sugar in the Objective-Smalltalk language. This syntactic sugar, discussed in their paper on 'polymorphic identifiers', allows you to use the same syntax for writing content to a file as you would writing to a key in a map or a field in an object. If you look at the pictures / tables in this paper, you get a general idea of what they are doing (e.g. replacing the filesystem store with a memory store while running tests). These dynamically dispatched processing pipelines are powerful, but can be hard to follow (which is true of dynamically dispatched processing pipelines in general). The power/obfuscation is multiplied by the convenient syntax of the language.

My opinion is that the actual innovation is the 'polymorphic identifiers' they introduced in their previous paper, which is definitely worth a read as my one line description of it can't really do it justice. It's kind of like being able to overload the assignment operator. Once you have that kind of feature, it's sort of a no-brainer to say 'Hey, all I/O (variables in memory, filesystems, etc) should use the same interface'.

<comment><USER11> For 10 years, people have been talking about REST as if it means something. I could never figure it out. If it means anything more than CRUD, it's lost on me.

<comment><USER17> I've had the same feeling and finally came to a few conclusion that Fielding's REST architectural constraints lead to client applications that are required to utilize undefined URIs for performance gains. The reason true RESTful APIs are scarce as compared to HTTP/JSON APIs is due to API developers recognizing this issue and choosing to deal with it by making URIs part of the API contract. The REST community has offered no additional guidance or answers other than to point out (correctly) that HTTP/JSON APIs aren't truly RESTful. That is OK.

Here is a much longer comment on reddit where I go through Fielding's thesis and a few other writings and show that following the constraints pretty naturally leads to the outcome above: [https://www.reddit.com/r/programming/comments/2oyj65/api_des...](https://www.reddit.com/r/programming/comments/2oyj65/api_design_guide_creating_interfaces_that/cmvcg6y/)

</comment></comment></comment></comment></comment></comment><comment><USER18> question: would you consider STL (standard-template-library) closer (in some sense of the word) "philosophically" to theory of objects than 'vanilla' OO ?

i mean, _i_ always find it _intriguing_ that in OO, world can be decomposed in terms of interfaces that vary on a single type, whereas, imho, what you _really_ need is to parameterize your program by the structure of data that it manipulates i.e. a notion of bunch of interfaces spanning across multiple types...

</comment><comment><USER19> OOP feels right because it's an imitation of reality. In the reality we live in... a verb cannot exist without a noun. Think about it: how can there be "movement" without the "thing that moves." OOP makes sense from this perspective.

If however we think of abstractions outside of reality as we know it. Things like imaginary numbers, negative numbers and non-euclidean geometry appear.

Outside of reality an Object can be further divided into two things that don't really exist in the real world: pure state and pure action (from certain perspectives, ... technically the function still occupies state and can be thought of as an object). In CS it feels as if the discovery came backwards the real world analogue (OOP) came after the abstraction that doesn't exist in reality (mathematical functions and numbers).

Anyway, I'm taking this somewhere that has a relation to the parent article so hear me out. Function and State as separate entities is a smaller organizational subdivision then Objects which are Functions With State. Separating Function and State solves a big problem that is central to Designing Systems. The problem is associated with modularity problems grouping two primitives together into a single entity. What happens is more often then not we don't fully understand the true nature of the thing we are building. So in the initial designs of an OOP system we unionize a certain function with a certain state and it seems like the correct thing to do at the time, but over time as requirements change or we gain greater knowledge of the problem we're solving we realize that the function/method is better used in a separate context. But it's too late... at this stage the method that we want to pull out is dependent on the object and that object is a dependency for multitudes of other objects. Thus we either end up rewriting code or creating a hack, thereby inventing technical debt.

If that method was never unionized with state, if we used smaller subdivisions in our code where state and functions are separate entities then this would be much less of a problem. The function would not be tied to state and that function can be executed in the context of anything.

This metaobject post talks about the isomorphism between OOP and HTTP/REST/Servers and talks about the success of that model and how we should bring it down to the process level. I'm thinking what's the point? JAVA and smalltalk and a bunch of other languages fill that role you're just changing the semantics, but the structure is still the same.

He also fails to talk about the problems we have with concept of HTTP, REST and servers taken to the max. We have a term for this it's called "microservices." The problems we have with microservices are exactly the same problems that I just described. I described a problem with OOP and microservices are an OOP model. The difference here is rather then unionizing action and state with Code it unionizes state and action with real cold hard metal. The actual machine that holds state and "does stuff" is the object. So all the problems of realizing how to divide or unionize services and state in microservices are exact same problems that existed when trying to figure out what methods belong with what object in OOP, only when the actual machine is your abstraction barrier, things are much harder to change. The problem is well described even by OOP advocate martin fowler: [https://martinfowler.com/bliki/MonolithFirst.html](https://martinfowler.com/bliki/MonolithFirst.html). His solution for this problem is less then ideal... basically... build it wrong first then tear it apart and mutate it into something else... I don't even know if martin fowler realizes that he's also talking about OOP as the design structure of microservices and OOP are isomorphic.

Anyway, I digressed... and I'm still disagreeing with the OPs conclusion. It makes no sense to me why we should bring this server/HTTP model down into code given the fact that it has all these problems and that it's basically already done with JAVA. The way forward is actually movement in the opposite direction. Don't abstract code into a server model rather abstract the server model into code. Basically code that doesn't compile into assembly language but compiles into apps that are automatically networked across a constellation of servers. It's a very hard thing to implement but being allowed to separate function and state at the server level like we do in code is, in my opinion, the way forward.

It also sort of exists in a minor way with the whole infrastructure as code thing and aws lambdas.

<comment><USER11> > The function would not be tied to state and that function can be executed in > the context of anything.

Non-OOP functions are still written against the interface of their parameters, so they remain tied to state.

<comment><USER19> Interfaces are usually stateless as they only contain methods.

Technically, the function body itself is a form of state but I addressed this technicality above.

<comment><USER11> No, I mean the function (e.g. a C function) assumes a particular type of parameter. So it's bound to that type of parameter (by accessing its fields) in the same way a method is bound to its object. It's the same problem.

<comment><USER19> Instructions acting on types or interfaces in the purest sense are just actions and verbs... it is not state. The technicality arises when you consider the fact that for the instructions to even exist you must write the instructions down... the result of writing something down is the creation of state.

So to address what I think will encompass what you're referring to and a lot more than that... anything that is written down as code is in itself state, including types, interfaces and the function body. But as I mentioned before this is a technicality.

We pretend that the computer is executing functions when it is actually executing assembly code that imitates functions just like we how we can pretend functions are stateless even though their very existence implies state.

<comment><USER20> I think the argument is that the difference between `noun.verb(state)` and `verb(noun, state)` is only semantic. The former is just syntactic sugar for the latter under the hood (or not. Look at python). The dependencies are the same.

<comment><USER19> I've seen your argument b4. I'm not sure if he's referring to that.

Either way it's more than semantics. Let's say I have two nouns. Noun1 and Noun2. Only Noun1 contains the verb method. Noun2 does not. How can I use noun1.verb on noun2?

I cannot use it. But I can use verb(noun, state) on either object. noun1.verb forms an arbitrary wall that becomes technical debt. Even modifying noun1.verb will not help, the only way is to move it AND modify it and change all the things that are dependent on it...

While verb(noun, ...) at most requires a modification, that's it. Semantically the "meanings" are the same but from a modularity perspective there is a difference in the "agility" of the method.

Let me put it simply. a method is tied to its parent object/interface by type AND scope of the parent instantiation. You cannot reuse the function outside of the scope.

A function is only tied to the type. Your argument is true if you're only thinking about types.

You might be thinking that the "type" of noun is really the same concept as scope and that if you get the type of the "noun" right then both examples are the same. You're not wrong in this sense but rarely do people place the right method on exactly the right interface or object. Usually they place it on an interface and realize (months or years later) that the method can be reused on 30 other unrelated objects. The change to correct the design on such a discovery involves a massive rewrite of a type hierarchy. It is a huge effort and often not undertaken.

<comment><USER20> I find it _much_ more likely that shoehorning `verb(noun1, ...)` to accept `noun2` will result in sub-optimal design than factoring out an interface (`verb(...)`) that both `noun1` and `noun2` will implement. A verb's meaning/implementation can shift dramatically depending on the noun to which it is attributed. E.g. `validate(user)` is materially different than `validate(order)`.

Any argument predicating on "massive rewrites" and "huge efforts" is a straw- man. A programmer can model dependencies incorrectly using either approach above. Expanding a discriminated union (to include `noun2`) will lead to the exact same amount of refactoring as extracting an interface. We know this because it _is_ a matter of semantics.

The discussion at hand is about comparing/contrasting the dependencies between object-methods (`noun.verb(...)`) and stand-alone functions (`verb(noun, ...)`). From the POV of the method/function, the dependencies are the same. Whether `noun` is explicitly passed as an argument or compiled into `this` does not change what information is available to the function body (i.e. it's dependencies).

<comment><USER19> >I find it _much_ more likely that shoehorning `verb(noun1, ...)` to accept `noun2` will result in sub-optimal design than factoring out an interface (`verb(...)`) that both `noun1` and `noun2` will implement.

I am not talking about the case you describe above. Get rid of Union types, that is a whole different thing. I am talking about a function that does not need to be shoe horned that can obviously be used for members of both noun1 and noun2 but due to a design decision the function is tied to noun1.

Let me give you a concrete example that is trivial. The example is so trivial that it probably won't happen in the real world but you can see how for concepts that are more complex it can happen all the time.

Imagine I have an app with a class in it called SortedListOfPeople. It would make sense to put a sort method on this class. Now imagine that this app runs for a bit then you add a feature which involves a class called GroupOfCats. The feature is very far away from and completely different from SortedListOfPeople. Then one day you get the task to turn GroupOfCats into SortedGroupOfCats.

Suddenly you got a problem. How do you re-use the code from sorted list of people without the sorted list of people? How do you use it with a different context at all? Not being able to reuse code is NOT a semantic problem. It is an intrinsic design problem.

Your genius solution above (Note how I call your solution genius instead of straw-man) is two implementations of the same concept. This is obviously more genius than one function.

Sortable types is an obvious example, but think about how often this problem occurs in OOP for more complicated concepts. You end up implementing things multiple times all over the place.

If the sort function was a stateless function operating on a sortable interface parameter you would not have this problem. The only thing you need to implement for GroupOfCats is to give it a sortable interface rather than reimplement sort for everything that needs to be sorted.

Actually if you think really hard about OOP and the sort function. How would you make a generic sort function that can be reused across all contexts while following the rules of OOP? You cannot use static classes and the function cannot take parameters... as that would imply a stateless function. The sort function must operate on the classes own state. How can you then share the sort method across two or more classes in OOP?

The answer is inheritance. Put the sort method in the base class. How would you share the sort function with classes that already have ancestors? Multiple inheritance. Too bad everybody hates these two concepts so they resort to garbage syntax that basically turns the class into a namespace so they can start using functions as if they weren't tied to some intrinsic state.

<comment><USER20> You have simply contrived a poor design, then pointed out its flaws. Not only that, you are _constraining_ the solution space (no static methods and must be parameter-less). That sounds like a straw-man to me. There is nothing inherent in OOP that mandates a developer choose your design.

Furthermore, you are comparing a perfectly factored functional design to a poorly factored OOP design. I can just as easily assert that `sort(people)` cannot be factored into `sort(comparable)` because "clearly" the body of `sort(people)` is dependent on some property of `people` that is not present on `comparable`. Contravariance cannot just be assumed.

Said another way, every function is tied to the entire public surface of the data to which it is provided (at least in theory). So unless `people` just happened to have exactly the same interface as `comparable` already, a new, more generic, `sort(comparable)` function would be necessary.

The solutions are roughly equivalent in either paradigm: move the behavior into a more generic container. Where composition can be used instead of inheritance in tandem with double dispatch, for OOP, if the public surface of SortedGroupOfCats must include a `sort()` function.

<comment><USER19> >You have simply contrived a poor design

I contrived a poor design that is a reflection of what can happen. There is no design theory making all designs perfect therefore many isomorphic mistakes in my design happen all the time uncontrived.

>Not only that, you are _constraining_ the solution space (no static methods and must be parameter-less).

I constrain it to prevent you from creating a function instead of a method. A function is outside of OOP a method is 100% OOP. a static class without state is equivalent to a namespace holding a bunch of functions. If I didn't constrain you you'd be proving my point by switching to using a regular function instead of OOP.

>There is nothing inherent in OOP that mandates a developer choose your design.

That is the problem. There is something inherent in functional programming that mandates the developer to never be able to make the previous design choice. If all your functions are stateless there is NO way you can even contrive the poor design I contrived earlier. That is the secret. Less expressivity is less ways to screw up. Imagine a programming language where the syntax only allows you to design your programs in the best possible way... Functional programming is closer to this goal than OOP.

>I can just as easily assert that `sort(people)` cannot be factored into `sort(comparable)`

It's better to factor something to be more general than to write 10 flavors of the same thing. How hard it is doesn't matter here, rewriting sort to solve this problem is better than OOP where you have to write another version. That is all I am arguing for.

>Contravariance cannot just be assumed.

The entire essence of my argument is that you discover this property in two random places, but you cannot apply a function in both places because the function is tied to another context.

>a new, more generic, `sort(comparable)`

And this is better than two specific flavors of sort. Let's scale this up to an app that's been around for 5 years.... in this case One generic sort is better than 20 different flavors of sort.

>The solutions are roughly equivalent in either paradigm: move the behavior into a more generic container.

But like I've been saying you can't just move the method in OOP you have to change the object hierarchy. If the method is to be used in another unrelated object hierarchy than the hierarchies have to be merged via multiple inheritance. All I want is the function, why am I bringing the whole object ancestral structure with it?

"I think the lack of reusability comes in object-oriented languages, not functional languages. Because the problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle."

        -joe armstrong

<comment><USER20> >I can just as easily assert that `sort(people)` cannot be factored into `sort(comparable)`

You are misunderstanding what I am asserting here. If the body of `sort(people)` is coupled to a property of `people` not present on `comparable`, you cannot _just_ refactor to a more generic `sort(comparable)` and expect the behavior to remain consistent. The solution requires two functions: `sort(comparable)` that abstracts the portion of the function body concerned with the surface of `comparable`, AND `sort(people)` that interacts with the property of `people` not present on `comparable`. It's obviously worth noting here that `sort` could just as easily be some other verb, say `validate` (I understand `sort` doesn't make much sense in this particular context).

Similarly, there is no need to "move the method" or "change the object hierarchy". You conveniently failed to quote the one line in my response above that addresses this...

>composition can be used instead of inheritance in tandem with double dispatch, for OOP, if the public surface of SortedGroupOfCats must include a `sort()` function

And while it makes for a great quote, Joe Armstrong is simply wrong. There is nothing inherent to OOP (and even less so when examining the languages that utilize the paradigm) that requires poor design. What if I wanted "the banana that one specific gorilla is holding in some particular jungle"? How would that look in OOP vs functional? More importantly, is there a meaningful difference or is it just semantics?

FWIW, I prefer a functional paradigm myself.

<comment><USER19> >You are misunderstanding what I am asserting here. If the body of `sort(people)` is coupled to a property of `people` not present on `comparable`, you cannot _just_ refactor to a more generic `sort(comparable)` and expect the behavior to remain consistent.

Refactor sort into the composition of two functions. One is reliant on people, the other is just sort. The signature of the original sort function remains the same. But you have a general function that can be reused in different contexts. This type of change CANNOT be done on OOP.

>composition can be used instead of inheritance in tandem with double dispatch, for OOP, if the public surface of SortedGroupOfCats must include a `sort()` function

composition moves the entire state across. Think about it. I have SortedGroupOfCats and you want me in order to reuse sort, move SortedGroupOfPeople into SortedGroupOfCats.

>And while it makes for a great quote, Joe Armstrong is simply wrong. There is nothing inherent to OOP (and even less so when examining the languages that utilize the paradigm) that requires poor design.

OOP is bad because it makes it possible to shoot yourself in the foot, and while avoidable, unfortunately the syntax promotes designs that tend to be bad.

>More importantly, is there a meaningful difference or is it just semantics?

There is.. a function does not need to be instantiated to be used. A function never modified an entity. That changes everything. The fact that lambda calculus and turing machine exist in a theoretical sense shows you that the industry knows about an intrinsic difference between the two concepts.

>FWIW, I prefer a functional paradigm myself.

Note that although I have used the functional paradigm as an example this is not my overall critique. I am not just saying OOP is better than functional programming. I am saying OOP is worse than imperative, procedural and functional programming. Out of all of the most popular ways of programming... OOP is the least modular and the one with many many design issues. Even non- functional programmers have noticed this... GO is one of the results of this realization.

There are cases where OOP works, but in most cases, it's sub-optimal.

<comment><USER20> >The signature of the original sort function remains the same. But you have a general function that can be reused in different contexts. This type of change CANNOT be done on OOP.

This is where you lose me. The above is simply untrue. There is absolutely no reason one cannot employ `SortingAlogrithm.sort` within the body of `people.sort()`. Are you suggesting every utility class (and by extension the entire standard lib) needs to be injected into an object before it can be used?

Again, you are creating a false-equivalence. A "fair" example would require our generic `sort(comparable)` be passed into the original as a dependency like so: `sort(people, csort)`. It's _possible_ that the two functions could be composed, but that is completely dependent on the semantics of each function (we cannot just assume composition is possible for every use-case).

The difference between a first-class function and an object is purely semantics. Yes, you have to `new` an object before you can call a method, but there is no requirement any "implicit context" has to be provided at the time of instantiation. Closures offer the exact same capability via "capturing" and partial application.

Conceptually, all OOP does is take 10 functions that all have the same parameter and "partially apply" each of them over that parameter into new functions that don't have a parameter (i.e. they get that "implicit context"). That is, OOP saves you a step. It is common practice in FP to start with "pure" functions then, higher up in the application, partially apply those functions into new, domain-specific functions with your data (a.k.a. dependency injection) that are strung together to carryout a use case. OOP allows you to _define_ partially applied functions instead of the need to compose them (of course this also makes the DI mechanism a bit different as well).

I can agree that the above _can_ make decomposition more difficult, but your general critique reads more of one leveled at programmers not understanding the basic principals of software design, not OOP. I could just as easily create a mess in FP as in OOP.

>More importantly, is there a meaningful difference or is it just semantics?

I urge you to sit down and write out the pseudo-code. It will be plainly obvious that there is no meaningful difference between each approach.

<comment><USER19> >This is where you lose me. The above is simply untrue.

No. My statements are true. But you are right about you being completely lost.

>There is absolutely no reason one cannot employ `SortingAlogrithm.sort` within the body of `people.sort()`

Let's talk about objectives and what you're implying with this suggestion. The objective is to sort a bunch of people within the the people class.

What is SortingAlogrithm.sort? Is it an object that sorts its own state or is it a stateless class with a stateless function? If it's an object that sorts its own state then it CAN'T do what I want. I want it to sort peoples' state NOT it's own state. If it's a stateless class with a stateless method then you are no longer doing OOP you have created a function that is not tied to state thereby proving my point that stateless functions are more modular.

>Are you suggesting every utility class (and by extension the entire standard lib) needs to be injected into an object before it can be used?

Yes this is the model in pure OOP languages. Otherwise you are using a hybrid of OOP and functions thereby providing evidence that OOP alone is broken. Things like JAVA, C++ do all kinds of BS like this further ingratiating my point.

>Again, you are creating a false-equivalence.

No. You are failing to understand. 'Lost' was the term you, yourself used.

>A "fair" example would require our generic `sort(comparable)` be passed into the original as a dependency like so: `sort(people, csort)`.

This is not fair at all. in fact it's ugly. I pass a generic sort as a parameter into a specific sort? If you think that's fair and you code this way then you're in for a surprise when building a complex system.

>It's _possible_ that the two functions could be composed, but that is completely dependent on the semantics of each function (we cannot just assume composition is possible for every use-case).

I'm thinking you got confused by what I mean by composition. There are two compositions I am referring to in my statements. Function Composition and Object Composition. Object Composition is exactly the previous example you gave sort(people, csort) or inserting something via the constructor People(csort), there's a number of ways to do it.

Function composition of A(x) and B(x) is F(x) = A(B(x)). Function composition is at the heart of functional programming.

>It's _possible_ that the two functions could be composed, but that is completely dependent on the semantics of each function (we cannot just assume composition is possible for every use-case).

If you're not changing state and something has properties of being sortable it can be done.

you have x = sortableListOfPeople

composedFunctions = f(sortableListOfPeople) {return doPeopleSpecificStuff(sortGeneric(sortableListOfPeople))}

you can go the other direction if you want. The implementation is situation specific but if something is sortable this can be done always but only if all functions are stateless and don't modify values. Note composedFunctions should have the exact function signature of the original function thereby negating the need to change other things dependent on it.

>The difference between a first-class function and an object is purely semantics.

No. A first-class function cannot change. It is immuteable and when called with the same input Always has the same output. An object with a method when called at different times can have different output based off of internal state. Your statement is categorically wrong.

>Yes, you have to `new` an object before you can call a method, but there is no requirement any "implicit context" has to be provided at the time of instantiation.

Then you are basically declaring a stateless function. The admission that you have to do this is an intrinsic flaw. Yes nothing prevents you from going outside of the OOP paradigm when programming in an OOP language. You likely have no choice due to inherit flaws in OOP. Try doing OOP without this ability... You'll see how broken the whole model is.

>Conceptually, all OOP does is take 10 functions that all have the same parameter and "partially apply" each of them over that parameter into new functions that don't have a parameter (i.e. they get that "implicit context"). That is, OOP saves you a step. It is common practice in FP to start with "pure" functions then, higher up in the application, partially apply those functions into new, domain-specific functions with your data (a.k.a. dependency injection) that are strung together to carryout a use case. OOP allows you to _define_ partially applied functions instead of the need to compose them (of course this also makes the DI mechanism a bit different as well).

Let me tell you definitively. I completely understand what you're talking about, I understand it now and I understood it before. No need to reiterate. What you're not understanding is that despite my 100% comprehension of your statements I am telling you, that you are failing to understand ME.

Let me try to put it as simply as possible. If there is an Object called Number and a method called addOneAndReturn... if I call that method on a Zero Twice? what happens? I get One and then I get a two. The method is returning two different values despite being called in the same way TWICE. This sort of thing is NOT POSSIBLE in a stateless function. It Cannot Happen period. THIS is the fundamental difference. THIS is MORE than semantics.

Yes I understand that currying and first class functions have parallels to Dependency Injection BUT there is still MORE then a semantic difference between OOP and functions.

>your general critique reads more of one leveled at programmers not understanding the basic principals of software design

Design is the domain of things we don't understand. There is no design in type theory or number theory because we understand all the implications of the axioms and theorems. We go to design when there is no formal theory that can say why one design is better than others.

I am not coming from the design perspective. I am coming from the theory perspective. When you tie functions with state the state must move along with the function. If you keep state and functions separate then they can move separately. This is logic. No design principles needed.

Any language with too many design patterns is a language that is very much lacking in a formal description (think: JAVA)

>I could just as easily create a mess in FP as in OOP.

You can. But there are more ways to do it in OOP then in FP. In fact there are more ways to shoot yourself in the foot in OOP than in procedural programming in general. I'm not even referring soley to FP. Even C is better than C++.

>I urge you to sit down and write out the pseudo-code. It will be plainly obvious that there is no meaningful difference between each approach.

You don't need to write psuedo code. Use your brain dude. A stateless function versus a function that carries it's own mute-able state. There is MORE than a semantic difference. The semantic difference you're referring to is when the SELF value is immuteable. In that case the two ways of calling the function become more similar, but THAT is NOT OOP.

There is one rule that needs to be followed to make ANY program FP. Just one rule, that's it. Make all things immutable. OOP is fundamentally different from this because it involves the mutation of Object state.

<comment><USER20> I fear the goalposts have moved from "the problem with OOP" to "the problem with mutability". These are distinct concepts. The fundamental premise of OOP is, among other things, the encapsulation of behavior _with_ data (as opposed to _around_ data). It has nothing to do with mutability. One can absolutely practice OOP with immutability (looking at Scala here). Similarly, OOP doesn't need to be written imperatively. Are you suggesting `sorted_people = people.sort()` isn't OOP?

You are building your own concept of OOP to argue against, not the one that exists in reality. (straw-man emoji)

<comment><USER19> >I fear the goalposts have moved from "the problem with OOP" to "the problem with mutability". These are distinct concepts.

No they ARE not. For OOP to work you have to have objects be mute-able. The modern definition of OOP are nodes that communicate with each other and change each others state.

The minute you get rid of mute-ability is the minute you are doing functional programming.

>One can absolutely practice OOP with immutability (looking at Scala here).

Scala is a multi-paradigm language. Also scala is not always immutable. The objects in scala can mutate.

>Similarly, OOP doesn't need to be written imperatively.

It does if you want the properties of an object to change. That is the dichotomy of OOP and FP otherwise there is no dichotomy and no point for there to exist vocabulary to separate the two concepts.

>Are you suggesting `sorted_people = people.sort()` isn't OOP?

If I remove the engine from my car and roll it down a hill while in the drivers seat am I still driving the car? Yes. Technically I am. But key feature of the engine moving the car is missing. You can call people.sort() OOP you can also call it not OOP because it is missing the key feature of self modification.

>You are building your own concept of OOP to argue against, not the one that exists in reality.

lol lets look at the definition. [https://en.wikipedia.org/wiki/Object- oriented_programming](https://en.wikipedia.org/wiki/Object- oriented_programming)

I directly quote from the site above:

"Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data, in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods). A feature of objects is an object's procedures that can access and often modify the data fields of the object with which they are associated (objects have a notion of "this" or "self"). In OOP, computer programs are designed by making them out of objects that interact with one another."

Key sentence above: "A feature of objects is an object's procedures that can access and often modify the data fields of the object with which they are associated"

The goal post was never moved. It was set by the Actual definition of OOP. I am explicitly including this feature to make sure that ALL we are dealing with is OOP and not some hybrid functional or OOP merger.

>(straw-man emoji)

This mechanism of turning macros into emojis doesn't work here on HN! Similar to your arguments.

<comment><USER20> The quoted text above is referring to objects, not OOP -- which encompasses a number of concepts. You can refer to the the "Features" section in your link above for the complete list (notice one is missing). For further information about the relationship between OOP and mutability just google it.

It's a waste of time to argue about a topic that is orthogonal to your original claim (before the goalposts moved): that the "problem" with OOP is how you invoke a function -- `noun.verb` as opposed to `verb(noun)`; As if those two systems are subject to different constraints. They are not. It is just semantics.

The above isn't to say there doesn't exist consequential differences between OOP and FP, but I absolutely did _not_ engage in this discussion to argue about OOP vs FP in general. I think we actually both agree FP is a superior paradigm.

<comment><USER19> >The quoted text above is referring to objects, not OOP -- which encompasses a number of concepts. You can refer to the the "Features" section in your link above for the complete list (notice one is missing). For further information about the relationship between OOP and mutability just google it.

Makes sense. Object oriented programming isn't programming revolving around objects. You totally invalidated all my claims with this genius argument here. You also invalidated the entire definition of OOP and wikipedia too.

>It's a waste of time to argue about a topic that is orthogonal to your original claim (before the goalposts moved)

At first I was going to say that the goal posts have not moved but your brain was the thing that moved. Then I realized nothing has moved. Your brain is still in the same place: A place of ignorance.

>that the "problem" with OOP is how you invoke a function -- `noun.verb` as opposed to `verb(noun)`; As if those two systems are subject to different constraints. They are not. It is just semantics.

Let me spell it out for you where the goal posts were when the conversation started. The goal posts were in a place where 99.999% of all programmers operate: In a universe of mute-able variables, mute-able objects and immutable functions. Typically "goal posts" start here because that's how 99.99999% of all programmers operate.

So within the bounds of these "goal posts" you made a claim that OOP and Functions only have a semantic difference. Which is CATEGORICALLY wrong. So then I decided to let you know that your CLAIM is only TRUE if VARIABLES are immutable you acted AS IF we were ONLY talking about immutable variables ALL ALONG as if that's the primary assumption all programmers make when talking about programming. The goal post wasn't moved... get it? I only changed the context a little to show you WHEN your arguments would be true, BUT nowhere did I "change the goal posts."

What happened after that is that YOU changed your argument. You imply that you've been ONLY talking about immutable variables all along and that I changed the goal posts to suit my needs. I can tell you 100% that you are either a liar or deeply delusional. You literally refuted a sourced definition of OOP in your attempt to stay relevant. Give it up dude.

>The above isn't to say there doesn't exist consequential differences between OOP and FP, but I absolutely did _not_ engage in this discussion to argue about OOP vs FP in general. I think we actually both agree FP is a superior paradigm.

I agree that we aren't talking about FP vs. OOP. What we are talking about is, and I quote:

"that the "problem" with OOP is how you invoke a function -- `noun.verb` as opposed to `verb(noun)`; As if those two systems are subject to different constraints. They are not. It is just semantics."

Which you are completely and utterly wrong about. You cannot make this statement without saying that all variables are immutable which is not a property that can be ASSUMED OUT OF THIN AIR.

<comment><USER20> Tone it down.

OOP is not "programming revolving around objects". Simply using objects in your code-base does not mean you are practicing OOP anymore than using functions means you are practicing FP. But I digress. Again, the definition of OOP is unrelated to the claim which prompted this discussion.

>The function would not be tied to state and that function can be executed in the context of anything

This is the (your) line of text at the top this thread (go look), and the point to which I wanted to offer some clarification. It has nothing to do with the definition of OOP or mutability vs immutability.

The point I have been trying to make is that `noun.verb` and `verb(noun)` are both tied to the same state; That the _caller_ of either of these functions needs to have a reference to `noun`. In this way, the "context" is also the same (both functions can only be executed in a context that has `noun`). There are problems with OOP! The above just isn't one of them.

>You cannot make this statement without saying that all variables are immutable

How do you know `noub.verb` mutates `noun`? Similarly, how do you know `verb(noun)` doesn't mutate `noun`? There is no way to make an assessment of the mutability of `noun` given those snippets. Which is kind of the point: they are equivalent.

Making an assertion about the behavior of either function (when that behavior is _clearly_ not shown) is building an argument against something else entirely. This is called a straw-man. Similarly, shifting the argument to be about the definition of OOP and/or mutability instead of the relationship between how a function is written and its dependencies/modularity is to argue about something else entirely. This is called moving the goalposts.

<comment><USER19> >How do you know `noub.verb` mutates `noun`? Similarly, how do you know `verb(noun)` doesn't mutate `noun`? There is no way to make an assessment of the mutability of `noun` given those snippets. Which is kind of the point: they are equivalent.

This is why you have to make every possible assertion. Muteable and immuteable. And in the muteable case your statement is wrong. Since we are talking about OOP (see first sentence of my first post) by definition only the muteable case is considered. There was no movement of goal posts, you simply failed to see where the goal posts were originally.

>Making an assertion about the behavior of either function (when that behavior is _clearly_ not shown) is building an argument against something else entirely. This is called a straw-man. Similarly, shifting the argument to be about the definition of OOP and/or mutability instead of the relationship between how a function is written and its dependencies/modularity is to argue about something else entirely. This is called moving the goalposts.

The topic at hand is on OOP. That's because that's the topic in my first post. Thus since OOP is mentioned in my first post THE DEFINITION of OOP is what I'm talking about. And since mute-ability is part of the DEFINITION of OOP this is the topic. What happened is you entered this conversation with the idea that the goal posts were somewhere else. They were not.

We are talking about noun.verb and verb(noun) in the context of OOP. That is the topic. And the statement of verb(noun) is the same as noun.verb is categorically wrong. You are wrong. This is concrete.

<comment><USER20> The only assertion I need to make (and have made repeatedly), is that `noun.verb` and `verb(noun)` are subject to the same constraints. In terms of mutability, we can say that both functions could mutate `noun` or both functions could not mutate `noun`. It is a straw-man to build an argument against a premise which arbitrarily asserts that `noun.verb` _behaves_ differently than `verb(noun)`. The behavior of the function(s) is not relevant to point you were trying to make or my point of clarification (of course two functions that behave differently are different!). Again:

>The function would not be tied to state and that function can be executed in the context of anything

The above is the claim which prompted this lengthy discussion. It has nothing to do with the definition of OOP or mutability. To rephrase your argument in my own words:

Separating data and behavior (state and functions resp.), in the form of `verb(noun)`, is superior to combining data and behavior, in the form of `noun.verb`, because it means `verb` is subject to fewer constraints and, as a result, is more portable.

The above is not accurate. There _are_ problems introduced by encapsulation. But one of them is not that functions are tied to state. This remains true for any function no matter how it is written (the semantics).

I'm not sure why you continue to insist on moving the goalposts here, especially to an argument for which you are so obviously wrong. The definition of OOP makes no claims about mutability. Furthermore, many of the most popular OOP languages provide built-in support for defining objects as immutable (while at the same time implementing immutable objects in their own standard libraries. e.g. `string` in many languages). Even a cursory google search on the subject unambiguously yields this information. I'm not going to waste my time debating this when you are fully capable of researching and revising your position. Especially because this has nothing to do with the claims that provoked this discussion in the first place.

My original comment was rather innocuous. It was intended as a point of clarification towards a claim you made as part of your broader opinions on the deficits that OOP impose on a system as it relates to functions, state, and modularity. You essentially say the same thing later in your post in your comparison between the OOP model and microservices:

>The difference here is rather then unionizing action and state with Code it unionizes state and action with real cold hard metal. The actual machine that holds state and "does stuff" is the object. So all the problems of realizing how to divide or unionize services and state in microservices are exact same problems that existed when trying to figure out what methods belong with what object in OOP...

Just replace "microservices" with "FP" in that last sentence and you will have basically synthesized my argument:

"all the problems of realizing how to divide or unionize services and state in _FP_ are exact same problems that existed when trying to figure out what methods belong with what object in OOP"

For what it's worth, I agree with your ultimate conclusions.

<comment><USER19> >>The function would not be tied to state and that function can be executed in the context of anything

>The above is the claim which prompted this lengthy discussion. It has nothing to do with the definition of OOP or mutability. To rephrase your argument in my own words:

>Separating data and behavior (state and functions resp.), in the form of `verb(noun)`, is superior to combining data and behavior, in the form of `noun.verb`, because it means `verb` is subject to fewer constraints and, as a result, is more portable.

>The above is not accurate. There _are_ problems introduced by encapsulation. But one of them is not that functions are tied to state. This remains true for any function no matter how it is written (the semantics).

Have you ever thought about the difference between a list of "noun.methods" that encapsulate a "noun" vs. a list of "verb(noun)" that also encapsulate a noun? Under your semantic equivalence principle it's the same thing. IN your universe one can encapsulate a noun with procedural functions through type signatures AND it can be done with OOP as well. We are of course negating the usage of a noun as a global variable.

Also what is the "noun" in "noun.verb"? Can it be a namespace? Is "noun.verb" the same as "namespace.verb"? Namespaces hold variables and functions and so do Objects... Are these two concepts isomorphic? If regular programming already has namespaces what's so special about Object Oriented programming? What's the point of calling a namespace an object?

Well then you could say that OOP allows the user to "generate" or "instantiate" namespaces at runtime. That's neat except what is the point of generating a new namespace for what is essentially the same thing? Why do I need namespace1.verb and namespace2.verb when I can just have verb(namespace) or just get rid of OOP and have a single namespace.verb?

Well you could argue that namespace1 and namespace2 have different states. That's why you need the ability to instantiate them. But then what's the point of instantiating different namespaces at runtime when you can just have verb(namespace1) or verb(namespace2)? What's the point of OOP if it's the same thing as everything else in existence? Was OOP invented for semantic confusion only?

Well no, in OOP the namespace.verb() verb modifies the instantiated namespace. namespace1.verb is DIFFERENT from namespace2.verb because they are modifying different states. This is OOP. If VERB was stateless and did not touch the state of namespace2 or namespace1 then there would be no difference and you wouldn't be doing OOP.

It is mutation that ties a method to state. The goal posts were never moved. When you talk about OOP you have to talk about it in the context of mutation because that's what Wikipedia lists as part of the definition and that is the only unique and logical difference between OOP and other forms of programming. Thus you must be mutating or reading internal state to be doing OOP.

In the context of OOP and the sort example, noun.verb MUST modify noun otherwise we aren't talking about OOP. IN the context of procedural functions verb(noun), verb COULD modify noun OR it could NOT. In FP verb CANNOT modify noun ever.

FP: verb(noun), verb cannot modify noun OOP: noun.verb, verb MUST modify noun Procedural programming: verb(noun), verb can modify noun or it may not.

The implementation changes depending on the context and the context is 100% OOP. For any styles to be isomorphic (which is what you are implying) the properties must match exactly. I talked about OOP in my first comment, you were making a clarification about it in reference to another person who was also talking under the SAME oop context. The title of this entire thread has OOP in it. We are talking about OOP.

You can bend procedural programming to be isomorphic to OOP. But this isn't a two way equivalence, you cannot always bend OOP to fit a procedural function.

This statement from you (a perversion of a statement I made earlier) is ALSO categorically wrong:

>"all the problems of realizing how to divide or unionize services and state in FP are exact same problems that existed when trying to figure out what methods belong with what object in OOP"

In FP, everything has to be immutable. This the exact opposite of a required property for OOP. OOP uses mutability to tie methods with state.

Also you should note the definition of encapsulation is literally my argument of unionizing state with methods plus the added property of information hiding or aka private members and methods ([https://www.wikiwand.com/en/Encapsulation_(computer_programm...](https://www.wikiwand.com/en/Encapsulation_\(computer_programming\))). That's it. Since you're basically saying that the unionization of state and methods ISN'T the problem... you must be referring to information hiding. The private keyword, according to you is the problem with OOP. All of the problems with OOP (encapsulation) according to you could be fixed if people stopped using the private keyword. Amazing. Take a look at python... no private keyword... didn't fix anything.

>For what it's worth, I agree with your ultimate conclusions.

If you think encapsulation is the cause of the "ultimate conclusion" you need to realize, namespaces and modules and libraries also encapsulate things with no problems. The source of OOP's problems is not in encapsulation. You or whoever introduced that idea to you is completely wrong. Literally you can write a metaprogramming script that removes all the private keywords from objects and according to your logic will fix the problem.

<comment><USER20> In OOP, unlike FP, immutability is an implementation detail, not a requirement. I'm trying to be gentle about this, but your insistence is becoming tiresome. Again, just do a search and inform yourself. I'm not going to patronize you by listing the numerous links/resources that clarify the above distinction.

>The problem is associated with modularity problems grouping two primitives together into a single entity

>If that method was never unionized with state, if we used smaller subdivisions in our code where state and functions are separate entities then this would be much less of a problem

>all the problems of realizing how to divide or unionize services and state in microservices are exact same problems that existed when trying to figure out what methods belong with what object in OOP

Maybe I'm misunderstanding you argument, but I understand "the problem[s]" above (your words) to be a matter of organization not implementation -- I see no reference to mutability.

I don't have to be wrong about this. `noun.verb` doesn't have to be materially different than `verb(noun)` for the validity of your point to hold about the difficulties of designing and distributing systems being the major obstacle and that abstracting the server model into code being more pragmatic than abstracting the code into the server model.

I am simply clarifying that you can create the same problems with organization in FP as OOP. That is, you can write a function with the wrong signature just the same as you can put a method on the wrong object. Modelling a domain happens before any code is written (theoretically). There is nothing inherent in either paradigm that forces a developer to synthesize a useful abstraction of the functional requirements of their system any better than the other one.

If anything I am _strengthening_ your argument.

<comment><USER19> >In OOP, unlike FP, immutability is an implementation detail, not a requirement. I'm trying to be gentle about this, but your insistence is becoming tiresome. Again, just do a search and inform yourself. I'm not going to patronize you by listing the numerous links/resources that clarify the above distinction.

I patronized you with wikipedia. Go ahead and send me some links to some blog posts. Just note that some medium blog posters "opinion" on OOP like your opinion doesn't mean anything without a proper logical reasoning. You will see tons of people who say garbage like "OOP" is "orthogonal" to "FP" which is equal to the amount of people who don't know what FP actually is.

>Maybe I'm misunderstanding you argument, but I understand "the problem[s]" above (your words) to be a matter of organization not implementation -- I see no reference to mutability.

I didn't mention it because it's a very subtle property that's very hard to see and very hard to explain. People understand how OOP is organized on the surface, they don't understand the subtleties of it. Only when we get into details does it come out: Mutability is the very property that dictates the organization of OOP. I get how it appears that I'm moving "goal posts" since I didn't bring it up explicitly in the beginning.

What happened was you noticed a subtle isomorphism between two paradigms but the details were even subtler then that. This is when I chose to bring up the topic of mutability because this is the core property that is intrinsically tied to the organization of OOP. In short, I dove into the details when you brought up a detail... Anyway, mutability It is the core property that breaks the isomorphism and dictates our vocabulary... it's why we have the term OOP, FP and Procedural Programming in the first place.

>I am simply clarifying that you can create the same problems with organization in FP as OOP. That is, you can write a function with the wrong signature just the same as you can put a method on the wrong object. Modelling a domain happens before any code is written (theoretically). There is nothing inherent in either paradigm that forces a developer to synthesize a useful abstraction of the functional requirements of their system any better than the other one.

You're talking about the application of programming styles to the real world which is amenable to opinion.

One paradigm is more flexible to change.

Much easier to change a function operating on the wrong type than it is to change a method intrinsically tied to scoped variables that change state.

The biggest key difference is that FP gives you flexibility to change the model once the inevitable design flaws become apparent.

You will note that in OOP there are no functions or data. Only data bundled with methods called Objects can exist. It's easy to see how these arbitrary walls cause numerous design issues. Also, again, it is the mutability of each object that is the actual instigator of this organizational scheme, I am not talking about the "semantic difference" you pointed out earlier.

>If anything I am _strengthening_ your argument.

I disagree. I believe OOP is actually _worse_ than most other styles of programming for most cases. You are saying OOP is the same as all other forms.

<comment><USER20> The Wikipedia page to which you keep referring does not support the argument that mutability is "core property" of OOP. The quote you've cited (far above at this point) is referring to a feature of objects, not OOP. OOP encompasses range of features. You can explore them on that very same page under the "Features" section. You will certainly notice that "Mutability" is not listed as a feature. OOP is an _approach_. Simply using objects does not mean you are practicing OOP any more than using functions means you are practicing FP.

I urge to to a ctrl+F on "mutable" and read the top 2 (of 3) passages where it is referenced (the third is not relevant):

> ... in most OOP languages, in particular in all those that allow mutable > objects.

> ... in OOP languages (with mutable objects) ...

The clarifications in the above passages are unnecessary if mutability is considered a necessary feature for OOP. If that's not enough, how about you read the first sentence of [https://en.wikipedia.org/wiki/Immutable_object](https://en.wikipedia.org/wiki/Immutable_object):

> In object-oriented and functional programming, an immutable object > (unchangeable[1] object) is an object whose state cannot be modified after > it is created.

If immutable objects are incompatible with OOP, why is it included in the above?

Are you suggesting that if I write a Java program and I use all of the features of OOP (inheritance, polymorphism, encapsulation, etc.) but don't use mutability, that my system is better understood as functional? Come on. What about an OOP system that doesn't mutate by design? Not every program requires changes of state. We need to put this to rest. I can pretend "this never happened". After all, this entire argument is not relevant to the point I was trying to make (the whole goalpost thing).

> Much easier to change a function operating on the wrong type than it is to > change a method intrinsically tied to scoped variables

_This_ is to the point I was trying to make. The above is simply untrue. If I have a function referenced all over my code base, `validate(giraffe)`, and we change the signature to `validate(gorilla)`, it isn't any easier to refactor the system than if it were modeled in OOP. In both cases, the _caller_ needs to have a reference to a different piece of data in order to call our `validate` function. Which means the caller of the caller needs to have a different piece of data (so now the caller needs to change), etc. up the stack. In the end, the most flexible solution in either paradigm is to "inject" the appropriate data (`giraffe`/`gorilla`) via the "DI" mechanism that the paradigm supports. In OOP this is in the constructor. In FP we can use partial application. These two concepts _are_ isomorphic.

I am _not_ saying that OOP is "the same as" all other forms. I am saying, in terms of the pitfalls regarding modelling a domain, all forms are the same. As I understand it, this is the argument your OP was making (you just left FP out of it).

I agree that OOP is worse than FP. There are a few features of FP that make it superior in many respects (notably required immutability and an algebraic type system).

<comment><USER19> >The Wikipedia page to which you keep referring does not support the argument that mutability is "core property" of OOP. The quote you've cited (far above at this point) is referring to a feature of objects, not OOP. OOP encompasses range of features. You can explore them on that very same page under the "Features" section. You will certainly notice that "Mutability" is not listed as a feature. OOP is an _approach_. Simply using objects does not mean you are practicing OOP any more than using functions means you are practicing FP.

Dude. OOP is programming oriented around objects. The core feature of OOP is objects. Any feature that an object possesses is a "core property." Also it's a pretty safe bet that anything mentioned in the first paragraph of the Definition of OOP is likely a core property.

>If immutable objects are incompatible with OOP, why is it included in the above?

>Are you suggesting that if I write a Java program and I use all of the features of OOP (inheritance, polymorphism, encapsulation, etc.) but don't use mutability, that my system is better understood as functional?

Yes I am. 100% if you use immutability your program is isomorphic to functional programming. It's included because you CAN do this. Just like how you can do functional programming in a procedural language. If you want to compare OOP to other styles you compare the features that are variant not the features that are identical.

>_This_ is to the point I was trying to make. The above is simply untrue. If I have a function referenced all over my code base, `validate(giraffe)`, and we change the signature to `validate(gorilla)`, it isn't any easier to refactor the system than if it were modeled in OOP.

it is easier. We've talked about the deeper difference. validate in OOP is attached to a concrete instance, it cannot be moved up to a more abstract type without affecting everything it's attached to.

>What about an OOP system that doesn't mutate by design?

You may lack the insight to realize it, but if you are doing this your program is basically a functional one. Your loops become recursion, you become unable to write procedural steps and your methods become isomorphic to stateless functions. You are no longer in OOP land.

>I agree that OOP is worse than FP. There are a few features of FP that make it superior in many respects (notably required immutability and an algebraic type system).

An algebraic type system is not exclusive to FP. It's included in Rust which is not an FP language. It has nothing to do with OOP or FP.

<comment><USER20> >OOP is programming oriented around objects. The core feature of OOP is objects

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)](https://en.wikipedia.org/wiki/Object_\(computer_science\))

>Immutable object: an object set up with a fixed state at creation time and which does not change afterward.

Crystal clear. Even the single sentence in which you are basing this entire waste-of-time argument on:

>A feature of objects is an object's procedures that can access and often modify the data fields of the object with which they are associated

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!).

>if you use immutability your program is isomorphic to functional programming

Being isomorphic to a functional program doesn't mean the program isn't OOP. From the same page above:

>Object-oriented programming is an approach to designing modular reusable software systems

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.

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.

>it is easier. We've talked about the deeper difference

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):

>A stateless function versus a function that carries it's own mute-able state. There is MORE than a semantic difference. The semantic difference you're referring to is when the SELF value is immuteable. In that case the two ways of calling the function become more similar, but THAT is NOT OOP

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 makes a great point (your point), and has actually served as inspiration for my latest side-project. So kudos to you for that.

<comment><USER19> >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)](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.

<comment><USER20> I urge you to attempt to condense your replies into more coherent prose. I'm not entirely sure what my takeaways from the above should be.

You seem to have moved the goalposts again from "OOP requires mutability" (which I think you have given up) to "OOP is different from FP":

>THE CORE DIFFERENTIATOR IS MUTABILITY

Aside from the fact that the above is not true (the core differnetiator is all of those "features" listed in the OOP wiki), I have explained a couple of times now that I did engage in this to argue about the differences between OOP and FP. There are numerous differences, and they have very little to do with my (or your) original claims -- other than the fact that you keep trying to move the goalposts to this topic as a means to say that because OOP is different than FP, `noun.verb` must also be different than `verb(noun)` in terms of modularity/dependencies. You are broadening my claim substantially (straw-man).

Again, this is the claim you made:

>If that method was never unionized with state, if we used smaller subdivisions in our code where state and functions are separate entities then this would be much less of a problem. The function would not be tied to state and that function can be executed in the context of anything.

to which myself and two other commentors sought to clarify. The `function` above cannot be executed in the context of anything. It _must_ be executed from a context that has a reference to `state` (because `state` is an argument to `function`). Notably, this is the _same_ context required to invoke the `method`. Similarly, the context _of_ the `function` and the context _of_ the `method` are the same -- they both have access to the same variables (dependencies). So yes, `noun.verb` vs `verb(noun)` is just semantics; both the surrounding and internal contexts are the same. Choosing one approach to express the behavior over the other makes no difference in terms of modularity/dependencies.

<comment><USER19> >I urge you to attempt to condense your replies into more coherent prose

My prose is coherent. I urge you to gain the intelligence to comprehend it. The only real option is to take english classes. This is not an insult, I see no alternative to help you comprehend english better other than taking a class. Seriously. It's not me, it's you.

> I'm not entirely sure what my takeaways from the above should be.

It's your comprehension that needs work. Re-read it if you can't understand or ask for clarification before you respond. If you have good english then honestly the only other logical explanation is your intelligence. Again not an insult, just observations.

>"OOP requires mutability"

It does THIS NEVER CHANGED. But many methods can be stateless. For your Program to be OOP there must exist methods that mutate state. It IS REQUIRED. If not then you're not doing OOP. Get it?

>Aside from the fact that the above is not true (the core differnetiator is all of those "features" listed in the OOP wiki), I have explained a couple of times now that I did engage in this to argue about the differences between OOP and FP. There are numerous differences, and they have very little to do with my (or your) original claims -- other than the fact that you keep trying to move the goalposts to this topic as a means to say that because OOP is different than FP, `noun.verb` must also be different than `verb(noun)` in terms of modularity/dependencies. You are broadening my claim substantially (straw-man).

Why don't you read my entire claim and respond to each snippet as I have done for you. Rather than take one of my claims ignore all the evidence I provided and go off on your own wild tangent and calling it a straw man. If you want to make my claim a strawman you need to respond to EACH of my points of evidence. I honestly don't even think you read my post. You just did a quick scan and used coherency as an excuse to avoid reading. I responded to your "kudos" as well, which was completely ignored.

>to which myself and two other commentors sought to clarify. The `function` above cannot be executed in the context of anything. It _must_ be executed from a context that has a reference to `state` (because `state` is an argument to `function`). Notably, this is the _same_ context required to invoke the `method`. Similarly, the context of the `function` and the context of the `method` are the same -- they both have access to the same variables (dependencies). So yes, `noun.verb` vs `verb(noun)` is just semantics; both the surrounding and internal contexts are the same. Choosing one approach to express the behavior over the other makes no difference in terms of modularity/dependencies.

Man, we're going in circles. This is crystal clear and you are WRONG. Read all previous post CAREFULLY. Respond to each point if you disagree. The logic is inescapable if you have the ability to follow it. If not this conversation is over.

<comment><USER20> It never ceases to amaze me how transparently people project their insecurities. I read your post. It was far too long, and all over the place. My response was focused only on the aspects I find relevant to the discussion at hand. I do not need (nor have any desire) to pick apart every point you attempt to make, however inaccurate or imprecise I find them to be, in order to compose my argument.

>For your Program to be OOP there must exist methods that mutate state

Provide me with a single resource that supports this claim (emphasis on "must"). I have found exactly zero corroborating sources that affirm the above, but many that (coincidentally enough all agree) mutability is an implementation detail in OOP. As far I have seen your logic is:

1\. Objects _can_ mutate state

2\. OOP uses objects

3\. OOP _must_ mutate state

Something is amiss... But digress.

I have quoted, a number of times now, the single excerpt from your OP to which I sought to add some clarity. I suppose I can do it again:

>If that method was never unionized with state, if we used smaller subdivisions in our code where state and functions are separate entities then this would be much less of a problem. The function would not be tied to state and that function can be executed in the context of anything.

It's rather narrow in focus, and suggests that separating functions and state leads to more modularized/portable behavior. My response is rather simple in substance: Simply reorganizing `noun.verb` to `verb(noun)` doesn't make any difference in terms of modularization. In other words, the `verb` is tied to `noun` in either case.

That is _not_ to say there is no difference at all. In terms of extension (the expression problem) it is well-known that basic OOP and basic FP are complimentary in this regard. Where OOP allows for open extension of data, FP allows for open extension of operation.

<comment><USER19> >It never ceases to amaze me how transparently people project their insecurities. I read your post. It was far too long, and all over the place.

It wasn't. Likely you just scanned it without any real analysis. The post is long because of charity to you. It was done with examples to help YOU understand. I have obviously failed to anticipate the complete nature of your mental aptitude. The logical conclusion is that you likely aren't intelligent enough to comprehend any of this, this is not my insecurity rather more you reassuring yourself that it isn't reflection of your intellectual abilities. Unfortunately, It is.

Also, Nothing was off topic, each part of my response was a reply to each point in your response.

>Provide me with a single resource that supports this claim (emphasis on "must"). I have found exactly zero corroborating sources that affirm the above, but many that (coincidentally enough all agree) mutability is an implementation detail in OOP. As far I have seen your logic is:

>1\. Objects _can_ mutate state

>2\. OOP uses objects

>3\. OOP _must_ mutate state

>Something is amiss... But digress.

I have stated this point a dozen times.

Because we are COMPARING OOP with other forms. The attribute of MUTABILITY must be compared. Because THAT is the form that breaks the isomorphism between OOP and FP. Otherwise we are comparing the Exact Same thing. There's no point. That is the property that breaks the "semantic equivalence" So when comparing definitions you MUST incorporate the property of mutability. It MUST be part of the DEFINITION we compare For this reason otherwise we are comparing nothing.

I used procedural programming as an isomorphic example of this above and the comparison of Human Males and Females. Read it again, it may kick some of those brain cells into gear. You believe that you are putting more "focus" but rather your incapability of understanding things is making you perceive things as off topic.

This conversation won't go anywhere unless you address those topics because what you are doing right now is restating your opinion when I have already addressed why your opinions are wrong. So to move forward you must address why I am wrong about you being wrong. This is how discussions/debates go. That's an extra IQ point given to you for free.

Also big thank you for stealing my idea. You're a real stand up guy.

<comment><USER20> >Because we are COMPARING OOP with other forms

I cannot stress this enough: I am _NOT_ comparing OOP with other forms (in a general sense). I have corrected you repeatedly on this (and pointed out how it is straw-man). My claim that `noun.verb` does not differ from `verb(noun)` in terms of modularity is _not_ that same as the (much broader) claim that OOP is isomorphic to FP. I have never made the latter claim, nor do I believe it to be true [1].

I understand that it does not behoove you to address my argument in good faith, but at some point we have to stop running in circles. Maybe you just misunderstood what I was attempting to say? (this is me giving you a chance to save face)

[1] If I were pressed to describe the relationship between OOP and FP, I would say they are complimentary approaches to designing software (in reference to the expression problem). I _wouldn't_ go so far as to say they are incompatible with one another: [https://stackoverflow.com/questions/3949618/are-fp-and-oo- or...](https://stackoverflow.com/questions/3949618/are-fp-and-oo-orthogonal) (as a matter of sheer coincidence many of the answers also discuss OOP and mutability)

<comment><USER19> >My claim that `noun.verb` does not differ from `verb(noun)` in terms of modularity is _not_ that same as the (much broader) claim that OOP is isomorphic to FP. I have never made the latter claim, nor do I believe it to be true [1].

Yes but the context of the entire thread is OOP. The semantic claim is made in that context. Also intuitively everyone who reads that will think noun.verb is OOP and verb(noun) is not. It's more like you moved the goal posts.

This also contradicts your claim of FP being different from OOP despite semantic equivalence. If there was only a semantic equivalence between noun.verb and verb(noun) then this implies OOP and FP are isomorphic. There is no other way to call functions or methods in either case and therefore they are the same under this misguided logic.

>Maybe you just misunderstood what I was attempting to say? (this is me giving you a chance to save face)

Save face from what? The thousands of people watching this conversation? I don't even care... this is the internet. Nothing was misunderstood by me. You're the one that's misunderstanding.

>If I were pressed to describe the relationship between OOP and FP, I would say they are complimentary approaches to designing software (in reference to the expression problem). I _wouldn't_ go so far as to say they are incompatible with one another: [https://stackoverflow.com/questions/3949618/are-fp-and-oo- or...](https://stackoverflow.com/questions/3949618/are-fp-and-oo-or..). (as a matter of sheer coincidence many of the answers also discuss OOP and mutability)

The expression problem is the same problem in FP and OOP according to your semantic equivalence logic. Simply rewriting noun.verb into verb(noun)and vice versa makes both data and operation problems exist in all forms of programming ONLY when values are immutable.

Another way to put it is that FP/immutability solves the expression problem by allowing you to change between the two styles of organization.

When OOP is immutable the two approaches are not orthogonal, they become parallel or identical. It is only when mutability is forced by only allowing member functions that mutate values rather then return results does the expression problem begin to change. This is when both design paradigms actually change and the dichotomy of the expression problem becomes apparent in the context of OOP and FP.

Stack overflow is even less credible than a medium blog post. There's no reason to resort to what you perceive to be authority to dictate what OOP and FP is. I don't even believe there's an officially sourced definition. All you need to do is take what humans as a majority intuitively understand as OOP and translate that into english. Likely when you ask a typical layman to translate his own intuition he'll get it wrong like the teeming millions on the internet. Just use logic to translate the ludicrous consequences of various "proposed" definitions to see which are valid.

<comment><USER19> You haven't responded which I presume means you've finally been enlightened.

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER21> Bit of a clickbait title... reasonable discussion.

</comment><comment><USER22> They should not have class variables.

</comment><comment><USER23> Cough cough. Seems someone has not really looked at the reality of the field.

Erlang is right there, i advise a look :)

<comment><AUTHOR> The "reality of the field" is that the WWW was/is built with Erlang?

I definitely _did_ miss that.

Back to the drawing board, I guess... ;-)

</comment></comment><comment><USER24> History needs to reevaluate Alan Kay as most of what he said was wrong.

Here is a cringe worth talk from 1997 where he claims the internet is disfunctional because it nit standalone and that all developers should build their own tools and compilers.

[https://m.youtube.com/watch?v=oKg1hTOQXoY](https://m.youtube.com/watch?v=oKg1hTOQXoY)

<comment><USER25> "HTML on the internet has gone back to the dark ages because it presupposes there should be a browser that understands its format."

This is the _fundamental_ reason the modern internet is centralizing to a couple of entities.

"This has to be one of the worst ideas since MS-DOS."

Yes, the modern browsers have taken us back at least 20 years when it comes to UI design, component based programming and distributed systems. The web is an endless stack of kludges, held together by duck-tape. I can back this up, in case you don't believe me.

But, we should ask ourselves how it became such a stack of kludges. And I think Alan hits the nail on the head.

"At the very least, every object should have a URL. I believe every object on the internet should have an IP. It represent much better what the actual abstracts are of the physical hardware to the bits. "

Beautiful insight. The URL does not scale from a systems perspective. In my designs, I see myself often using UUIDs and negotiation to transfer knowledge about entities. The URL (and RESTful communication) is an annoyance. It fixates the location to something arbitrary. I can only use one hierarchy to denote the same object. I cannot easily renegotiate how the same things are named in my systems. And, the worst: the type of the object is often included in the url. `[https://foo.bar/person/123`](https://foo.bar/person/123`) _fixes_ the type 'person' to the object 123.

URLs nowadays are an abomination. Most are not durable, contain excess information and suffer from projecting the information against an arbitrary axis.

Finally, all developers should at least once have implemented their own compiler. It is not a hard experience at all and can be done in around 100 hours by someone with a medium skill in programming using a good text-book. It gives a truly fundamental insight into systems design and should simply not be skipped.

W.r.t. tools: I assume any programmer worth his salt has build at least some of their tools! Perhaps I should start asking this at interviews. If you don't understand how your tools are built, how can you even begin thinking about building tools for others? And how can you understand, without attempting a crude build yourself? All the hard things are already done, the literature is there, the books are written.

So, anyways, you make a bold claim: "most of what he said was wrong." This is awfully vague, I am afraid. Lets make it a challenge. Except for him making predictions, I challenge you to come up with a couple of statements from Alan Kay, and we'll discuss it.

<comment><USER11> > This is the fundamental reason the modern internet is centralizing to a > couple of entities

The reason Google and Facebook dominate the internet has little to do with technology and much to do with economics, namely scale economies and network effects.

> Yes, the modern browsers have taken us back at least 20 years when it comes > to UI design.

I'll grant that CSS is a mess. What else?

> I can only use one hierarchy to denote the same object.

You can create multiple URLs that point to the same object.

<comment><USER25> > The reason Google and Facebook dominate the internet has little to do with > technology and much to do with economics, namely scale economies and network > effects.

And the network effects can only happen because there is a tight coupling between the data (contained and scrambled within the HTML page) and the presentation. Had data and presentation be decoupled, I could have combined network information from various providers and present it to me in one overview.

> I'll grant that CSS is a mess. What else?

Everything. The security model, the fact that the user has limited control over their identity (and it is not build into the protocols), the multi- threaded nightmare, no component standardization, very limited integration with low-level OS systems, the 'one-tab is one context' metaphor, the box- model, the misfit of page-to-interaction (and the history API), the non- existent voice interaction, the color-model, the DPI/pixels/ems transformations, the invisible local storage we barely manage, the resource utilisation, the lack of uniformity in the programming model, the peer-to-peer communication (WebRTC does not count, since it is not standardized and has quite some flaws), the lack of (easy) customization abilities (high-contrast websites), the limited math-rendering, the enourmous complexity... I could go on.

> You can create multiple URLs that point to the same object.

Yes, but they would not denote equivalence. I could use a redirect, but then one system needs to know the representation of the other. It would be fundamentally asymmetric.

Also, it would contradict the term _Unique_ Resource Locator.

<comment><USER11> > no component standardization

This one is interesting because Alan Kay is so expressly against it ("browsers shouldn't have features"). He thinks every object should just render itself as a bitmap.

Besides, browsers do have standard components. That's what the semantic HTML tags like <button /> are. The specific views vary between browsers. Is that a problem? Regardless, almost no site uses the standard stylings that do exist. They use a de facto standard like Bootstrap, or they build their own.

I agree with some of your other points, but I don't understand your lament of "enormous complexity" while you're advocating for more features.

<comment><USER26> One thing about rendering to a bitmap is that it is more robust over time. Look how much code is in the browser to support older styles of html. Smart endpoints dumb pipes, prevents ossification. The browser tries to be far too smart for its own good and ends up making a mediocre job of everything while being hugely complex (as outlined by parent above)

</comment></comment></comment></comment></comment></comment><comment><USER27> Title assumes that Alan did in fact get anything wrong, which is incorrect</comment>