So which languages are left without object systems?
So which languages are left without object systems?
At minimum, I'd say an object system needs some form of messaging and state hiding. That is, an object holds hidden state, and responds to external messages.
I advise some reading "The Art of the Metaobject Protocol", or similar literature.
In some cases, the only way the features of some UTM A's architecture will be obtained through UTM B, is if UTM B is used to create a simulation of UTM A, and so then that provides a way to execute the UTM A instructions themselves. In that situation, UTM B itself has not acquired the features of UTM A.
A UTM can take an instructional input which turns it into a different machine, which can then process tapes designed for a different TM mechanism.
A fixed programming language (and its standard library) is a UTM. If there are regular expressions in the language syntax, or the library, it's a feature of the UTM.
Everything else is instructions: additional libraries, macros, whatever.
We can extend languages by pretending that the additional code we have written (libraries, syntax rewriting) comprise a new, extended language. So that's a new UTM.
There are limits in what syntactic rewriting can provide in a seamless, efficient way. Some features are simply not expressible in the target language of the rewriting, other than by using the syntax to create an inefficient, interpreted language. The use of the features it provides is walled off within the embedded syntax. (Not to deny that this is nevertheless valid and practically useful.)
The UTM theory tells us that we can always adapt a UTM to accept the tapes intended for any TM mechanism. However, it doesn't tell us how costly that is. For some TM mechanisms, the approach may be to translate a given tape up-front into the UTM's own instructions and then run it directly. For some TM mechanisms, the approach may be to simulate the mechanism: the UTM's instructions execute the simulator, which executes the tape. The UTM theory mostly talks about simulation.
What we know is given a Turing Complete language A (i.e. a UTM) we can always write an interpreter for language B. That's the baseline. We then have a new UTM equivalent to B, consisting of language A, plus the interpreter. That setup then accepts programs of language B, and their inputs.
By "the library" do you mean the core library of the language?
If a language didn't have regular expressions as part of its core library, does that mean regular expressions would not be a feature of that language?
> Some features are simply not expressible in the target language of the rewriting, other than by using the syntax to create an inefficient, interpreted language.
Why inefficient? Why interpreted? What if the syntax was efficiently compiled?
I use Clojure a fair bit, and that has a miniKanren implementation in the form of core.logic. Would I say that makes Clojure a relational programming language? No, I don't think so, because it's not part of the core language.
Similarly, there exists an optional static typing library for Clojure called core.typed - does that make Clojure a statically typed language? Again, I don't believe so.
You can build a library to implement any feature, particularly in Lisps or other languages with support for AST transformations. Those features may even be counter to the core design of the language - you could write a library in Haskell to support dynamically typed, imperative programming, for example.
The difference between them are important to some people. And that's why they will argue for that.
So they argue with knowledge based on Internet facts instead of actual CS literature.
Classes binds data and functions together, and object systems supports inheritance. These are some of the things that some people don't really like, but you may not care. People sometimes care about syntax as well, writing "Class" is also part of the experience of using the language.
We have different words in the language for a purpose, that's my opinion.
Not all object systems use inheritance, and even those that do, we can speak about delegation, interface/trait/protocols/type classes inheritance, regular classes inheritance, or some weird stuff like object patterns from BETA.
That is why we have CS literature, to put the right words in place.
As you said, there are a lot of object systems that are different, and the difference matters. Having inheritance or not matters. I was just making examples to show that things are different.
We all know that C++ concepts != go/typescript interfaces != Java/c# interfaces != Haskell type classes (c# concepts) != rust/scala traits.
Try to explain that using "CS literature", maybe a lot of language designs don't have a word yet made for that. Yep there are Subtyping, Bounded quantification, Ad hoc polymorphism, Row polymorphism, but still not enough to tell all of them from each other.
But to anyone in the community, people all know that they are all not Classes and what make them special is important. It is quite clear, but why don't you get that?
The concepts CS literature are quite trivial and people can spend a few weekends to learn, or maybe another few for type rule syntax or a few others for basic category theory to understand them in a more intuitive way. But the real problem of making a good language for some applications is still there and much more complex and difficult. And maybe current literature are not enough for that.
The elites will never dictate the words, the people will pick up whatever they want to express their knowledge anyway, as we know of what happened in history.
As for ML functors: they're neither polymorphism, nor dynamic dispatch. First: functions for different types can't share names (unless we're talking about shadowing of names with lexical scope), the names are either qualified with the name of the struct they come from or they're not qualified at all. In all cases there is exactly one implementation for every name. And again: no dynamic dispatch. MLton even defunctorizes all code at compile-time. The only polymorphism in SML is the one that's used in some built-ins (like +), but it's not available to users of the language. SML has something called "polymorphic functions", but it has nothing to do with writing multiple implementations of one function under one name and letting the compiler select which one is called; which is what is usually meant by "polymorphism".
If I have time later I might post an example, apparently we are only right with code.