Safety (of all kinds) is not the only selling point of Rust and Zig, and the fact that Ada also have safety measures doesn't mean that it's instantly an option for me.
For example, I keep seeing people hype about Zig/Rust, for all kinds of reasons; and the way that they present their arguments is very compelling. While I've heard of Ada before, AFAICT the only context in which it is brought up is to downplay hype over Rust/Zig; never as a standalone.
Sounds like a PR problem, mostly.
EDIT: Not to say that there aren't other problems, just saying that this point alone isn't some magic bullet.
I don't like Rust because it gives me memory safety, tons of languages do that. I love Rust because the tradeoffs it gives me worth the switch, and the overall tooling and ecosystem are very well made.
It's the case that the Zig creator did put a high priority on soft "PR" for the language, the first hire was a developer advocate/community manager. I think this is a great case of "lessons learned" from the history of programming languages.
Same applies to the tooling of Ada/SPARK, but as you have said, it is pretty much a PR issue.
OCaml has seen the alternative "Reason" syntax (JS-like) grow in popularity. Maybe a C-like (or better, rust-like) syntax for Ada would help the language's adoption. People already using Ada would complain that the current syntax is fine but they're not the target demographic :-)
I can easily read and understand someone's Ada, C, or OCaml code and actually know what is going on, but I cannot read and understand even my own Perl code (after a week or two), or other people's Rust code. I would rather prefer reference implementations to be in C than in Rust, too. If I read the C version, I can easily port it to any language vs. if it were in Rust.
OCaml does not look like Rust to me (OCaml seems more consistent, and Rust seems like a mixed bag of everything to me). It does not hide as much behind symbols for example as Rust does, I think, and learning it was really easy. I tried to read Rust, I really did, but everything is so hidden from me. I did not mean to say that any of the mentioned languages are anywhere close to C though. In any case, if I had to look at reference implementations, C would be the best (to me). It is really easy to know what is going on and why, and thus it is easy to implement it in any languages I know. Probably because it is not a language with many high-level abstractions or language constructs (syntactic sugars) that hide what is going on.
Example snippets as to why I dislike Rust:
let mut parents_array = ArrayVec::<[&[u8; BLOCK_LEN]; MAX_SIMD_DEGREE_OR_2]>::new()
let input_ptrs: &[*const u8; DEGREE] = &*(inputs.as_ptr() as *const [*const u8; DEGREE]);
And this is nothing, there are much worse ones, and I would have to give you files for that, but pretty much any famous Rust project is difficult to read for me. I really do not understand most Rust code, I wonder if the problem is with me.I still dont understand this, you spend 80% of the time thinking about code, 19% reading, and 1% typing.
I don't even remember much, just that how much I loved just the look of the example programs, but that was during community college when I was new to programming. It wasn't part of a class, but the guy who implemented the curriculum just jammed the library with jewels and the entire library collection was just full of classics especially since the actual curriculum was just a basic associates in "business data processing."
For example, a couple of features come together really nicely to make memory safety easier to test in Zig: * You need a reference to an Allocator to be able to allocate memory, so as a general rule, the caller can control which allocator is used. * Unit testing is integrated well into the language. * Therefore, you can create an allocator for each unit test, and fail the test at the end if any memory was leaked. * This process can also happen at the application level with the General Purpose Allocator, which can let you print an error when the program exits if anything was leaked.
The above doesn't solve every memory safety problem (and there are other features like native bounds-checked slices that solve other kinds of issues), but it provides an extra layer that can probably get us quite far into the "quite safe" camp.
https://devblogs.microsoft.com/cppblog/new-static-analysis-r...
https://devblogs.microsoft.com/cppblog/finding-bugs-with-add...
https://docs.microsoft.com/en-us/cpp/code-quality/using-sal-...
https://docs.microsoft.com/en-us/visualstudio/debugger/how-t...
No need to switch languages with a lesser eco-system, just learning to turn on the compiler switches that are already there.
There were no free beer compilers and no 8/16 bit home computer was capable of hosting an Ada compiler, Basic, Pascal and Modula-2 was the best they could manage.
Is there a good compiler that one can install for free?
Are there a few good and comprehensive books / references / guides, available online for free?
If you want something to become popular, give it away. Ideally, push it. At the very least, have a limited free version. Or turn a bling eye to small-time piracy, as many vendors did for a long time. Or make it dead easy to buy it for $10.
(None of the above works for you? Sorry, you have just turned down 99% of kids who might like to tinker with your tech, love it, and then promote it wherever they go. Your tech may be hot and desired in the narrow circle of pros, but it's not going to become popular and win the world.)
Accessibility is really not the problem. The problem is, Ada is an old language that has many similar problems to C: lack of a good package management story, and a design by committee making language evolution glacially slow (though that also doubles as a feature). It also lacks a vibrant ecosystem like we can find in other popular languages.
Furthermore, SPARK in particular takes the concept of safety much further than Rust or Zig do right now, as it allows proving the correctness of a program according to a formal specification. Rust/Zig only care about proving the absence of UB. This makes SPARK much more complex, and thus have a much higher barrier of entry.
The problem for older languages is that the bar for what's expected of a language has risen substantially. A long time ago, languages weren't even expected to have implementations. Today, not only are implementations expected for all major platforms, languages are also expected to run on phones and the browser, include package managers and library repositories, have a language server implementation and editing modes for all major IDEs, be open source with active development, provide extensive documentation on the scale of a book, and also promote a vibrant and active community. Oh, and to top it off, users don't want to pay for any of that. It's just expected, which is why most languages these days only come out of large tech companies that can afford to fund all of the above with no expectation of profit.
A better starting point might be http://www.GetAdaNow.com/
The most prominent project that i know of written in ada is ghdl.
Sure, but if you only ever give people safety scissors then you're severely limiting the kinds of things that they can build. You have to let people who know what they are doing be able to do what they need to do, so you have to be able to turn the runtime safety off. Zig can do this at the scope level.
If you dont want full control like in C++, a language would be nice that has one specific style, one specific way to do things, and so on. Go(lang) is quite close to this, in my experience. You can't do thread safety wrong, because there's only really one way, and so on.
I would love a language with
1. Explicit nullable types (not like Java's "anything can be null" design), so everything is a non-nullable reference type unless its "optional<T>" for example. I strongly support the idea of a nullable type only being used where it being null carries information.
2. Strong typing - like, tungsten strong. Implicit conversions need to be compiler errors, no implicit constructors, etc. with simple explicit casting
3. One style - and it better not be Java-like forced-OOP.
4. Full and clear memory control, RAII support, no gc. I need my RAM for other stuff.
I'm not sure if there's a language like that out there. I don't care for library support, I just want a fun language.
The new gc is pretty much compiler assisted scope managed smart pointers as well. Also when using the gc you can build your own types with custom create/free/copy/move operators to do what you want without worrying about a stop the world gc.
Using the arc gc pretty much compiles down to what you'd do manually. For cycles you can use the orc gc, again it's all opt in.
I find this a great balance of productivity and performance, where it's easy to have high control when you want it, and still get good performance when you're not bothered.
With the new ARC & move semantics, Nim has hit a sweet spot, IMHO. It's like the language struggled to find a fit for a long time. But ARC allows very low overhead memory safety, perfect for mcu's and wasm in particular.
Though perhaps Swift could be a contender in this arena as well with its ARC, but it's development is so Apple centric.
What's interesting to me is that with move semantics and smarter compiler analysis, an ARC based GC overhead approaches that of Rust's compile time lifetime memory management. For any non-trivial program Rust seems to use a lot of Rc's or copies to get around lifetime analysis issues. So if the compiler can automatically figure out lifetimes in code it can eliminate many ARC operations.
I hope more languages adopt more flexible ARC based gc's or improve on rusts ergonomics.
If you're really responsible, it's possible to use the system allocator to inform the system about how much memory your allocations consume so that the memory pressure triggers have a correct accounting of how much memory is being used.
Then on the past languages that failed to gain steam, Mesa/Cedar, Modula-2+, Modula-3, Oberon, Oberon-07, Oberon-2, Active Oberon, Eiffel, Sing#, System C#, Component Pascal, among many others.
The only thing missing is that many are badly taught, use new everywhere and don't bother to fully understand all language features.
It makes for a very performant pure functional language. My only gripe is that the stdlib is abysmal, and hardcoded into the compiler.
- value types
- stackalloc is safe since C# 7
- SafeHandles since C# 2.0
- IDispose interface
- IDispose like Dispose() since C# 8
- Marshal class since C# 1.0
- Span<>() classes since C# 7
- static lambdas since C# 9
- native function pointers since C# 9
You don't hear about the struggles of using it in practice because the projects you've pointed out are usually confidential.
In my experience MISRA is a much more popular standard for secure programming in the defence industry versus Ada. MISRA is a C standard, and yes, it runs missile systems, Boeing braking systems, you name it.
Ada suffered from its domain, original price of compilers, and the few UNIX vendors that cared to offer compiler like Sun, it was an additional acquisiation on top of UNIX SDK.
Everyone knows that only newbies do coding errors in C, so why spend the extra money? /s
The Sun C compiler was an additional cost item, just like everyone else.
That was my point.
https://www.nongnu.org/gm2/homepage.html
However I doubt the language gets much use nowadays beyond some legacy code bases, its opportunity is now gone.
The Ariane 5 maiden flight disaster illustrated quite clearly that the choice of language has little influence on the actual correctness of a program.
Ada on its own is no better than Pascal in that regard. A formally verified and thoroughly tested MISRA C program can be safer and more correct than a sloppily written Ada program.
So the question is indeed not as rhetorical as one might think - why spend the extra money indeed? Isn't it better spent on verification, testing, tooling and culture, which benefits the development regardless of programming language?
So yes, it is quite worthy to reduce the amount of money spent in verification, testing, tooling and culture.
The alternative is to just give up that programmers will never learn and just force verification at hardware level, like Google is doing on Android.
"Memory Tagging for the Kernel: Tag-Based KASAN"
https://www.youtube.com/watch?v=f-Rm7JFsJGI
Oracle on Solaris SPARC,
https://docs.oracle.com/cd/E37838_01/html/E61059/gqajs.html
Apple on iOS,
https://developer.apple.com/documentation/security/preparing...
Microsoft on Azure Sphere,
https://www.microsoft.com/security/blog/2020/11/17/meet-the-...
http://www-users.math.umn.edu/~arnold/disasters/ariane5rep.h...
http://www.adapower.com/index.php?Command=Class&ClassID=FAQ&...
I would love to see something like "Rustlings" for Ada, as I found that was a good way to practice not only writing code, but reading it as well.
I was able to self-teach Haskell and Erlang without any major problems, and even managed to ship applications written in it commercially.
(Looks like I found a use for the new Rosetta on my M1 Mac.... I wonder when there will be builds for aarch64 for Darwin)
:D
My argument is that if I need that insane speed and safety features have to be off I should actively work for that not the other way around that I should actively work for safety.
Why? Because we forget to do things.
> Another language that does safety like this incredibly well is Ada (Ada/SPARK)
I wanted to learn Ada for a long time. Do you have a guide or tutorial how to get into it?
Especially these ones: https://news.ycombinator.com/item?id=21435869 and https://news.ycombinator.com/item?id=21437498
Sorry if a lazy question, last time I looked at ada was decades ago and I'm surprised to find enthusiasts for it on HN.
edit: an advantage for c is that you can get loads of examples just googling, sucks for less used languages I guess.
- https://en.wikibooks.org/wiki/Ada_Programming/Libraries/GNAT... (search for "C select()")
- https://www.codelabs.ch/anet/
- https://github.com/samueltardieu/adasockets
- https://github.com/rtyler/ada-playground/blob/master/epollec...
Some old reading: https://brokenco.de/2013/04/07/async-with-ada.html
You may want to check how GNAT.Sockets and Anet are implemented, too. I know that GNAT code is heavily documented.
https://news.ycombinator.com/item?id=19122884 (!)
https://news.ycombinator.com/item?id=19245898 (!!)
https://news.ycombinator.com/item?id=19274244 (!!)
https://news.ycombinator.com/item?id=19274412
https://news.ycombinator.com/item?id=19770405
https://news.ycombinator.com/item?id=20776296
https://news.ycombinator.com/item?id=20934511 (!!) [3]
https://news.ycombinator.com/item?id=20939336 (!!)
https://news.ycombinator.com/item?id=21286061
https://news.ycombinator.com/item?id=21286292
> These runtime checks[1] are costly, both in terms of program size and execution time. It may be appropriate to remove them if we can statically ensure they aren't needed at runtime, in other words if we can prove that the condition tested for can never occur.
> This is where the analysis done by GNATprove comes in. It can be used to demonstrate statically that none of these errors can ever occur at runtime. Specifically, GNATprove logically interprets the meaning of every instruction in the program. Using this interpretation, GNATprove generates a logical formula called a verification condition for each check that would otherwise be required by the Ada (and hence SPARK) language.
Additionally, in Ada/SPARK, you can formally verify tasks (concurrency), too: https://docs.adacore.com/spark2014-docs/html/ug/en/source/co....
Moreover:
> SPARK builds on the strengths of Ada to provide even more guarantees statically rather than dynamically. As summarized in the following table, Ada provides strict syntax and strong typing at compile time plus dynamic checking of run-time errors and program contracts. SPARK allows such checking to be performed statically. In addition, it enforces the use of a safer language subset and detects data flow errors statically.
Contract programming:
- Ada: dynamic
- SPARK: dynamic / static
Run-time errors:
- Ada: dynamic
- SPARK: dynamic / static
Data flow errors:
- Ada: -
- SPARK: static
Strong typing:
- Ada: static
- SPARK: static
Safer language subset:
- Ada: -
- SPARK: static
Strict clear syntax:
- Ada: static
- SPARK: static
Additionally, safe pointers in SPARK: https://blog.adacore.com/using-pointers-in-spark and https://arxiv.org/abs/1710.07047.
More information about Get_Line (i.e. even where you would think you cannot go static): https://blog.adacore.com/formal-verification-of-legacy-code.
[1] overflow check, index check, range check, divide by zero
Already happening with Nim.
But I'd expect a system programmer to know better. When to use release and when to use development mode.
Case in point, rust doesn't catch integer overflows in release build either. Maybe Efficiency is more important than we think?
Maybe because they assume that it's only used for that purpose? You talk about rocket science and you expect people to jump on the bandwagon...
You already know someone will teach their students to always have it off because its "slower" or something.
Make something idiot-proof and the world invents a better idiot.
Another language that does safety like this incredibly well is Ada (Ada/SPARK), and I'm unsure why people aren't more hyped about it. So many people hype Rust or Zig or whatever new language, and yet there's an incredibly safe and expressive language that's used in high-reliability applications like missile guidance systems, that nobody seems to talk about.