Author finally opened his eyes.
Looks rather like eyes closing to me.
Java has single inheritance, which sucks; but it has multiple inheritance of interfaces at least, and good luck doing any serious work in Java without that being involved. (That is also designed that way in order to pander to implementation ease and certain run-time efficiencies; but has been turned into fallacious arguments like "multiple inheritance is bad ... unless it's interface inheritance").
Oh, and one problem with this prototype business is that in fact it is single inheritance (in the typical incarnations, at least; am I invoking a strawman)? It seems inescapable that supporting multiple inheritance under the prototype paradigm requires that we make a single new object out of two or more existing objects. But if objects are effectively just bags of properties (a.k.a. hash tables) it does seem easily doable. Make new empty object, stuff with properties of all argument objects, season to taste, return.
The next level of enlightenment is figuring out that applied FP isn't that great either and to use whatever makes sense, wherever it makes sense.
Sometimes opinions are great to get everyone on the same table even if for some usage, some things might not be appropriate.
I think opinions generally achieve the opposite of that. That said, if you're sitting at the table where everybody believes in FP, you should wholeheartedly apply FP principles - or find another table. That's part of "do what makes sense, where it makes sense".
The really good thing about OOP though is that nobody really believes in it anymore. That opens up the opportunity to take some good ideas and insights and apply them undogmatically.
FP has good ideas and insights as well, but it's more difficult to separate those from the cargo cult surrounding it.
In JavaScript you have precise control over inheritance, you can specify your own algorithm for how class A inherits from classes B and C. It's a totally different beast to classical inheritance in Java that has such a bad reputation because it's such a straightjacket
> In JavaScript you have precise control over inheritance, you can specify your own algorithm for how class A inherits from classes B and C.
Yeah maybe, but please don't do that.
Language flexibility doesn't obscure the readability of code. It enhances it. In a flexible language, unclear code is always programmer error, and programmer error is fixable. In an inflexible language, a lack of clarity can sometimes be unavoidable (e.g. java programmers forced to shoehorn everything into classes)
I don't find it shocking, I think it's a sign of immaturity. Been there, done that.
> Language flexibility doesn't obscure the readability of code. It enhances it.
Given a language without any sorts of constraints, any program can and will be written in any conceivable style.
In design - not just programming language design - constraints are generally a good thing.
> In a flexible language, unclear code is always programmer error, and programmer error is fixable.
Virtually all errors are fixable in principle. In practice, there's a budget. Your clever and elegant but utterly idiosyncratic abstractions are costing me money in terms of getting people onboarded.
> In an inflexible language, a lack of clarity can sometimes be unavoidable (e.g. java programmers forced to shoehorn everything into classes)
This is not a bad trade-off at all.
A flexible language invites architecture astronauts to re-invent the concept of classes or modules over and over in slightly different ways. That's Javascript until ES6 and we're still suffering from it.
The best example of that in programming language design I have seen is the V programming language. (https://vlang.io)
No global variables, no null/undefined/nil/None/... V is the only language I know in which variable shadowing is an error. (Do you know any other language with this feature/constraint?)
And then I remember the handling of ''var''s in js and hoisting etc. ... sigh!
gcc -Werror=shadow
Demo: $ gcc -Werror=shadow -x c -
void foo(int x) { { int x; } }
[Ctrl-D][Enter]
<stdin>: In function ‘foo’:
<stdin>:1:25: error: declaration of ‘x’ shadows a parameter [-Werror=shadow]
<stdin>:1:14: note: shadowed declaration is here
cc1: some warnings being treated as errorsI did not dare to open the gcc man page, now I think I will look at it.
For that constraint, one have to pass an option. I want to know if any language (other than V) which has this as default.
Yes, to hack up, so what? Non-prototype object systems can also be written simply and in a small footprint, and have a reasonably small description.
A prototype object system is barely one step above pretending that a hash table is an object.
2. It's powerful.
It's not expressive of OOP concepts and creates spaghetti code. All OOP is monkey patching: make this object like that one, but patch this.
3. It leads to smaller, less redundant code.
Because you're not properly specifying classes, which serve as an important guide to the structure of your program, and provide a locus of control.
We can achieve smaller and less redundant code by identifying every function that is only called once and manually inlining it, so there is no name that is redundantly mentioned two places in the program. That doesn't mean it's a good idea.
4. It's dynamic and hence it's better for dynamic languages.
This point is subtly fallacious. Dynamic languages also have non-prototype based object systems, which are also dynamic and good for those languages. There is good dynamic and there is bad dynamic.
Under prototype object, it's hard to do certain important dynamic things like redefine the method of a class such that all objects of that class (existing instances) use the new method.
Non-prototype objects systems in dynamic languages can easily support prototype-like mechanisms without those being the main mechanism of organization of OOP programs.
Failing that, in any dynamic language that gives you hash tables, you can ignore the fine OOP system and do prototypes with hashes.