Yeah, we get it that functional languages came first, but rather than looking down on C++ why not celebrate that functional constructs are making it into places where they haven't been before.
Because that's a meaningless thing to celebrate? Having functional concepts available in a poorly integrated way, with super ugly syntax is more depressing than anything, because seeing it in use is a reminder of how much cleaner it would be in a language like Haskell or OCaml.
Why not accept that C++ isn't a functional language, and realize that many die-hard C++ users won't use these features for the same reasons they're not already using functional languages.
I'd rather see these efforts directed towards improving the compilers and libraries for languages like Haskell, OCaml, etc.
I swear I remember fans of older OO languages saying the almost exactly the same thing with "object oriented" in place of "functional" about the way C++ grafted OO concepts onto C when C++ was new -- and, IMO, with good justification. Still, C++ was not exactly unsuccessful with that, either.
I'm a die-hard C++ user, and have come to love functional programming for a very C++y reason: improved performance that comes from lock-free parallelizability (if you never modify values, you don't have to synchronize access).
But I also love the simplicity that comes from not having to think so deeply about lifetimes and which portions of code can see which objects in which states. The abstraction of data-structure from algorithm is nice, the terseness is nice, the regularity is nice, but it's the lifetime and visibility simplification that helps me the most.
I don't know Haskell or OCaml. I wouldn't know a monad if it slapped me in the face. But functional C++ makes me happy
Operating Systems. Games. Deterministic soft and hard real-time systems (there's a reason you wouldn't be able to certify a control system for a fighter jet written in Javascript). Scientific stacks. Multi-media (do you think Renderman is written in Ruby?).
I'd even argue against using GC'd languages in desktop applications. It's getting to a point where these run-times are gobbling up a few gigs worth of pages from the OS and they still hang or crash when the OS decides to start paging them to disk. Or another process gets priority from the scheduler. The fact is while processor speeds have increased memory hasn't and that's the big bottle-neck on current hardware. Despite popular beliefs I think users do care about performance. They don't notice good performance but as soon as that beachball/whitescreen/whatever comes up and the UI is unresponsive you can bet their face is scrunching up like a walnut. Does that happen only to 1 or 2 users? 10%? We don't measure things like that enough when our happy little GC will take care of it for us.
Tuning GCs for workloads is probably as much or more work, in my limited experience, as designing your program from the bottom up around its specific data patterns. You'll get better performance from the latter approach more often than tuning a GC to your workloads after profiling. The wins in that case are incremental (we tuned our JVM after some profiling and shaved off 1.8% from our inner loop!). Where they can be dramatic with the right data structures and careful attention to locality (we saw an 800x reduction in cycles due to cutting unnecessary allocations and a 300% speed increase -- sweet!).
Even tuning your allocation strategy can net you bigger gains than trying to structure your code around a JIT.
All that being said -- GC's are incredibly useful in many situations. You just have to measure and be thoughtful. Memory is still an issue GC or not.
If you are coding the full application yourself, probably.
If doing distributed development with 20+ team members from multiple contractors of various skill levels, which is my world, I have my doubts.
To me that's any device with a battery(I'm looking at you smartphones), gamedev, and as you mentioned embedded systems.
There's also another class of programs that's not related to GC. C++(and C by subset) is the only way to write truly cross-platform code for all the modern OS's. If you want to target Android, iOS and Desktop C++ is the only supported path on all those platforms with the right performance guarantees(JS doesn't cut it perf-wise on mobile, yet). That's why you see DropBox and quite a few other shops using C++.
For instance if you have a GC that compacts then by definition you cannot guarantee object relative layout. This object layout is critical in making sure that your traversal order is cache and pre-fetch friendly.
AFAIK struts+arrays in C# are the only construct I've seen that lets you get close to explicitly control ordering of objects. In almost every other GC'd language you end up needing to use a giant byte array(hello emscripten!) in order to make those guarantees. If you work in that manner you're throwing away 90% of what makes the language useful and paying the cost of not working with the objects in their native form.
Check Mesa/Cedar, Modula-3, Oberon, Oberon-2, Active Oberon, Component Pascal, D.
All system programming languages with GC.
I'm sure they fit the definition but I don't know that I'd want to use any in production aside from D. D is so similar to C++ I'd just rather use C++ instead since it's a bit more proven of a stack.
The problem is to have an OS vendor that would care to bring those features back.
So far I see it happening with Swift and C#, where Microsoft is slowly adding features from System C# used in project Midori.
Will they kill C++? Surely not, but they might reduce the use cases one would use it for.
For example, nowadays I don't write full stack applications in C++ any longer, I just use it for infrastructure code.
You do that in GC and non-GC environments exactly the same way: by embedding your objects in arrays.
> AFAIK struts+arrays in C# are the only construct I've seen that lets you get close to explicitly control ordering of objects.
And Java's upcoming value types.
> If you work in that manner you're throwing away 90% of what makes the language useful and paying the cost of not working with the objects in their native form.
I disagree. Even without value types, working with byte buffers in Java may still be significantly less work than C++, depending on how much of your application requires this kind of work. And the GC saves you a lot of work when you deal with concurrent data structures.
The main disadvantage (good) GCs have is their significant RAM overhead when good performance is required.
Value types are nice in Java, when will we see them in production? We don't even have Java8 on Android yet so I probably won't be able to use them till ~4-5 years from now.
Byte arrays may be less work but they still have problems, you'll pay the int->float cast costs for one, which can be non-trivial on some platforms. Also if you want to use Strings you end up allocating a new string on each access since Java doesn't have a nice way to wrap an immutable string(take a look at FlatBuffers if you want to see this in more detail).
I think it's important to understand they we're talking about a specific set of areas that C++ excels in. There are certainly places where I think Java and other managed languages make sense but if I need to make performance guarantees I'd rather not shoe-horn in a GC'd language where proven stacks have been successful.
Then you embed the array of chars in the object, just like in C++. I don't see what having a GC has to do with it. As to embedding arrays in objects in Java, I think it's planned as part of the value-type project, but no prototype yet. I know John Rose (JVM architect) said that the two features they intend to address are arrays of structs and structs of arrays (but not buffers of structs of arrays).
> you'll pay the int->float cast costs for one
HotSpot should optimize it away (not sure about byte buffer usage, though). It sees an integer read and a cast to float, and reads directly into a floating-point register.
> Java doesn't have a nice way to wrap an immutable string
You mean mutable string? Well, there's the CharSequence interface that String and the mutable StringBuilder implement, but it's true that not many standard APIs accept a CharSequence.
> I think it's important to understand they we're talking about a specific set of areas that C++ excels in.
I agree. C/C++ is unparalleled for single-threaded traversals over encoded binary data (e.g. video encoding/decoding and other signal processing) and for performance-sensitive applications running in memory constrained environments . Managed runtimes even try to compete in those domains.
In other cases, the extra performance you can squeeze out is too insignificant (and growing less significant with time) to justify the extra effort. And in some cases of growing importance (interesting multi-threading), C++ has to work really hard to even match GC-runtime environments. The real cost that is always paid is the significant RAM overhead.
And BTW: Android isn't Java. It's compatibility with Java has always been very partial, and, of course, its development is not directed by the JCP.
In Go:
A struct is laid out as you declared it, with possible compiler added padding. A struct value field (not a pointer) in another struct is laid out contiguously in memory as you declared it. An array (or a slice) of values (no pointers) are laid out contiguously in memory.
You can happily take pointers into any of these larger structures. If you had a data structure where you really wanted to control the layout, you can create a slab allocator as a big array of values, and take pointers into that array to allocate pieces of your data structure. I did this exact thing to write a red-black tree in Go.
It is true that Go's GC isn't compacting. But it will be in the future (or it is planned to be).
But, if I hadn't programmed in Go I would have agreed with your comment above.
or Go, especially with the value types. Now there is no automatic SoA/ AoS conversions but otherwise, you have full control over memory layout.
There is at least work towards making controlled GC pauses a possibility.
Like these ones?
http://www.atego.com/de/products/atego-perc/
Used for this?
Also IIRC aviation has incredibly strict rules on freeing during flight, so this likely switches to a fixed memory model for at least part of the time.
In Ada deallocattion requires use of the unsafe package and in SPARK dynamic allocation it isn't even possible.
However the usage of GC based systems by the military in their weapon control systems, shows that there are GC implementations that able to cover certain types of real time use.
After all a GC pause during a battle situation is probably not something one wishes for.
Then either use a GC that doesn't have multi-millisecond pauses, or make sure your "plain" GC doesn't. Both approaches are used very commonly.
I was just pointing out that most GC's that are general purpose have 2-3 ms pauses for collection which is a no-go for soft-realtime systems. I did not say that GC's are incompatible with soft-realtime systems.
Object pools and GCs do different things, and you can have object pools in both GCed environments as in manually-managed ones, and they'd work equally the same. But note that you need a very, very good (and far from trivial) object pool to beat a good GC in multithreaded environments.
> I was just pointing out that most GC's that are general purpose have 2-3 ms pauses for collection which is a no-go for soft-realtime systems.
Well, most free ones. If you're writing a soft-realtime system with stricter latency requirements you'll either work harder to avoid the GC or pay for a low-latency one.
From what I've read on the RTJS spec the real-time areas you're talking about use an arena allocator which is a different memory allocation strategy than GC.
I don't see how.
> From what I've read on the RTJS spec the real-time areas you're talking about use an arena allocator which is a different memory allocation strategy than GC.
Yes, but both hard- and soft-realtime threads (that do use a GC) share the same JVM and can share some objects. Also, keep in mind that realtime JVMs guarantee scheduling latency for hard realtime threads of up to a few microseconds. If you can live with higher latencies, you can use realtime GCs.
In hard real-time systems, there's generally the idea that if scheduling fails, things will break and/or property (or, worse, people) will be damaged.
Think of things like industrial high-torque motor control and avionics.
If deadlines are missed in multimedia applications the product isn't meeting its stated and implied requirements.
The consequences may be different, but a television that drops perceptible video frames is just as 'defective' (from an engineering point of view) as an industrial control system which drops motor control signals.
It's so far from the mainstream norm to implement these ancient time-savers that you can't help being excited about Swift, even though such a language should be mundane by now.
How so?