5 ms·
> The protocol method clearly has access to the contents field of the record, scoped by the record definition. Thank you for pointing this out. I have learned
by didibus 8y ago
> The protocol method clearly has access to the contents field of the record, scoped by the record definition.
Thank you for pointing this out. I have learned something today. I didn't know that protocols implemented inline within the deftype and defrecord macros were actually given direct access to the fields. And even more surprising to me, that mutable fields on deftype are actually made package restricted. Well then, I have to concede it to you, even within my definition of OOP, deftype is now an equivalent construct to my concept of objects. Those methods are no longer trait like, they're full blown object methods, with special privileges, and tight coupling to the mutable data fields. They can not be defined separately to the type, and a type can not be extended outside its definition to support such methods.
> I am not saying that traits/protocols/interfaces/typeclasses are necessary for OO, I am saying that they are sufficient.
> Object isn't a keyword in any of the languages we've mentioned. But we know how to find them and what they are. I don't understand why you can't see this one.
So how would you define OO? I get it your are in the camp that equal polymorphism to OO? And by the way, I do see it. Clojure/Script has object-based constructs. If you think of the more general sense for object, which is identity + attributes, records fit the bill. This is defined here https://en.wikipedia.org/wiki/Object_(computer_science)#Object-based_languages https://en.wikipedia.org/wiki/Object_(computer_science)#Obje.... Now, I also agree with you, it even has a construct that groups data and behavior together in the form of deftype with mutable fields. So at this point, it has support for OOP.
What I'm really arguing is just a taxonomy. I see three distinct characteristics. The grouping of data and behavior together behind an object (OO). The ability to dispatch to different implementations of a procedure based on the datatype (type polymorphism). And the ability to inherit behavior from the behavior of an associated parent (inheritance). And this is my preferred taxonomy.
In that sense, prior to me learning about deftype with mutable fields, I saw Clojure/Script as supporting type polymorphism using either protocols or multi-methods. And inheritance through multi-methods. But I did not see anything to group data and behavior together behind an object. Thus I did not consider it had support for OO.
I know some people say polymorphism alone is the essence of OO. Thus Haskell, Rust, Clojure/Scipt, Go, PureScript, and others are all OO languages. I don't know though, I feel the average dev doesn't think of it that way.
Other people think of OO as the bundling of data and behavior, and that seemed much more reasonable to me. This is how the Gang of Four book defines OO for example. And this is how I like to think of it also.
But, after this conversation, I wonder if I don't prefer the definition from the wiki link I shared. Where OOP is the combination of all three. A single construct which groups data and behavior, and allows polymorphism as well as inheritance. And this is what is known as an object, and all three must be present to be considered OOP. With this definition, I think Clojure/Script wouldn't fit as OOP. Since, and tell me otherwise, deftype doesn't support inheritance. And multi-methods don't group data and behavior.
- likeclockwork 8y ago> So how would you define OO? I get it your are in the camp that equal polymorphism to OO? And by the way, I do see it. Clojure/Script has object-based constructs. If you think of the more general sense for object, which is identity + attributes, records fit the bill. This is defined here https://en.wikipedia.org/wiki/Object_(computer_science)#Obje... https://en.wikipedia.org/wiki/Object_(computer_science)#Obje.... Now, I also agree with you, it even has a construct that groups data and behavior together in the form of deftype with mutable fields. So at this point, it has support for OOP. > I know some people say polymorphism alone is the essence of OO. Thus Haskell, Rust, Clojure/Scipt, Go, PureScript, and others are all OO languages. I don't know though, I feel the average dev doesn't think of it that way. I don't think that polymorphism alone is sufficient to be considered OO. I think it's important to recognize you can do OOP without much language support, people even do OOP in C. There's probably someone doing OOP in assembly somewhere. > But, after this conversation, I wonder if I don't prefer the definition from the wiki link I shared. Where OOP is the combination of all three. A single construct which groups data and behavior, and allows polymorphism as well as inheritance. And this is what is known as an object, and all three must be present to be considered OOP. With this definition, I think Clojure/Script wouldn't fit as OOP. Since, and tell me otherwise, deftype doesn't support inheritance. And multi-methods don't group data and behavior. Lets work with your definition.. You concede that all of those constructs group data and behavior, since they let you define a type's methods in a manner that has access to that type's internal implementation. You concede that they allow polymorphism because you can substitute any type that implements the trait/protocol/interface/typeclass. I don't think subclass inheritance is necessary to OO because it's there as a means of expressing type polymorphism and in the class-bases languages it was for the longest time the only way of expressing type polymorphism. So.. what's the difference between participating in an interface/trait/protocol and inheriting from an abstract class? I don't particularly think there is any (some of these languages even have default implementations, including Haskell), you get subtype polymorphism from either.. so in my view the inheritance requirement is met even without a full-blown class hierarchy or deep prototype chain. > Those methods are no longer trait like, they're full blown object methods, with special privileges, and tight coupling to the mutable data fields. They can not be defined separately to the type, and a type can not be extended outside its definition to support such methods. All of the other constructs work the same way, even typeclasses in Haskell. Trait implementations in Rust can have privileged access to private fields. I assume it's the same with Go interfaces. And in Haskell you can't destructure or even construct a type if you don't have access to its constructor--so if you don't export the constructor from your module.. all your fields are private. But you can export a function that constructs the type. You can export the typeclasses. You can export accessors for public fields, and functions to return a modified version of the instance and so forth. > I know some people say polymorphism alone is the essence of OO. Thus Haskell, Rust, Clojure/Script, Go, PureScript, and others are all OO languages. I don't know though, I feel the average dev doesn't think of it that way. Well, they're not all OO languages. They all do have language level support for all of the concepts that OOP is made of and you can use them to do Object-Oriented Programming even though some of them are clearly Functional Programming languages. OOP means classes and nothing else in the mind of the average dev. In my opinion it's really just a pattern that you can apply/implement anywhere with more or less support from the language and in sufficiently flexible languages you can even build your own object system and it might even be nice to use. Supporting OOP doesn't make a Functional language not-Functional, or even a multi-paradigm language. No one would call Haskell a multi-paradigm language, yet it has language level support for OOP. Classes and FP don't really mix, but OO in FP works and doesn't have to compromise the FP paradigm. OO isn't something you need to dedicate an entire language to in order to use or benefit from.