Hashing a slice

I have a slice that is bound to a variable name as follows.

let x = vec![0.0, 2.0, 8.0];

Is there a function I could write of form fn hash(&[f32]) -> ??? that would hash - not by what the slice contains - but by what the slice is bound to?

Would ??? = *const [f32] work?
Would something similar work?

What are you trying to do? Since you cannot have several references to the same “object” in the same way you can in many other languages such as Java, it usually doesn't make sense to perform this operation.

If you are using a smart pointer like Rc that allows you to have several references to the same object, they typically have a dedicated method (e.g. ptr_eq) for doing an equality check. In the specific case of an Rc, you can call into_raw to obtain a pointer which you can cast to usize and then hash.

If you must, you can use a similar method on Vec, which returns a pointer you can cast to usize and hash. However if the vec runs out of capacity, it will reallocate which results in a new hash.

So, std::ptr::hash, but as @alice said tgis seems like a bad idea.

Yes, you can coerce from &[f32] to *const f32 to hash by address.

My by_address crate has a wrapper type for conveniently hashing/comparing slices (and other types) by identity rather than by content.

*const [f32] seems better than *const f32 if you want to make sure lengths are equal. (and it looks like by_address fully supports this use case)

Thanks everyone, std::ptr::hash seems like what I need.

As a quick follow-up question - when does std::ptr::hash change for a given slice. When the slice gets reallocated? If so, when does the slice get reallocated? only when its capacity changes? will this happen randomly at some other point?

The capacity changes once you give the global allocator (Rust uses jemalloc now) a *mut u8 followed-by the new Layout. Re-allocation never happens "randomly" for raw slice types. If you use a std::vec::Vec, then re-alloc occurs once you push an item such that its new implied length is greater than the capacity. Re-allocation is done automatically for you with vectors (so long as you use the safe functions provided in the API), but with raw slices, this needs to be done manually

Rust now uses the system allocator by default, you can opt into jemalloc if you want to with the #[global_allocator] attribute.

Oops, yes, I meant to write *const [f32].

Again, thanks everyone.

Just to clarify, can someone explain when I should use std::ptr::hash vs when I should use *const [f32]?

You can pass a *const [f32] to std::ptr::hash, it's not mutually exclusive.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.