请考虑以下代码(简化但可编译):
use std::sync::Arc;
pub trait ActorRef<Message> { /* ... */ }
pub trait Actor<Message> { /* ... */ }
pub trait ActorSpawner {
/// Spawns a new actor returning an actor ref
/// for passing messages to it.
fn spawn<Message,A,R>(actor: A) -> Arc<R>
where R: ActorRef<Message>, A: Actor<Message>;
}
Run Code Online (Sandbox Code Playgroud)
是否可以实现ActorSpawner::spawn或实现与其他签名类似的东西?
问题中的代码被简化以将其减少到我无法解决的核心部分.
通常,Actor应该具有由处理消息改变的可变状态(示例中缺少处理方法).您可以生成一个Actor并可以通过它与它通信ActorRef(示例中缺少send方法).
我想允许不同的"产卵"方式Actor.例如,消息处理可能发生在每个actor的一个线程上.或者可以在由其他actor共享的线程池上完成处理.
其他代码可能依赖于创建更多actor.使用的基础机制应该是抽象的.既然有特质ActorSpawner.
让我们假设我们有一些虚拟实现Actor和ActorRef:
struct NoopActor;
impl<Message> Actor<Message> for NoopActor {}
struct DeadRef;
impl<Message> ActorRef<Message> for DeadRef {}
Run Code Online (Sandbox Code Playgroud)
现在应该可以使用这些虚拟实现以某种方式实现特征.
这是我的第一次尝试:
struct DeadActorSpawner;
impl ActorSpawner for DeadActorSpawner {
fn spawn<Message,A,R>(actor: A) -> Arc<R>
where R: ActorRef<Message>, A: Actor<Message>
{
Arc::new(DeadRef)
}
}
Run Code Online (Sandbox Code Playgroud)
导致此错误:
error[E0308]: mismatched types
--> src/main.rs:29:18
|
29 | Arc::new(DeadRef)
| ^^^^^^^ expected type parameter, found struct `DeadRef`
|
= note: expected type `R`
found type `DeadRef`
Run Code Online (Sandbox Code Playgroud)
或另一个:
struct DeadActorSpawner;
impl ActorSpawner for DeadActorSpawner {
fn spawn<Message,A,R>(actor: A) -> Arc<DeadRef>
{
Arc::new(DeadRef)
}
}
Run Code Online (Sandbox Code Playgroud)
导致此错误:
error[E0053]: method `spawn` has an incompatible type for trait
--> src/main.rs:25:42
|
12 | fn spawn<Message, A, R>(actor: A) -> Arc<R>
| ------ type in trait
...
25 | fn spawn<Message, A, R>(actor: A) -> Arc<DeadRef> {
| ^^^^^^^^^^^^ expected type parameter, found struct `DeadRef`
|
= note: expected type `fn(A) -> std::sync::Arc<R>`
found type `fn(A) -> std::sync::Arc<DeadRef>`
Run Code Online (Sandbox Code Playgroud)
我已经尝试了许多其他的东西无济于事,包括使用相关类型的Messagein Actor和ActorRef.
是否可以实施
ActorSpawner::spawn
是的,但据我所知没有有用的实现
或者用另一个签名来实现类似的效果
我相信您正在等待Arc<ActorRef<Message>>返回。因此,您可以在不了解 * 类型的情况下使用DeadActorSpawnerthrough特征。ActorSpawnerDead
您实际上所做的是尝试专门化该spawn函数以返回Arc<DeadRef>. 我修改了你的ActorSpawner返回一个特征对象:
pub trait ActorSpawner {
fn spawn<Message, A>(actor: A) -> Arc<ActorRef<Message>> where A: Actor<Message>;
}
struct DeadActorSpawner;
impl ActorSpawner for DeadActorSpawner {
fn spawn<Message, A>(actor: A) -> Arc<ActorRef<Message>>
where A: Actor<Message>
{
Arc::new(DeadRef)
}
}
Run Code Online (Sandbox Code Playgroud)