The resident C/C++ experts here would have you believe that the same is possible in C/C++. Is that true?
The resident C/C++ experts here would have you believe that the same is possible in C/C++. Is that true?
In C++? Maybe, but you’d need to make sure you stay on top of using thread safe structures and smart pointers.
What Rust does is flip this. The default is the safe path. So instead of risking forgetting smart pointers and thread safe containers, the compiler keeps you honest.
So you’re not spending time chasing oddities because you missed a variable initialisation, or you’re hitting a race condition or some kind of use after free.
While there’s a lot of people who say that this slows you down and a good programmer doesn’t need it, my experience is even the best programmers forget and (at least for me), I spend more time trying to reason about C++ code than rust, because I can trust my rust code more.
Put another way, Rust helps with reducing how much of the codebase I need to consider at any given time to just the most local scope. I work in many heavy graphics C and C++ libraries , and have never had that level of comfort or mental locality.
Smart pointers are no panacea for memory safety in C++ though: even if you use them fastidiously, avoiding raw pointer access, iterator invalidation or OOB access will come for you. The minute you allocate and have to resize, you're exposed.
Rust isn’t perfect but it gives me so much more trust in everything I do.
In NeXTStep they were written in ObjC, and probably should've stayed that way.
Can someone explain? Is there something other than DriverKit, which seems to be C++?
Both would sort of fit those descriptions I guess if one were to squint.
https://developer.apple.com/documentation/iokit
Which is how the Objective-C framework for NeXTSTEP drivers used to be called,
http://www.nextcomputers.org/NeXTfiles/Docs/NeXTStep/3.3/nd/...
I always find strange how "kernel C" is C, even though ISO C would bork in kernel space, but doing a similar C++ subset is pointed out as not being C++.
When I’ve written lower level components the things that have really been godsends outside the safety features are things like enums (much more powerful than C/C++ unions/enums and much more ergonomic than variants).
And even though I said traits don’t offer too much more than C++, one thing I think they do really offer is when combined with generics. Rust generics let you define trait requirements better (though not as extremely flexible) as C++ concepts/constraints.
Plus there’s something to be said for cargo being a killer feature for rust. Easy build configuration , easy package management and access to a large ecosystem of libraries.
Between that and the book..:As steep a learning curve as the language itself has, the actual on-boarding process is way more accessible than many other compiled languages.
Rust sucess story is briging Cyclone type system into mainstream, and in such a way that other languages (even those with automatic management runtimes) started looking at affine and linear type systems for low level performance optimizations.
However for explicit type conversions, bounds checking in strings and arrays, modules, co-routines, assignment before use,... there were plenty of alternatives, which for one reason or the other didn't took off, most not really technical related.
For what it’s worth, the same is true of Swift. But since much of the original Rust team was also involved with Swift language development, I guess it’s not too much of a surprise. The “unsafe” api requires some deliberate effort to use, no accidents are possible there. It’s all very verbose through a very narrow window of opportunity if you do anything unsafe.
I just wish it was more cross platform (I know it technically works on Linux and windows…but it’s not a great experience) and that it didn’t have so much churn (though they’ve stopped futzing with the core components as much with Swift 4+).
I also wish it was faster. I did an Advent of Code against some friends. I picked Rust, they picked Swift. The rust code was running circles around their Swift ones even when we tried to keep implementations the same.
Anyway, that’s a rant, but I think to your point, I feel like Swift could have been as big as Rust..or bigger given the easier use, with many of the same guarantees. I just wish the early years were more measured.
I've done Advent of Code a few years -- even Javascript implementations, if using a good (optimal) algorithm, are highly performant, so I'm suspicious of the claim. In most AoC problems, if your code is observably different between languages, it's the fault of the algorithm, regardless of language. But perhaps you are referring to well-profiled differences, even if there are no observable differences.
That said, in projects other than AoC I've compared Swift to C++ and it's hard to deny that a low-level language is faster than Swift, but Swift itself is certainly fast compared to most dynamically typed or interpreted languages like Python, JS, Ruby, etc. which are vastly slower than anything in Swift.
When I say Rust ran circles around it, I mean the difference was not noticeable unless timing, and was the difference of 200ms vs 400ms or a 3 seconds vs 5 seconds , so nothing to write home about necessarily.
I know Javascript have an unfair advantage here, since the competition between V8 and the other javascript cores is huge over the years and garbage collection on JS is not often a problem. At least I see more people struggling with the JVM GC with its spikes in resource usage.
I've also heard that the erlang VM (be it written in elixir or erlang itself) implements GC on a different level, not to the global process, but on a more granular way.
Is there a good resource that compare the current state of performance between those languages or approaches?
For me it isn't even that it catches these problems when I forget. It is that I can stop worrying about these problems when writing the vast majority of code. I just take references and use variables to get the business logic implemented without the need to worry about lifetimes the entire time. Then once the business logic is done I switch to dealing with compiler errors and fixing these problems that I was ignoring the first time around.
When writing C and C++ I feel like I need to spend half of my brainpower tracking lifetimes for every line of code I touch. If I touch a single line of code in a function I need to read and understand the relevant lifetimes in that function before changing a single line. Even if I don't make any mistakes doing this consumes a lot of time and mental energy. With Rust I can generally just change the relevant line and the compiler will let me know what other parts of the function need to be updated. It is a huge mental relief and time saver.
Talking of C++ it can be really solid to work with your own data structures where you control code on both ends. Using templates with something like boost::serialization or protobuf for the first time is like magic. E.g you can serialize whole state of your super complex app and restore it on other node easily.
Unfortunately it's just not the case when you actually trying to work with someone else API / ABI that you have no contol over. Even worse when it's moving target and you need to maintain several different adapters for different client / server versions.