If that were true, we wouldn’t have lost so many people who just got sick of the lack of movement.
Talking from experience here, I created the SDL2 bindings, which are still in development. You can either do a really thin binding which doesn’t utilise any Ada feature and it’s just like programming in C, but in Ada. Or you go the thick route, which imports the functions and sometimes the structures, depending, and then wraps them in Ada types which proper ranges. The difficulty here is that for a lot C libs, there are no ranges defined or even thought of. Thicker bindings takes substantially longer due to this, which in turns makes it difficult to keep going. So, yeah, you’ll find bindings in sometimes ok shape and sometimes not bad and sometimes just bad.
One major difference is that Ada was created at a time when most military computers were single-core with in-order sequential execution and no cache. Although limited SIMD existed, any other concurrency was very coarse-grained. That’s the underlying execution model for C, Pascal, C++, etc.
Rust was created to address the complexity of multi-core processors with multi-level cache hierarchies where computational efficiency may require much concurrency. In my experience few humans are capable of error-free design and implementation of highly-concurrent systems unless they employ tooling that flags their errors in conceptualization or implementation.
Well, that makes things much nicer. It’s unfortunate though that this info is buried somewhere in manuals, and the default behavior is to create non-owned access type. It’s easier to make mistake than to write correct code then. Although does this feature support moving such heap-allocated storage out of current scope?
I tried to skim through storage pool management and unfortunately couldn’t grasp idea how to properly use 'Size clause. Could you please provide example analogous to
let foo_box = Box::new(Foo(42u32));
My point is, it’s explicit “not null” instead of explicit “nullable”. Less safer behavior is the default one.
std::unique_ptr is one of the first things which are taught to C++ newcomers. While knowing about ADA’s Storage_Size requires sifting through manuals or forum threads.
I agree and the default should be to deallocate on the access type going out of scope on end;.
No, because I don’t know what that is doing.
But the Ada equivalent would be use the representation clause:
type Some_Ptr is access ...;
for Some_Ptr'Storage_Size use <some_size>;
or the aspect, which Ada 2012:
type Some_Ptr is access ... with
Storage_Size => <some_size>;
Yes, but they cannot make that the default because of legacy.
Starting Ada programmers don’t even use new/Unchecked_Deallocation at teh start, because most things are statically allocated either in packages or on the stack, so it’s only when you need to do container type stuff that you require allocators at all. Allocators are considered to be a more advanced Ada feature. It’s possible to write entire programs without using them at all. You could say that’s even safer than Rust in that regard.
You can write smart pointers in Ada using controlled types with generics, as I mentioned before.
Nothing exceptional here, Rust no_std crates successfully demonstrate possibility of writing programs without allocators as well. But I fail to see how presenting allocations as an “advanced feature” helps promoting Ada as a modern general purpose language.
Can you elaborate? Specifically in comparison with Rust no_std programs.
In Ada you can have dynamically sized variables or objects on the stack, thanks to unconstrained types. No pointers at all, no heap allocation.
For complex cases like trees, linked lists, etc. you can use the Ada.Containers which have deterministic (then predictable) garbage collection via finalization.
Are you really looking at Ada through a ‘C++ lens’? That is one of the main point of Lucretia:
Ada can moves you miles before even needing an equivalent to ‘std::unique_ptr’. There is your main constraint on newcomers and a sound app architecture. Need to make a ninja ‘move’?.. check the manual. Stop comparing to ‘how C++ would do’. Doing so, you blind yourself to what Ada has to offer.
Ada has all the control you may need… but you have to ask for it. The fact that Ada is build around explicit mechanism is godsend in regard to all aspects of software engineering. I respect you like and appreciate Rust but I fail to understand how the requiring of such implicit knowledge to achieve so little is desirable in any production environment?
In contrast, Ada is a very straight shooter; its focus is on the result, not the act of. This is probably what makes it so good at producing reliable abstractions… like you know … your surgical robot software or … your avionic navigation system.
Ada delivered such system for the past 40 years so yeah, Rust has ground to cover in that respect.
Ada’s mentality is derived from the working definition of type as a set of values and a set of operations on those values and subtype as an additional constraint (possibly null) on the set of values — Thus we can say:
Integer_Size : Constant := 32;
Type Integer is range -2**(Integer_Size-1)..2**(Integer_Size-1)-1
with Size => Integer_Size;
Subtype Natural is Integer range 0..Intger'Last;
Subtype Positive is Natural range Natural'Succ(Natural'First)..Natural'Last;
As you can see, this is exactly like defining a set, and then making useful subsets by adding more constraints, restricting the possible values. (This is very useful in terms of reasoning; it’s rather a shame that the OOP-hype of the past few decades has produced a sort of “it’s not useful if you can’t extend it” mentality, which is easily disproven by recursion.) — Anyway, access-types are essentially the same: the normal values being [null | <reference>] and the addition of the constraint (not null) reduces that to [<reference>].
EDIT: Note that everything in the above example is in terms of the named-number Integer_Size; this means that if you had a 48-bit machine all you would have to do is change the constant to 48. (Or 64 for a 64-bit machine.)
You need that sort of stuff [pointers] far less frequently than in C/C++ — see Memory Management with Ada 2012 [webm] — in part because (a) parameters can be in, out, or in out; and (b) arrays/slices “know” their indices.
Again, see the above. (But if you really need RAII, it’s not at all hidden: RM 7.6 -- Assignment and Finalization.)
There is no community edition for the Ada language. All of the language is freely available here.
What you’re referring to is the GNAT offering of AdaCore, which does have a community edition, but there are two things to note (a) the GPL restriction is due to the RTL, if you use a different RTL you’re fine; and (b) GNAT is also available from the FSF (here) and is free from the GPLed RTL problem.
You don’t need to qualify which particular version of gnat you have unless you have multiple versions, then specify the PATH, other than that, use whatever IDE you want. If you want LSP support, well, that’s just lacking.