> I'd say traits in Rust, typeclasses in Haskell and Scala imlicit views are the equivalent to Clojure/Script protocols. And similarly, those constructs by themself aren't OOP. I think a simple proof is that if they were, then all OOP languages would have them. But because there are OOP languages (the most popular ones at that) which don't have them, then it follows this construct is not fundamental to OOP.

This seems completely circular to me. Your definition of OOP is really "whatever all OOP languages do"?

> I'm not sure I'm explaining myself very well. Think of an object. The object defines some data fields. And it defines some methods together. You can't use those methods with other objects. The ownership is tied to the object that defined them.

In Clojure you can't use a protocol method on a type that doesn't implement that protocol. I don't see it as being that different from D's Uniform Function Call Syntax (a free function can be called as a method of its first argument and vice versa.)

What is OO to you? Is it Class Oriented Programming? Is it a programming paradigm or is it the list of features and practices common to a family of languages? Almost no common OO languages treat method calls as messages. It's just a function call with a (usually) hidden 'this' parameter. Applying a protocol function to a record that implements it isn't really any different, from a perspective of message passing. A message is passed to the record and based on its pedigree it decides how to respond.

Plenty of OO languages don't have private data and allow direct access to object fields. Arguably, by your definition, it isn't OO at all to even provide for public fields. As long as the methods follow the data around or vice versa, in my view, encapsulation has been achieved. Enforcement is another concern, but it's not Jail Oriented Programming so I don't see that enforced encapsulation is a necessary condition for OO.

A record implementing a protocol can receive method calls. All of its method implementations happen with the records own fields in scope (assuming you define them in the defrecord). It doesn't need to restrict access, if you'd like it to have private data.. respect its privacy and don't look.

As I understand it, the state of the art in Class-Oriented Programming has been to define interfaces for everything, and then define classes that implement those interfaces, and then use the interface to type functions and methods. A Trait in Rust or a Protocol in Clojure just knocks out the middle man, the unnecessary and unwanted class. What's left is still OO, you can get rid of the class and all of it's baggage and still have plenty of OO left.

> A record is a set of key/value pairs with an associated type. A Person record defines a type Person, with keys Age and Weight and their values. That's all a record does. It can't restrict access to its data, it can't expose methods, and it can't receive messages (method calls). You can now write functions that take input of this new type. Those functions can be defined anywhere. They have no special access to the data inside Person, there's no `this` or `self`. The functions don't live inside the datatype. Now, if you want a common set of functions to work over many different types, you can specify a protocol. That's all a protocol does. This is just functional programming.

This, to me, is a description of object-oriented programming without the class ceremony. It's also functional programming. The use of records and protocols is functional programming, but the constructs themselves have OO nature. I don't think functional programming and object oriented programming are in opposition to each other. I think functional programming and mutable state heavy/class-happy programming don't mix but the latter is not my definition of OO.