3 ms·
Well you say "that family" but you only give examples of why Rust isn't Ada. Is the situation that you consider there are two families of languages, "Ada" and
by tialaramex 2y ago
Well you say "that family" but you only give examples of why Rust isn't Ada.
Is the situation that you consider there are two families of languages, "Ada" and then "All of the other programming languages" and you've decided to label that second group C?
On that basis I agree, Rust has a "C base" as do Fortran, Logo and the Standard ML of New Jersey, but I don't think that's a useful way to understand anything about programming languages.
> In Rust if I declare an array as having 5 elements then pass it to a function where I try
to access element 6 then nothing will try raise an error at compile time.
https://rust.godbolt.org/z/4eMTTMar4 https://rust.godbolt.org/z/4eMTTMar4
Looks like a compile time error to me. I suspect you wrote a function which takes a slice reference not an array. In Rust these types are named &[T] and [T; N] and sure enough we don't know the value of N in a slice because well, it's not part of the type. Ada can't magically know this either, in Ada you've probably been writing an array here, and if that's what you meant you can do that in Rust too with similar effect.
You can't do it in C (the array types do exist in C, but they decay to pointers at the edge of any function, so we can't pass these types between functions) but you can in Rust.
> arrays are only indexed by numbers rather than any discrete type
I guess you're thinking about core::slice::SliceIndex<[T]> ? This is (at least for now and perhaps forever) an unstable trait, so, you're not "allowed" to go implement this in stable Rust, but if you did anyway you can cheerfully implement SliceIndex for your own type, Rust won't barf although you can probably undermine important safety features if you try because none of this is stabilized.
Far from being "only numbers" core::slice::SliceIndex<[T]> is already implemented for the ranges (both kinds) and for a binding pair (lower_bound, upper_bound)
So in terms that maybe seem more obvious to you, we can do foo[(Bound::Unbounded,Bound::Unbounded)] as well as foo[3..=4] and foo[3..] in addition to the obvious foo[3] -- these are all defined on slices rather than arrays though because in practice that's what you actually want and we can just decay the array to a slice during compilation.
Overall I still think it really is the syntax that threw you off.
- LiamPowell 2y ago> Well you say "that family" but you only give examples of why Rust isn't Ada. Ada is the language I work with daily, but I think other languages that have been designed for the ground up for safety have similar features. Aside from arrays vs slices, the solutions to these problems all seem less ergonomic than they could be if they were a part of the core design of the language, which is my major issue here rather than whether it is possible at all to do such things. > You can't do it in C (the array types do exist in C, but they decay to pointers at the edge of any function. You can pass around a pointer to an array in C (int (*)[3]), but I don't think it's worth considering as the language and standard library are not designed to make working with it easy. This is the same as my issues with Rust, if declaring a new type to represent a number of files isn't as easy as just using a u32 then no one will use it, etc.. My opinion is that the absolute safest way to do something needs to also be the easiest way to ensure that users always pick the safest option. Ideally the user would even have to go out of their way to pick the more unsafe option. Rust is really good at this with memory and thread safety, just not as much with the rest of the language (although it's certainly better than C). As an addendum to my last example in the GP, I suppose the borrow checker prevents any safety issues from such a type requiring a separate allocation without generics that I was originally considering, although it does not help with leaks.
- estebank 2y ago> This is the same as my issues with Rust, if declaring a new type to represent a number of files isn't as easy as just using a u32 then no one will use it, etc.. #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[repr(transparent)] pub struct FileCount(pub u32); The annotations aren't needed until you make these part of your API and you want to communicate specific actions, but it's likely close what you'd end up with. The first thing I'd do, and likely get away with, is struct FileCount(u32); > My opinion is that the absolute safest way to do something needs to also be the easiest way to ensure that users always pick the safest option. Agreed.