It was great to have different languages having different paradigms but now you can do everything in everything and code bases I'm working on are a confusing mess.
It was great to have different languages having different paradigms but now you can do everything in everything and code bases I'm working on are a confusing mess.
There are other languages on less-shaky foundations, but people don't use them for various legitimate and illegitimate reasons.
Languages are effectively immutable. Unless you can reach out and edit every single piece of code that breaks when you remove a feature, you can't remove a feature from a language. You can only create a new, almost identical language, and then spend a decade migrating people. This is what happened to Python2/3.
Very few things have been successfully deprecated in C or C++. Even massive security holes in the standard library.
Thats demonstrably false. Python was a loud transition, but most of the language warts and syntax is still there. Same as the Php and perl transitions and the wacky es6 or java. The list goes on.
> > new, almost identical language,
Emphasis added.
Either it means it's a different language or it's a new language. The ambiguity in interpretation leads to a statement of non-meaningful change (tautology) or a statement of important change. The gracious interpretation is the only thing worth responding to, not quibbling over the possible non-statement.
Nitpick (and also proving your point): there is no language Python2; you mean Python vs Python3.
Think of programming languages as a seminar where designers are crafting that Ur-language between themselves, and folks like me in the peanut gallery look on.
C++ wasn't the first multi-paradigm language, and it won't be the last.
AFAIK Lisp is not that low-level, Object Pascal is okay but generics/codegen are 20 years too late for example, PL/I is a pile of every known feature at the time by design but it's hard to tell now.
Honestly I’ll be deeply ashamed as a Python programmer writing cascading ifs when even C++ gets pattern matching. (Yeah, I know all the arguments against it.)
What I meant is the language does not force this on you as The Right Way To Do Things™ and thus it mostly boils down to organizing with peers and agreeing on a consistent set of guidelines (which goes well beyond language features...)
C++ is a huge, complex language. It's probably its greatest downside. Making it even more complex, should only be done with very good reason.
If you doubt this, consider the continued popularity of C, a thoroughly anaemic language by today's standards, with no clear advantages over C++ except for its simplicity, minimalism, and that the language changes very slowly. Well, that and its existing adoption levels. It's not quite the case that every feature C has is also in C++, but it's very close, and I can only name one exception: variable-length arrays (an unpopular addition to C) are not officially supported in C++.
C++'s complexity means that:
* It's very difficult to learn. It's extremely difficult to learn well. It's just about impossible to learn in its entirety. This isn't an exaggeration. (Andrei Alexandrescu might be the closest we have to someone who knows all of C++. He's a world famous C++ expert. Mortals don't stand a chance.)
* Different C++ programmers know (and write in) different subsets of the language. Good C programmers know essentially all of C. (I'll admit I'm weak on C's bitfields, and I couldn't tell you every subtlety of its memory model, but when it comes to C++, there may be areas of the language I've never even heard of.)
* C++ style guides (such as Google's one, or LLVM's one) are long and complex documents, by necessity
* We will never have a fully complete C++ compiler that truly matches the language spec. This undermines the spec; the language you're really using depends on your C++ compiler. To put that another way: portability is harmed because different C++ compilers cannot be relied upon to support the same language features.
* C++ compilers are more prone to arcane bugs, than C compilers
* Different C++ compilers have different arcane bugs, harming portability
* It's far easier to develop tools for C than for C++ (compilers, IDEs, etc)
* There are more C compilers out there than C++ compilers, especially for targets like PIC, or for very obscure platforms, or for particular needs such as safety-critical work. There's even a formally verified C compiler ('CompCert') with near-complete support for C99's features. I doubt there will ever be a formally verified C++ compiler.
* C is easier to mechanically reason about; there are more static-analysis tools for C than for C++
* If C++ were simpler it might have given rise to stable ABIs, the way C has. Instead, even different versions of the same C++ compiler might not be interoperable.
* It's less predictable regarding performance. Template metaprogramming can bloat your binaries for seemingly no reason. In C however, all features of the language map naturally to assembly; the programmer can generally predict roughly what assembly will be generated. This matters to those working with operating systems, graphics, high-performance programming, or where side-channel attacks are a security concern.
C++ is also faster-moving than C, meaning:
* It takes more work to maintain your skills for reading other people's code
* Code can age. Old code looks different from new code, unless it's actively maintained, which means work and risks new bugs. If the language rarely changes, this problem goes away.
* If you're developing a compiler, you'd rather a stable language like C, so that you don't have to make a career out of keeping up with the latest additions to the language. Keeping up with the additions to C++ is more than any one compiler-engineer could hope to do.
There are very few 'conservative' languages like C (there are also Scheme and Forth), but it can be a language's greatest strength. Zig is hoping to be another such language, but we'll have to see if it succeeds.
With all of that said, I tend to favour C++ over C, and I really like pattern-matching. It's something that cannot really be 'faked' with templates or macros. (Another personal favourite feature of mine, named arguments, is similar in that regard.) I think it's rather silly that the major OOP languages have until recently completely ignored this brilliant language feature from the functional programming world, as if it adds nothing over switch/case. Even D, an extremely feature-rich language, still lacks pattern matching.
Go is a simple language, no?
It's higher-level than C, but no historical baggage, so probable comes out to the same complexity to fully understand the language.
I don't think you can do everything in everything. Try working with lazy immutable data structures in Rust, for one.
Or look at Dart - now has "non-nullable types," monadic error handling (sort of), but of course the whole thing is on shaky foundations so what's it worth?
Why is that an issue?
Hiding the fact that a lazy value needs to be mutated to initialise it is a little more work (since a nice API lets the user treat the value as if it doesn’t need to be mutated), but is certainly possible.
It's not proper laziness as defined in Okasaki's thesis/book. One needs more complex things like lazy finger trees.
The language is not.
If you can implement lazy finger trees with iterators I'd love to see it :)
I don’t think this is that hard; you “just” need to construct the data structures as elements of an object-graph data structure, and then retrieve your data through an explicit thunk of the object-graph itself.
In lazy languages the object-graph data structure is implicit, but that doesn’t mean that the Rust version of the call site code needs to be any more verbose. It’s just the definitions of the data structures themselves that would be more unwieldy. (And you could probably build some generic lazy container types and mostly work with those.)
Think: what Objective-C does with autorelease-pool objects.
Maybe think of language design as a search thru an n-dimension problem space.
There's the perennial trilemma of functional (LISP), imperative (APL), and object oriented (Simula), where your new language lands somewhere within that triangular design space.
Then add extra dimensions for type systems. Nominal vs structural vs whatever.
Then add some more for ideas swiped from declarative (SQL, VRML, LINQ), stack-based (Forth), REPLs (Logo), constraints (Prolog), and whatever else people cook up.
Ya, the churn is nutty making. But it's also awesome at the same time.
by each other you mean the ml world right ? :p
Some subset of features inspired in them are used in some languages, but that has nothing to do with functional programming taking over.
Where'd that come from? I thought that was monadic-do from Haskell.
Sure, you can still build object components, but it's informally frowned upon.
I think we have wildy different definitions of FP.
No one with old C++ code is going to switch to these future hipster standards, let alone even C++14.
I think this standard bloat is digging its own grave. It will have the opposite effect. People who want the new shiny stuff will use the new shiny thing (Rust). The old timers will stay on C++11 all the way to 2070 when a man or machine finally rewrites everything in $(new lang).
If there's a good idea, why not use it?
When you have a syntax that you like for whatever reasons (including because you have a lot of legacy code written in it) it makes sense to extend the syntax where possible to make it more convenient if you can do so within the constraints of performance.