我想要写的函数签名
虽然不符合语法,但最接近我的本意
fn spmc_test_scope(
make_worker: impl for<'a> Fn(i32, &'a Mutex<Vec<i32>>) -> impl FnOnce() + Send + 'a)
我想要跑的代码
use std::sync::Mutex;
use std::thread;
use std::time::{Instant, Duration};
use std::vec::Vec;
fn spmc_test_scope(
make_worker: impl for<'a> Fn(i32, &'a Mutex<Vec<i32>>) -> impl FnOnce() + Send + 'a)
{
let queue = Mutex::new(Vec::from_iter(0..32));
let begin = Instant::now();
thread::scope(|s| {
for id in 0..4 {
s.spawn(make_worker(id, &queue));
}
});
println!("used: {} ns", Instant::now().duration_since(begin).as_micros());
}
fn main() {
spmc_test_scope(|id, queue| move || {
let mut count = 0;
let mut sum = 0i64;
while let Some(num) = { let num = queue.lock().unwrap().pop(); num } {
sum += num as i64;
count += 1;
thread::sleep(Duration::new(0, 10));
}
println!("id:{id} count:{count} sum:{sum}");
});
spmc_test_scope(|id, queue| move || {
let mut count = 0;
let mut product = 1i64;
while let Some(num) = { let num = queue.lock().unwrap().pop(); num } {
product *= num as i64;
count += 1;
thread::sleep(Duration::new(0, 10));
}
println!("id:{id} count:{count} product:{product}");
});
}
尝试
- 函数签名正确,实现报错在
thread::scope(|s| {
fn spmc_test_scope<'a, W, MW>(make_worker: MW)
where W: FnOnce() + Send + 'a, MW: Fn(i32, &'a Mutex<Vec<i32>>) -> W
- 函数签名正确,调用错误,与想要的不符: where 里面的两个 'a 没有关系
fn spmc_test_scope<W, MW>(make_worker: MW)
where for<'a> W: FnOnce() + Send + 'a, for<'a> MW: Fn(i32, &'a Mutex<Vec<i32>>) -> W
- type_alias_impl_trait 改下可以运行, 但 spmc_test_scope 不能多次调用, 因为 Worker<'a> 是一个类型,而不是泛型约束
type Worker<'a> = impl FnOnce() + Send + 'a;
fn spmc_test_scope<MW>(make_worker: MW)
where for<'a> MW: Fn(i32, &'a Mutex<Vec<i32>>) -> Worker<'a>
type Worker<'a> = impl FnOnce() + Send + 'a;
fn spmc_test_scope(
make_worker: impl for<'a> Fn(i32, &'a Mutex<Vec<i32>>) -> Worker<'a>)
#![feature(type_alias_impl_trait)]
use std::sync::Mutex;
use std::thread;
use std::time::{Instant, Duration};
use std::vec::Vec;
type Worker<'a> = impl FnOnce() + Send + 'a;
fn spmc_test_scope(
make_worker: impl for<'a> Fn(i32, &'a Mutex<Vec<i32>>) -> Worker<'a>)
{
let queue = Mutex::new(Vec::from_iter(0..32));
let begin = Instant::now();
thread::scope(|s| {
for id in 0..4 {
s.spawn(make_worker(id, &queue));
}
});
println!("used: {} ns", Instant::now().duration_since(begin).as_micros());
}
fn main() {
spmc_test_scope(|id, queue| move || {
let mut count = 0;
let mut sum = 0i64;
while let Some(num) = { let num = queue.lock().unwrap().pop(); num } {
sum += num as i64;
count += 1;
thread::sleep(Duration::new(0, 10));
}
println!("id:{id} count:{count} sum:{sum}");
});
/*
spmc_test_scope(|id, queue| move || {
let mut count = 0;
let mut product = 1i64;
while let Some(num) = { let num = queue.lock().unwrap().pop(); num } {
product *= num as i64;
count += 1;
thread::sleep(Duration::new(0, 10));
}
println!("id:{id} count:{count} product:{product}");
});
*/
}
1
共 10 条评论, 1 页
评论区
写评论巧了,首页的新问题 【求助】 ITIFTR 和 opaque type 里面提到
#![feature(impl_trait_in_fn_trait_return)]
这一看就能解决我最早写出的定义的问题但结果还是报错, 根据这些issues
Tracking Issue for impl Trait as output type of Fn traits in function return position
Multiple nested impl Trait in trait method does not work
Fn trait doesn't allow impl returns (impl Fn() -> impl Trait), which is inconsistent with all other traits
看起来还没做好。
从功能实现的角度上讲,当然苦瓜小仔的一种改进的做法:playground 最好, 高效且容易理解。
我之前写的时候一时脑子发昏,才写出那种复杂的定义。
当然,
Box<dyn>
总能让他跑起来。但是从语言律师的角度,
for<T: SomeTrait>
之类的语法,应该是有必要的。感觉是下面这个方法好,向闭包内传引用就解决生命周期的问题了。
--
👇
苦瓜小仔: 一种低效的做法:playground
一种改进的做法:playground
一个可行的方法
官网 HRTB 的讨论里面提出过
for<T: SomeTrait>
的语法 issue#1481按此语法应该可以写成这样
这个讨论也类似于此问题,pnkfelix 在此收集大量的相关问题 issue#56537
--
👇
TLMegalovania: 在rust forum上有类似问题么
在rust forum上有类似问题么
我知道下面的错在哪了, 最后的
+ 'a
, 本意是加在 W 上面, 但实际是加在 MW 上了那么再改写, 写清楚结合性, 但是语法错误
设想的语法, 对多个泛型参数有效的
for<'a>
语法另一种设想的语法
一种低效的做法:playground
一种改进的做法:playground
函数签名应该是对的.
不写任何生存期参数, 也是调用处报 lifetime may not live long enough
之前写过下面的,函数签名直接就报错,原来调一下 for<'a> 的位置就可以的啊
--
👇
TLMegalovania: 4. lifetime may not live long enough