我正在编写一个WebSocket服务器,其中一个Web客户端连接到多线程计算机AI上下棋.WebSocket服务器想要将Logger对象传递给AI代码.该Logger对象将管理从AI到Web客户端的日志行.在Logger必须包含对客户端连接的参考.
我对生命周期如何与线程交互感到困惑.我用Wrapper类型参数化的结构重现了这个问题.该run_thread函数尝试解包该值并记录它.
use std::fmt::Debug;
use std::thread;
struct Wrapper<T: Debug> {
val: T,
}
fn run_thread<T: Debug>(wrapper: Wrapper<T>) {
let thr = thread::spawn(move || {
println!("{:?}", wrapper.val);
});
thr.join();
}
fn main() {
run_thread(Wrapper::<i32> { val: -1 });
}
Run Code Online (Sandbox Code Playgroud)
该wrapper参数存在于堆栈中,并且它的生命周期不会延伸超过run_thread堆栈帧,即使该线程将在堆栈帧结束之前连接.我可以从堆栈中复制值:
use std::fmt::Debug;
use std::thread;
struct Wrapper<T: Debug + Send> {
val: T,
}
fn run_thread<T: Debug + Send + 'static>(wrapper: Wrapper<T>) {
let thr = thread::spawn(move || …Run Code Online (Sandbox Code Playgroud) 我编写了一个程序,它具有特征Animal和Dog实现特征的结构.它还有一个AnimalHouse存储动物作为特征对象的结构Box<Animal>.
trait Animal {
fn speak(&self);
}
struct Dog {
name: String,
}
impl Dog {
fn new(name: &str) -> Dog {
return Dog {
name: name.to_string(),
};
}
}
impl Animal for Dog {
fn speak(&self) {
println!{"{}: ruff, ruff!", self.name};
}
}
struct AnimalHouse {
animal: Box<Animal>,
}
fn main() {
let house = AnimalHouse {
animal: Box::new(Dog::new("Bobby")),
};
house.animal.speak();
}
Run Code Online (Sandbox Code Playgroud)
它返回"Bobby:ruff,ruff!" 正如所料,但如果我尝试克隆house编译器返回错误:
fn main() {
let house …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试在Rust中实现一个简单的Parser-Combinator库.为此,我希望有一个泛型map函数来转换解析器的结果.
问题是我不知道如何复制持有闭包的结构.示例是Map以下示例中的结构.它有一个mapFunction存储函数的字段,它接收前一个解析器的结果并返回一个新结果.Map它本身就是一个可以与其他解析器进一步组合的解析器.
但是,对于要组合的解析器,我需要它们是可复制的(具有Clone特征限制),但是我该如何提供Map呢?
示例:(只有伪代码,很可能无法编译)
trait Parser<A> { // Cannot have the ": Clone" bound because of `Map`.
// Every parser needs to have a `run` function that takes the input as argument
// and optionally produces a result and the remaining input.
fn run(&self, input: ~str) -> Option<(A, ~str)>
}
struct Char {
chr: char
}
impl Parser<char> for Char {
// The char parser returns Some(char) if …Run Code Online (Sandbox Code Playgroud) 如果我想要一个不可复制的类型擦除(动态类型)可调用,那就是
Box<dyn Fn(i32) -> ()>
Run Code Online (Sandbox Code Playgroud)
如果我想要一个引用计数类型擦除的可调用对象,那就是(取决于我是否需要线程安全)
Rc<dyn Fn(i32) -> ()>
Arc<dyn Fn(i32) -> ()>
Run Code Online (Sandbox Code Playgroud)
但在这里,这些副本都引用相同的底层内存——它们并不不同。
如果我想要不同的可调用对象,我该怎么做?当Implements时Box<T>已经实现,但未实现,因此不适用于此处。做类似的事情:CloneTCloneFnClone
Box<dyn Fn(i32) -> () + Clone>
Run Code Online (Sandbox Code Playgroud)
失败并显示:
error[E0225]: only auto traits can be used as additional traits in a trait object
--> src/main.rs:7:35
|
7 | fn foo(f: Box<dyn Fn(i32) -> () + Clone>) {
| ------------- ^^^^^ additional non-auto trait
| |
| first non-auto trait
|
= help: consider creating a new trait …Run Code Online (Sandbox Code Playgroud) 我无法以紧凑的方式克隆地图:
extern crate itertools_num;
use itertools_num::linspace;
fn main() {
// 440Hz as wave frequency (middle A)
let freq: f64 = 440.0;
// Time vector sampled at 880 times/s (~Nyquist), over 1s
let delta: f64 = 1.0 / freq / 2.0;
let time_1s = linspace(0.0, 1.0, (freq / 2.0) as usize)
.map(|sample| { sample * delta});
let sine_440: Vec<f64> = time_1s.map(|time_sample| {
(freq * time_sample).sin()
}).collect();
let sine_100: Vec<f64> = time_1s.map(|time_sample| {
(100.0 * time_sample).sin()
}).collect();
}
Run Code Online (Sandbox Code Playgroud)
我用这段代码得到的错误是
`time_1s` moved here …Run Code Online (Sandbox Code Playgroud) 我试图了解 Rust 中的所有权,但遇到了与转让所有权相关的误解。考虑以下代码:
fn main() {
let closure = || 32;
foo(closure);
foo(closure); //perfectly fine
}
fn foo<F>(f: F) -> u32
where
F: Fn() -> u32,
{
f()
}
Run Code Online (Sandbox Code Playgroud)
我认为应该转让所有权,foo(closure)不允许第二次调用。
为什么有效?
当我尝试编译此代码(playground)时:
fn main() {
let iter = "abc123".chars().filter(&|&c: &char| c.is_digit(10));
match iter.clone().take(3).count() {
3 => println!("{}", iter.collect::<String>()),
_ => {}
}
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
error: borrowed value does not live long enough
--> test.rs:2:41
|
2 | let iter = "abc123".chars().filter(&|c: &char| c.is_digit(10));
| ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value only lives until here
| |
| temporary value created here
...
7 | }
| - temporary value needs to live until here
|
= note: consider using a `let` …Run Code Online (Sandbox Code Playgroud)