作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用async-tungstenite来监听websocket,并使用async-std的StreamExt对结果流进行操作。
我想使用HashMap从websocket累积最新的股票行情指示器值。这些股票行情值将在以后查找以用于计算。我正在使用Ticker结构的symbol(String)值作为HashMap的键。我正在使用.scan StreamExt方法执行累积。
但是,我收到与生存期有关的编译错误。这是一些简化的代码:
let tickers = HashMap::new();
let mut stream = ws.
.scan(tickers, accumulate_tickers);
while let msg = stream.next().await {
println!("{:?}", msg)
}
...以及accumulate_tickers函数:
fn accumulate_tickers(tps: &mut HashMap<String, Ticker>, bt: Ticker) -> Option<&HashMap<String, Ticker>> {
tps.insert((*bt.symbol).to_string(), bt);
Some(tps)
}
我收到的编译错误如下:
error[E0271]: type mismatch resolving `for<'r> <for<'s> fn(&'s mut std::collections::HashMap<std::string::String, ws_async::model::websocket::Ticker>, ws_async::model::websocket::Ticker) -> std::option::Option<&'s std::collections::HashMap<std::string::String, ws_async::model::websocket::Ticker>> {accumulate_tickers} as std::ops::FnOnce<(&'r mut std::collections::HashMap<std::string::String, ws_async::model::websocket::Ticker>, ws_async::model::websocket::Ticker)>>::Output == std::option::Option<_>`
--> examples/async_std-ws.rs:64:4
|
64 | .scan(tickers, accumulate_tickers);
| ^^^^ expected bound lifetime parameter, found concrete lifetime
我不知道一种为扫描方法提供生命周期参数的方法。
最佳答案
我能够做到这一点。在解决编译器错误的过程中,我最终获得了accumulate_tickers
函数的以下签名:
fn accumulate_tickers<'a>(tps: &'a mut &'static HashMap<String, Ticker>, bt: Ticker) -> Option<&'static HashMap<String, Ticker>>
我确实希望累加器HashMap具有静态生存期,这样才有意义。
tps: &'a mut &'static HashMap...
看起来确实有些奇怪,但是可以工作。
tickers
还必须具有静态生存期(这是累加器的初始值。我尝试在
main
之外将其声明为静态,但不允许我将其设置为函数的结果-
HashMap::new()
。
lazy_static! {
static ref tickers: HashMap<String, Ticker> = HashMap::new();
}
这给了我一个具有静态生存期的HashMap累加器。但是,就像在根作用域中声明的普通静态值一样,它是不可变的。为了解决这个问题,我阅读了lazy_static团队的一些提示,然后找到了
https://pastebin.com/YES8dsHH。这向我展示了如何通过将其包装在
Arc<Mutex<_>>
中来使我的静态累加器可变。
lazy_static! {
// from https://pastebin.com/YES8dsHH
static ref tickers: Arc<Mutex<HashMap<String, Ticker>>> = {
let mut ts = HashMap::new();
Arc::new(Mutex::new(ts))
};
}
这确实意味着我必须在读取或修改它之前从Mutex中检索累加器(并锁定它),但是再次起作用。
#[macro_use]
extern crate lazy_static;
lazy_static! {
// from https://pastebin.com/YES8dsHH
static ref tickers: Arc<Mutex<HashMap<String, Ticker>>> = {
let mut ts = HashMap::new();
Arc::new(Mutex::new(ts))
};
}
// SNIP
// Inside main()
let mut ticks = ws
.scan(&tickers, accumulate_tickers);
while let Some(msg) = ticks.next().await {
println!("{:?}", msg.lock().unwrap());
}
// SNIP
fn accumulate_tickers<'a>(tps: &'a mut &'static tickers, bt: Ticker) -> Option<&'static tickers> {
tps.lock().unwrap().insert((*bt.symbol).to_string(), bt);
Some(tps)
}
我很高兴听到关于可以使之更简单或更优雅的建议。
关于rust - StreamExt .scan()方法上的“expected bound lifetime parameter, found concrete lifetime”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63193627/
我正在使用async-tungstenite来监听websocket,并使用async-std的StreamExt对结果流进行操作。 我想使用HashMap从websocket累积最新的股票行情指示器
我正在尝试将 rust future 流(重复)连接到水槽(排水管)。第一种方法工作正常(检查下面),但第二种使用 .forward 的方法无法编译(错误显示为内联)。关于我做错了什么的任何指示? u
我是一名优秀的程序员,十分优秀!