I need a function which processes a bunch of X
s:
fn process_vals(sample: &[ X]) { ... }
fn process_refs(sample: &[&X]) { ... }
Either the refs
or the vals
version will do, but I'd like there to be only one. I would guess that the refs
version would be the one to go with. However, if I find myself holding a &[X]
or a Vec<X>
, what would be a good way of turning the inner X
s into &X
s?
The following works, but is a bit long-winded
fn slice_of_vals(xs: &[X]) { process_refs(&xs.iter().collect::<Vec<_>>()) }
Can I do better? Is there something along the lines of as_ref()
that might be appropriate here?
Generic vs. specific conundrum
In the process of playing around with this, I found that the by-value version appears to work very directly in generic code, but not on code that uses a specific type:
// ----- Generic-by-val version -------------------------
fn process_vals_generic<T>(sample: &[T]) {}
fn foo_generic_vals<T>() {
// A variety of ways of holding a bunch of Ts
// All of these can be passed easily to process_vals_generic
fn slice_of_refs<T>(ts: &[&T]) { process_vals_generic( ts) }
fn slice_of_vals<T>(ts: &[ T]) { process_vals_generic( ts) }
fn vec_of_refs<T>(ts: Vec<&T>) { process_vals_generic(&ts) }
fn vec_of_vals<T>(ts: Vec< T>) { process_vals_generic(&ts) }
// Two ways of holding a single T
// Both easily passed to process_vals_generic
fn just_one_ref<T>(t: &T) { process_vals_generic(&[ t]); }
fn just_one_val<T>(t: T) { process_vals_generic(&[&t]); }
}
// ----- Specific-by-val version ------------------------
struct X;
fn process_vals_specific(sample: &[X]) {}
fn foo_specific_vals() {
// A variety of ways of holding a bunch of Xs
// Unlike the generic version above, some of these fail to compile
fn slice_of_refs(xs: &[&X]) { process_vals_specific( xs) } // ERROR: expected &[X], found &[&X]
fn slice_of_vals(xs: &[ X]) { process_vals_specific( xs) }
fn vec_of_refs(xs: Vec<&X>) { process_vals_specific(&xs) } // ERROR: expected &[X], found &Vec<&X>
fn vec_of_vals(xs: Vec< X>) { process_vals_specific(&xs) }
// Two ways of holding a single X
// Unlike the generic version above, the first case fails to compile
fn just_one_ref(x: &X) { process_vals_specific(&[ x]); } // ERROR: expected X, found &X
fn just_one_val(x: X) { process_vals_specific(&[ x]); }
}
I suspect that the T
being inferred by the compiler is not what I think this is.
How can this difference between the generic and non-generic code be explained?