News for hackers. Stuff that matters.
Re:Grids in Rust, Part 2: const generics by brundolf on Sunday April 04, 2021 @03:19AM (#26687541)
A Vec is a length, capacity, and pointer. I don't see how you could implement Rust's safety guarantees with runtime-sized arrays that don't know their capacity (for bounds-checks). I guess you could theoretically do without the length/capacity distinction, so you could eliminate one value (but not two) by having "plain" runtime arrays. Overall I just can't imagine there are very many cases where eliminating a single number's worth of memory usage for an entire collection is worth having separate concepts with separate implementations, syntaxes, etc, not to mention all the downsides of not having reallocations/usage-length managed for you.
Re:Grids in Rust, Part 2: const generics by unanswered on Sunday April 04, 2021 @10:14AM (#26689543)
Length=capacity is already available, and always has been, as Box<[T]>
Re:Grids in Rust, Part 2: const generics by brundolf on Sunday April 04, 2021 @08:26PM (#26694126)
Can [T] be any length, decided at runtime?
Re:Grids in Rust, Part 2: const generics by unanswered on Sunday April 04, 2021 @11:22PM (#26694995)
Yes.
Re:Grids in Rust, Part 2: const generics by brundolf on Sunday April 04, 2021 @11:26PM (#26695015)
That's news to me, and good to know. Seems moldavi's original comment was incorrect
Re:Grids in Rust, Part 2: const generics by steveklabnik on Monday April 05, 2021 @10:58AM (#26699893)
I mean, it depends on the words you use. "Array" has a specific meaning in Rust, and that's [T; N]. You cannot have a run-time value for N, and so in that sense, they are correct. If by "array" you mean "any number of values laid out next to each other in memory," then they're wrong, but that's not usually what this term means in Rust specifically. Vectors and slices are also laid out this way, but they're not called "arrays."

Box<[T]> is close, but it's a pointer + length, where the pointer is to the heap, whereas [T; N] is a series of values, and can be on the stack. That's why it's a "boxed slice" and not an "array."

And yes, any slice type is runtime sized. That's why slices exist; they have a length stored in them to keep track of how long they are. This goes for &[T], Box<[T]>, Arc<[T]>, any of them.

Re:Grids in Rust, Part 2: const generics by brundolf on Monday April 05, 2021 @01:16PM (#26701748)
So could I write something like this?

  // returns a heap-allocated buffer of length new_arr_length
  fn my_malloc<T>(new_arr_length: usize) -> Box<[T]> {
    todo!()
  }
The answer seems like no, looking at it, but it's possible there's a syntax for it I don't know about

I guess what it comes down to is: slices can't own their data, can they (I'm genuinely not sure)? If so, and this is indeed a slice, then it should be impossible for this to work in this way

Though, in that case it would also seem fairly pointless (as opposed to a &[T])

Re:Grids in Rust, Part 2: const generics by steveklabnik on Monday April 05, 2021 @02:36PM (#26702790)
You can't, but not because of the slice stuff, but because you have to give it valid values. This works

  // returns a heap-allocated buffer of length new_arr_length
  fn my_malloc<T: Default + Clone>(new_arr_length: usize) -> Box<[T]> {
    vec![T::default(); new_arr_length].into_boxed_slice()
  }
> slices can't own their data, can they (I'm genuinely not sure)

The problem is that "slice" can mean both &[T] and [T]. [T] is an unsized type, so it needs to be behind a pointer. Putting it behind a & is the common case, and doesn't have ownership because &T doesn't own T, but you can also put it behind Box<T>, which does have owership over T.

> Though, in that case it would also seem fairly pointless (as opposed to a &[T])

Yes, it's very niche. I've never used one in all my years of Rust. But Box<[T]> is two thirds of the size of Vec<T> (no need for capacity, since capacity == length) and maybe there are cases where that is significant, for example.

Re:Grids in Rust, Part 2: const generics by brundolf on Monday April 05, 2021 @03:12PM (#26703284)
I see! That makes sense now. Unsized types are one of the Rust concepts that I haven't gotten a good handle on yet, probably mainly because they don't come up very often in practice. The only other one I know of is str, and I'm not even sure how I'd go about using a plain str.
Re:Grids in Rust, Part 2: const generics by steveklabnik on Monday April 05, 2021 @03:20PM (#26703361)
Totally. It works the same way: it's gotta be behind a pointer. Arc<str> would be a signature for a threadsafe interned string, for example.

    use std::sync::Arc;
    
    fn foobar(s: &str) -> Arc<str> {
        Arc::from(s.to_string())
    }
You almost always can only create these sorts of values by casting.
Re:Grids in Rust, Part 2: const generics by unanswered on Monday April 05, 2021 @10:33AM (#26699524)
Most of what you read online is, especially about rust.