就像我的a previous question一样,我正在重构一个小的Rust项目。与该问题类似,编译器和我也没有在方法和价值观上保持一致。但是,错误消息非常不同,并且此似乎可能涉及库,hyper在此示例中。
/* extern and use directives... */
pub struct WebServer /* with stuff not relevant to the error */;
impl WebServer {
pub fn serve(&mut self) {
let server = Server::http(Ipv4Addr(127, 0, 0, 1), 80);
let mut listening = server.listen(self.return_page).unwrap();
listening.await();
}
fn return_page(&mut self, req: Request, mut res: Response) {
/* Put the page together */
}
}
当serve()
和return_page()
只是main.rs
中的函数时,这会编译并运行。
如上所述隐藏在struct
中,我收到以下错误:
.../src/main.rs:13:48: 13:59 error: attempted to take value of method `return_page` on type `&mut WebServer`
.../src/main.rs:13 let mut listening = server.listen(self.return_page).unwrap();
^~~~~~~~~~~
.../src/main.rs:13:48: 13:59 help: maybe a `()` to call it is missing? If not, try an anonymous function
.../src/main.rs:13 let mut listening = server.listen(self.return_page).unwrap();
^~~~~~~~~~~
我认为解析器只需要朝着正确的方向轻推,但即使我对相关问题给出了建议,我也没有在文档中看到任何可以说明的方式,&#34 ;不,我的意思是将函数作为参数,就像我需要的调用函数的签名一样。"鉴于上述语法在struct
?
对于关闭的半心半意的尝试似乎更糟和错误消息仍然建议调用return_page
而不是传递它,但我很可能误解了这种情况下的用法
修改:为了澄清使用现有答案后的情况,原来的return_page()
当然没有self
参数,这本身就是部分问题。但它在对象内部也需要self
,因为它需要访问成员变量。
答案 0 :(得分:3)
您无法将return_page
直接传递给listen
,因为Handler
仅适用于带有2个参数,请求和响应的函数。 return_page
需要3个参数(self
计数作为参数)。
试试这个:
let mut listening = server.listen(|&: request, response| self.return_page(request, response)).unwrap();
或者,为impl
添加Handler
,然后将return_page
功能移至名为impl
的{{1}}。
handle
请注意impl WebServer {
pub fn serve(&mut self) {
let server = Server::http(Ipv4Addr(127, 0, 0, 1), 80);
let mut listening = server.listen(&self).unwrap();
listening.await();
}
}
impl<'a> Handler for &'a WebServer {
fn handle(&self, req: Request, mut res: Response) {
/* Put the page together */
}
}
通过不可变引用传递Handler
,而不是通过可变引用传递。您可能需要使用RefCell
来绕过这一点。
答案 1 :(得分:1)
简短的回答是你可以使用UFCS(统一函数调用语法):
let mut listening = server.listen(WebServer::return_page).unwrap();
答案很长,我怀疑这会使你的代码工作。您没有显示直接在main中定义return_page
的方式,但我想它类似于fn return_page(req: Request, mut res: Response)
。
此签名与定义为WebServer方法的return_page
不同。
我们来看看它:
fn return_page(&mut self, req: Request, mut res: Response)
这是一个采用&mut self
类型的第一个参数的函数,即&mut WebServer
。如果listen
没有预料到这个签名,您将会得到一个&#34;不匹配的类型&#34;错误。
让我尝试创建代码的模拟实现:
// serve calls listen passing it return_page. Note that
// the signature of return_page matches the one that
// listen is expecting, fn(u32, u32)
fn serve() {
listen(return_page)
}
// mock return_page
fn return_page(a: u32, b: u32) { println!("{}, {}", a, b) }
// listen expects a function that takes two u32
// and returns nothing
fn listen( f: fn(u32, u32) ) { f(1, 2) }
fn main() {
serve();
}
现在让我们将serve和return_page移动到impl中,就像我认为你做的那样:
fn listen( f: fn(u32, u32) ) { f(1, 2) }
struct WebServer;
impl WebServer {
fn serve(&self) {
listen(WebServer::return_page)
}
// a method is a function that takes the implementing type
// as a first parameter. We can use UFCS to invoke it as
// a function: WebServer::return_page
fn return_page(&self, a: u32, b: u32) { println!("{}, {}", a, b) }
}
糟糕,不匹配的类型:listen
不期望第一个类型为&WebServer
的参数。你需要这个签名:
fn listen(f: fn(&WebServer, u32, u32) )
请注意,如果假设listen
确实有该签名,我们的程序就可以运行。请参阅最后一个playpen示例