Skip to content

Commit 000ea7f

Browse files
authored
Merge pull request #1040 from benkay86/master
add mapv_into_any(), resolves #1031
2 parents 307234e + 94ffa0f commit 000ea7f

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

src/impl_methods.rs

+39
Original file line numberDiff line numberDiff line change
@@ -2473,6 +2473,45 @@ where
24732473
self
24742474
}
24752475

2476+
/// Consume the array, call `f` by **v**alue on each element, and return an
2477+
/// owned array with the new values. Works for **any** `F: FnMut(A)->B`.
2478+
///
2479+
/// If `A` and `B` are the same type then the map is performed by delegating
2480+
/// to [`mapv_into()`] and then converting into an owned array. This avoids
2481+
/// unnecessary memory allocations in [`mapv()`].
2482+
///
2483+
/// If `A` and `B` are different types then a new array is allocated and the
2484+
/// map is performed as in [`mapv()`].
2485+
///
2486+
/// Elements are visited in arbitrary order.
2487+
pub fn mapv_into_any<B, F>(self, mut f: F) -> Array<B, D>
2488+
where
2489+
S: DataMut,
2490+
F: FnMut(A) -> B,
2491+
A: Clone + 'static,
2492+
B: 'static,
2493+
{
2494+
if core::any::TypeId::of::<A>() == core::any::TypeId::of::<B>() {
2495+
// A and B are the same type.
2496+
// Wrap f in a closure of type FnMut(A) -> A .
2497+
let f = |a| {
2498+
let b = f(a);
2499+
// Safe because A and B are the same type.
2500+
unsafe { unlimited_transmute::<B, A>(b) }
2501+
};
2502+
// Delegate to mapv_into() using the wrapped closure.
2503+
// Convert output to a uniquely owned array of type Array<A, D>.
2504+
let output = self.mapv_into(f).into_owned();
2505+
// Change the return type from Array<A, D> to Array<B, D>.
2506+
// Again, safe because A and B are the same type.
2507+
unsafe { unlimited_transmute::<Array<A, D>, Array<B, D>>(output) }
2508+
} else {
2509+
// A and B are not the same type.
2510+
// Fallback to mapv().
2511+
self.mapv(f)
2512+
}
2513+
}
2514+
24762515
/// Modify the array in place by calling `f` by mutable reference on each element.
24772516
///
24782517
/// Elements are visited in arbitrary order.

tests/array.rs

+14
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,20 @@ fn map1() {
989989
assert_eq!(a[(0, 0)], *c[(0, 0)]);
990990
}
991991

992+
#[test]
993+
fn mapv_into_any_same_type() {
994+
let a: Array<f64, _> = array![[1., 2., 3.], [4., 5., 6.]];
995+
let a_plus_one: Array<f64, _> = array![[2., 3., 4.], [5., 6., 7.]];
996+
assert_eq!(a.mapv_into_any(|a| a + 1.), a_plus_one);
997+
}
998+
999+
#[test]
1000+
fn mapv_into_any_diff_types() {
1001+
let a: Array<f64, _> = array![[1., 2., 3.], [4., 5., 6.]];
1002+
let a_even: Array<bool, _> = array![[false, true, false], [true, false, true]];
1003+
assert_eq!(a.mapv_into_any(|a| a.round() as i32 % 2 == 0), a_even);
1004+
}
1005+
9921006
#[test]
9931007
fn as_slice_memory_order_mut_arcarray() {
9941008
// Test that mutation breaks sharing for `ArcArray`.

0 commit comments

Comments
 (0)