在函数式编程语言中,集合上最原始/最基本的操作是同态map
;它(大致)Collection[A] -> (A->B) -> Collection[B]
Rust系列似乎不支持这一点。我想这是因为它们是可变的集合;如果您已经在使用可变集合,则就地更新会更有效。
我错过了一个单独的“不可变集合”库(比如Scala)吗?
使用A->B
将Collection[A]
变为Collection[B]
的“就地映射”操作怎么样(与ML和Haskell不同,它实际上可以安全地做到这一点因为仿射类型!)甚至是A=B
和就地地图采用A->A
的特殊情况?
很难用搜索引擎回答这个问题,因为所有的点击都涉及“映射”名词(如HashMap
)。
答案 0 :(得分:3)
要将容器映射到容器,请迭代并collect()
:
vec.iter().map(|x| x * 2).collect::<Vec<_>>();
要在原地更改项目,请使用for循环和iter_mut()
。不建议在这种情况下使用迭代器链接,因为修改值会引入副作用。
for x in vec.iter_mut() {
x *= 2;
}
答案 1 :(得分:3)
Rust有一个map()
函数,但它不是每个容器的一部分,而是特征Iterator
(Rust特征非常类似于Haskell的类型类):Iterator:map()
。该特征包含许多更有用的方法,其中许多对于FP程序员来说应该是熟悉的。
让我们看看map()
的实际效果:
let result: Vec<_> = vec![2, 3, 5, 7]
.into_iter() // we have to get an iterator over the vector
.map(|i| i * i) // next we map each element
.collect(); // finally we collect all elements into a new vector
map()
的类型是您所期望的:
:: Iterator a -> (a -> b) -> Iterator b
或者在Rust语法中:
trait Iterator {
type Item;
fn map<B, F>(self, f: F) -> Map<Self, F>
where F: FnMut(Self::Item) -> B;
}
首先看起来更复杂,但它确实有意义,将来可能会更好。签名是(self, f: F) -> Map<Self, F>
。和
self
Iterator
超过Self::Item
[比较:Iterator a
] F
是FnMut(Self::Item) -> B
[比较:(a -> b)
] Map<Self, F>
对于Iterator
返回F
[比较B
] Iterator b
为a -> a
如果你想做一个就地let mut v = vec![2, 3, 5, 7];
for e in &mut v {
e *= 2;
}
let mut m = HashMap::new();
m.insert("anna", 5);
m.insert("peter", 3);
for v in m.values_mut() {
v *= 2;
}
地图(意思是:没有变换类型),你可以获得对每个元素的可变引用并进行更改。例如:
inputs n=4
如果没有不安全的代码,目前无法执行更改类型的就地映射。部分原因是Rust的类型系统无法在编译时比较两种类型的大小(但它会改变)。