我正在尝试从创建每个元素的仿函数创建一个二维矩阵,并将其存储为平面/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`a3823833_MiniPost` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `a3823833_MiniPost`;
/*Table structure for table `user` */
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`userid` bigint(10) NOT NULL,
`username` varchar(20) NOT NULL,
`password` varchar(20) NOT NULL,
`email` varchar(50) NOT NULL,
PRIMARY KEY (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*Table structure for table `profile` */
DROP TABLE IF EXISTS `profile`;
CREATE TABLE `profile` (
`userid` int(11),
`lastName` varchar(50),
`firstName` varchar(50),
`dob` varchar(10),
PRIMARY KEY (`userid`),
CONSTRAINT `profile_fk` FOREIGN KEY (`userid`) REFERENCES `user` (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
(每行连接)。
我使用嵌套的Vec
(实际上是map
和嵌套的flat_map
)来创建每一行并将其连接起来。 Here is what I tried:
map
不幸的是,我在编译期间遇到错误:
fn make<T, F>(n: usize, m: usize, f: F) -> Vec<T>
where
F: Fn(usize, usize) -> T,
{
(0..m).flat_map(|y| (0..n).map(|x| f(x, y))).collect()
}
fn main() {
let v = make(5, 5, |x, y| x + y);
println!("{:?}", v);
}
如何在嵌套地图中使用闭包?我解决了这个问题by using a single map on 0..n*m
,但我仍然对答案感兴趣。
答案 0 :(得分:7)
在你的情况下,内部闭包|x| f(x,y)
是一个借用闭包,它通过引用获取其环境(y
和f
)。
.flat_map(..)
的工作方式,禁止您保留对y
的引用,而y
不是来自外部范围。因此,我们需要让您的闭包按值获取其环境,usize
Copy
(0..m).flat_map(|y| (0..n).map(move |x| f(x, y))).collect()
error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
--> src/main.rs:5:36
|
1 | fn make<T, F>(n: usize, m: usize, f: F) -> Vec<T>
| - captured outer variable
...
5 | (0..m).flat_map(|y| (0..n).map(move |x| f(x,y))).collect()
| ^^^^^^^^ cannot move out of captured outer variable in an `FnMut` closure
不是问题:
f
然而,现在又出现了另一个问题:
m
在这里,我们试图将1
移动到闭包中,这绝对不可能(除非f
是Fn(usize, usize) -> T
,但编译器无法知道)。
由于&
是&
,我们也可以明确传递Copy
引用,而fn make<T, F>(n: usize, m: usize, f: F) -> Vec<T>
where
F: Fn(usize, usize) -> T,
{
let f_ref = &f;
(0..m)
.flat_map(|y| (0..n).map(move |x| f_ref(x, y)))
.collect()
}
引用为y
:
f_ref
在这种情况下,闭包按值获取其环境,此环境由Copy
和ifelse(x < 100, sprintf("%0.2f", x), sprintf("%0.5e", x))
# [,1] [,2] [,3] [,4] [,5]
#[1,] "9.99999e+06" "-0.79" "-0.56" "0.91" "-2.57"
#[2,] "-0.13" "9.99999e+06" "-1.83" "-0.34" "1.73"
#[3,] "-0.48" "0.38" "1.00000e+07" "1.40" "-0.32"
#[4,] "-0.05" "-0.62" "0.91" "1.00000e+07" "1.15"
#[5,] "-0.09" "-0.33" "-0.16" "0.35" "9.99999e+06"
组成,两者都是noquote(ifelse(x < 100, sprintf("%0.2f", x), sprintf("%0.5e", x)))
# [,1] [,2] [,3] [,4] [,5]
#[1,] 9.99999e+06 -0.79 -0.56 0.91 -2.57
#[2,] -0.13 9.99999e+06 -1.83 -0.34 1.73
#[3,] -0.48 0.38 1.00000e+07 1.40 -0.32
#[4,] -0.05 -0.62 0.91 1.00000e+07 1.15
#[5,] -0.09 -0.33 -0.16 0.35 9.99999e+06
,一切都很顺利。
答案 1 :(得分:1)
添加到Levans's excellent answer中的另一种定义函数的方法是
fn make<T, F>(n: usize, m: usize, f: F) -> Vec<T>
where
F: Fn(usize, usize) -> T + Copy,
{
(0..m).flat_map(|y| (0..n).map(move |x| f(x, y))).collect()
}
由于我们知道|x, y| x + y
是Copy
类型,因此f
将为flat_map
调用的每个回调复制。我仍然希望使用Levans的方法,因为它不如复制参考文献有效。