The compiler should just know these patterns when it sees them being used. They don’t need extra keywords.
That sounds like a footgun. Without a thorough understanding of these implicit rules (e.g. as somebody who doesn’t write much code in this language) it’d be hard to keep track and easy to make mistakes where the compiler can’t infer what your intention is. Those keywords are both for the compiler to verify that a class doesn’t violate those rules and for the reader as documentation.
For an example, Swift has a no-op keyword that is for the reader only: You have to write try in an expression containing a function call that can throw. Therefore you can see all the statements where code might escape regular execution paths. In the end that’s pretty rare, and I feel more confident about exception flow than in other languages. You don’t get the feeling that it might throw from anywhere.
The common factor in all of these is keeping the language purely OO (not “multiparadigm”), but merging functional features into its type system while implementing them in an OO way.
There’s room for different kinds of OO languages for different use cases. We’ve had a lot of OO dynamic languages like the ones you name, but they’re not good for systems programming. (GC and JIT are big obstacles.) There’s been a resurgence of new systems languages in the last decade, but most of them threw out real OOP.
Interfaces alone get you part of the way there, but in the couple years I spent working in Go I found that they have limits and things get really messy if you try to go past them. Swift has real OOP in its classes, but not in structs, which is awkward.
Oh, I’m not interested in the dynamically-typed, GC’d, or JIT’d nature of most smalltalk-family languages paticularly (Though Java and Scala are both dynamically typed, GC’d, and JIT’d also…) but their approach to OOP.
What are the OOP features from ST that you feel are missing in Java etc.? I used ST80 for a few years back in the ’80s; my answer would be “everything is an object”, “messages as first-class entities that can be sent anywhere”, and “updating methods and classes on the fly”.
For the most part those lend themselves to dynamic scripting-type languages, particularly the first. Objective-C does incorporate the latter two in a native-level language.
“everything is an object” is a big one, of course. Nothing that prevents a statically-typed or even stack-allocated language from having that work.
“message sending” is also do-able. There are a few options here, including requiring that the message symbol be a literal somewhere and then tracing it statically to do the dispatch (wouldn’t allow dispatch based on just grabbing user input and stuffing it into a message name, but otherwise it would work fine).
A big one for me is “objects are easy to make” – Java more-or-less maps classes to files for example, which is a huge friction for newcomers to creating more objects.
However, none of the above is the big thing I think I had in mind when I posted my comment, which is the culture and practise of a language. Could I write highly object-oriented code in Java? Especially newish Java versions? I can probably get close in many cases, or even all the way there in some. But will I? Will any of the code examples I read lead me in this direction? Studying Java to learn OOP isn’t bad primarily because Java is bad but because the Java code you encounter is unlikely to be very OOPy, and is at best likely to think it is OOPy in ways that you have to un-learn.
You claim that you got rid of object, but you reintroduction static, which is object, but worse. I think object was an important improvement Scala did, because it cleanly separated two different kinds of methods.
I like [] for generics. It’s great that the language parser can disambiguate the different uses of () … but why? And are you sure a reader will also be able to disambiguate as easily as the parser does?
Class.new(x) is an improvement over new Class(x), but I’d drop new altogether and do Class(x).
No exceptions is the right choice.
This reads counter-intuitive: listOfInts.List(Add)\fold(), because List isn’t a member of listOfInts, but fold clearly is. Why not listOfInts.fold[Add]()?
The problem you mention regarding dynamic vs. static dispatch is the reason why I wouldn’t want extension methods in the language.
I also adopted as in pattern matching, similar to your example, but being able to leave out the names to be bound does not feel like an improvement to me. This is really dangerous because it breaks silently when the type’s author changes the member name and some other value is in scope.
Personally, I’d want to go a step further and unify if-expressions and match-expressions:
if Some("foo")
.. as Some($value) then print(s"got some $value")
.. as None then print("got nothing")
It is time for OO languages that have ML assistants assumed in the design. Tools that automatically recognize similarities and patterns and simplify your code.
I would have also liked to hear why the author thinks OOP should be revived. The list at the beginning and most of the article is focused at fixing the warts, but I wonder what the author thinks the advantages are.
That sounds like a footgun. Without a thorough understanding of these implicit rules (e.g. as somebody who doesn’t write much code in this language) it’d be hard to keep track and easy to make mistakes where the compiler can’t infer what your intention is. Those keywords are both for the compiler to verify that a class doesn’t violate those rules and for the reader as documentation.
For an example, Swift has a no-op keyword that is for the reader only: You have to write
try
in an expression containing a function call that can throw. Therefore you can see all the statements where code might escape regular execution paths. In the end that’s pretty rare, and I feel more confident about exception flow than in other languages. You don’t get the feeling that it might throw from anywhere.Ah yes a lot like trying to program in rust. Moving away from explicit ownership annotations was a crazy move.
I’d love to know what the author thinks of Swift.
Here you go. :)
https://www.reddit.com/r/ProgrammingLanguages/comments/m479v3/comment/gqsurg3
Much obliged!
I wonder if OP has an opinion on Pony lang, One of the newer, and more refreshing takes in OO offerings
If you want to do OOP and your inspirations are Java, C#, and Scala, you’re starting from a pretty low and non-OOPy point.
Design for a new OOP system needs a healthy dose of smalltalk family (ST80, ruby, Self, etc) to have a prayer.
There’s room for different kinds of OO languages for different use cases. We’ve had a lot of OO dynamic languages like the ones you name, but they’re not good for systems programming. (GC and JIT are big obstacles.) There’s been a resurgence of new systems languages in the last decade, but most of them threw out real OOP.
Interfaces alone get you part of the way there, but in the couple years I spent working in Go I found that they have limits and things get really messy if you try to go past them. Swift has real OOP in its classes, but not in structs, which is awkward.
Oh, I’m not interested in the dynamically-typed, GC’d, or JIT’d nature of most smalltalk-family languages paticularly (Though Java and Scala are both dynamically typed, GC’d, and JIT’d also…) but their approach to OOP.
Agreed. I’ve been interested in Crystal for this reason.
What are the OOP features from ST that you feel are missing in Java etc.? I used ST80 for a few years back in the ’80s; my answer would be “everything is an object”, “messages as first-class entities that can be sent anywhere”, and “updating methods and classes on the fly”.
For the most part those lend themselves to dynamic scripting-type languages, particularly the first. Objective-C does incorporate the latter two in a native-level language.
“everything is an object” is a big one, of course. Nothing that prevents a statically-typed or even stack-allocated language from having that work.
“message sending” is also do-able. There are a few options here, including requiring that the message symbol be a literal somewhere and then tracing it statically to do the dispatch (wouldn’t allow dispatch based on just grabbing user input and stuffing it into a message name, but otherwise it would work fine).
A big one for me is “objects are easy to make” – Java more-or-less maps classes to files for example, which is a huge friction for newcomers to creating more objects.
However, none of the above is the big thing I think I had in mind when I posted my comment, which is the culture and practise of a language. Could I write highly object-oriented code in Java? Especially newish Java versions? I can probably get close in many cases, or even all the way there in some. But will I? Will any of the code examples I read lead me in this direction? Studying Java to learn OOP isn’t bad primarily because Java is bad but because the Java code you encounter is unlikely to be very OOPy, and is at best likely to think it is OOPy in ways that you have to un-learn.
This is what I wrote elsewhere:
\
as a namespace operator is weird. Simply use.
.You claim that you got rid of
object
, but you reintroductionstatic
, which isobject
, but worse. I thinkobject
was an important improvement Scala did, because it cleanly separated two different kinds of methods.I like
[]
for generics. It’s great that the language parser can disambiguate the different uses of()
… but why? And are you sure a reader will also be able to disambiguate as easily as the parser does?Class.new(x)
is an improvement overnew Class(x)
, but I’d dropnew
altogether and doClass(x)
.No exceptions is the right choice.
This reads counter-intuitive:
listOfInts.List(Add)\fold()
, becauseList
isn’t a member oflistOfInts
, butfold
clearly is. Why notlistOfInts.fold[Add]()
?The problem you mention regarding dynamic vs. static dispatch is the reason why I wouldn’t want extension methods in the language.
I also adopted
as
in pattern matching, similar to your example, but being able to leave out the names to be bound does not feel like an improvement to me. This is really dangerous because it breaks silently when the type’s author changes the member name and some othervalue
is in scope.Personally, I’d want to go a step further and unify if-expressions and match-expressions:
No multiple dispatch?
It is time for OO languages that have ML assistants assumed in the design. Tools that automatically recognize similarities and patterns and simplify your code.
I would have also liked to hear why the author thinks OOP should be revived. The list at the beginning and most of the article is focused at fixing the warts, but I wonder what the author thinks the advantages are.