3 ms·
Which new languages are you talking about here? The new languages I'm familiar with (which, granted, are mostly from the period between like 2008 and 2013, so m
by sanderjd 3y ago
Which new languages are you talking about here? The new languages I'm familiar with (which, granted, are mostly from the period between like 2008 and 2013, so maybe you're talking about much newer ones...) all seem very steeped in familiarity of historical languages. For instance, this article mentions Rust's hygienic macros, which were certainly developed with knowledge of Scheme's earlier work on that.
- adrian_b 3y agoRust is one of the typical examples that I had in mind. While it has some very nice features, they are combined with ugly mistakes inherited from languages such as C. For instance the need of using the address-of operator for function parameters passed by reference is ugly and pointless. Moreover, the distinction between parameters passed by value and parameters passed by reference is a big mistake in the design of a programming language. Already in July 1977, the DoD Ironman requirements for computer programming languages have shown the only right way of classifying function parameters, i.e. in 3 kinds, in, out and in-out (this had been inspired by the language Jovial, previously used in some DoD projects, but Ironman has improved upon the Jovial version of parameter specification). When any function parameter is specified as belonging to one of these three kinds, then it is irrelevant whether they are passed by value or by reference. That is an implementation choice that belongs to the compiler and which is completely transparent for the programmer (e.g. the programmer does not care whether an in-out parameter is passed by reference, i.e. the function receives a pointer which it uses to modify directly the parameter, or it is passed by value, when the function receives a copy of the initial value of the parameter and at function exit the final value of the copy is copied back to the caller). Besides the burden imposed on the programmer to care about how parameter passing is implemented, the failure to adhere to the Ironman requirements may cause serious performance degradation. The ugliest parts of C++, which, especially before 2011, were frequent causes of confusions, bugs and low performance, derive from the failure of C++ (inherited from C) to distinguish the out parameters from the in-out parameters. To work around this misfeature, which is especially important for an object-oriented language, C++ had to invent some kinds of constructors that would not have been needed otherwise, it also had to handle constructors in some special ways, different from the other kinds of functions, and then it had to continue to invent new tricks for fixing performance problems, like move semantics. The inappropriate way of classifying function parameters is just one example of many programming language defects that are still widespread even if the right solutions were known fifty years ago. It would take more space to explain the implications for OOP of distinguishing out parameters from in-out parameters, but the main result is that many redundant operations are avoided automatically and effortlessly, while the C++ compilers have needed several decades of improvements until they have become sophisticated enough to avoid such redundant operations when handling big objects, like in libraries that implement operations with matrices and vectors, and the compilers still need considerable help from the programmer, who has to specify details that should not have been his or her concern.
- sanderjd 3y agoRust's design and development was incredibly informed by knowledge of programming language history. People making different judgments and decisions than you would have made is not necessarily evidence that they are less knowledgeable than you, it is often the case that they have just come to different conclusions than you have. That's why there isn't one perfect version of everything; similarly knowledgeable and well-intentioned people often prefer incredibly different answers to the same questions. It's kind of surprising, maybe, but it's also why humanity is so interesting and varied; why we have so much different kinds of art and music and architecture and stuff. 100% of your examples are things that you seem to think have exactly one correct answer, but which people actually have different preferences on and different reasons for choosing different approaches. I promise you that Graydon Hoare was familiar with the concept of in, out, and in-out parameters when he started working on rust. None of this means that any language is perfect, it's just that you're ascribing things to ignorance that are far more likely to reflect differences of opinion on subjective questions.
- adrian_b 3y agoI agree that many differences between programming languages are differences between programming styles where it cannot be said that one variant or the other is definitely better, but only that one variant is more suitable for some people while the other variant is more suitable for other people. Nevertheless, I have been careful to not choose an example of this kind, but one where there is no doubt about what is right and what is wrong. I am curious how do you justify that it is a good thing for a programmer to waste time to think whether a function should be invoked as f(x) or f(&x) and to waste time and page space with writing and reading "&" symbols, when this wasted time cannot bring any contribution to solving whatever problem needs to be solved. Choosing whether to pass parameters by value or by reference is a problem of the same nature as the allocation of the hardware registers, which does not belong to a high-level language. The C keyword "register" is now obsolete, but the parameter-passing method should have become obsolete at the same time. Of course, for this to become possible, the direction of the parameters must be specified, to allow a correct compiler decision. When the direction of the parameters is specified, "const" no longer needs to be specified, because it is implied by "in". Moreover, like I have said, any language that does not distinguish out parameters from in-out parameters, but which nonetheless allows the definition of new data types, together with mechanisms for their allocation, initialization, and deallocation, becomes excessively complicated, because it must add a special kind of functions that support one "out" parameter, i.e. the constructors, despite the fact that normal functions do not support such parameters, and then for each new type several kinds of distinct constructors and operators are needed, e.g. copy constructor, move constructor, assignment, which would not have been needed otherwise. When out and in-out are distinguished, assignment is not an operator, like in C++, but only a syntactic separator. In languages like C++, the programmer also needs to annotate some operations, so that they will use the kinds of implicit constructors that will be efficient in that context. So if the defined data types can be used in any ways in which primitive types are used, then the mess of C++ is unavoidable. If there are restrictions on how the defined types are used, e.g. when operators cannot be overloaded or when various other such restrictions are enforced, then some of the complications of C++ can be avoided but such restrictions are even less desirable. So between a single super simple rule of specifying in all function prototypes whether the parameters are in, out or in-out and having to keep in mind a great number of rules of how to deal with constructors in general and with several kinds of special constructors, in order to achieve acceptable performance when handling large objects, I do not see how there can be alternative views about which is right and which is wrong, except when they are based on lack of familiarity with the right solution. When out and in-out parameters are distinguished, there are no constructors as a special category and no worries about them. An object can be initialized with any function that has an out parameter of the correct type. The only constructor is the default constructor, which is an ordinary function that needs to be specified only so that the compiler will invoke it implicitly when there is no explicit initializer.