2017-09-11 1 views
0

Je vais avoir des difficultés à convertir ce trait Scala à RustComment convertir une implémentation de trait anonyme Scala en Rust?

trait Inject[A, B] { 
    self => 

    def inject(input: A): B 

    def project(input: B): Try[A] 

    def contraMap[AA](inj: Inject[AA, A]): Inject[AA, B] = new Inject[AA, B] { 
    override def inject(input: AA) = self.inject(inj.inject(input)) 

    override def project(input: B) = self.project(input).flatMap(i => inj.project(i)) 
    } 

    def map[BB](inj: Inject[B, BB]): Inject[A, BB] = new Inject[A, BB] { 
    override def inject(input: A) = inj.inject(self.inject(input)) 

    override def project(input: BB) = inj.project(input).flatMap(i => self.project(i)) 
    } 

} 

Voici mon Rust équivalent

pub trait Injection<A, B> { 
    fn inject(input: A) -> B; 
    fn project(input: B) -> Result<A, InjectionError>; 
    fn contraMap<AA>(input: Injection<AA, A>) -> Injection<AA, B>; 
    fn map<BB>(input: Injection<B, BB>) -> Injection<A, BB>; 
} 

pub struct InjectionError { 
    msg: String, 
} 

Je reçois:

error[E0038]: the trait `Injection` cannot be made into an object 
--> src/main.rs:4:5 
    | 
4 |  fn contraMap<AA>(input: Injection<AA, A>) -> Injection<AA, B>; 
    |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Injection` cannot be made into an object 
    | 
    = note: method `inject` has no receiver 
    = note: method `project` has no receiver 
    = note: method `contraMap` has no receiver 
    = note: method `map` has no receiver 

Si j'ajoute une référence self, Je reçois toujours la même erreur:

pub trait Injection<A, B> { 
    fn inject(&self, input: A) -> B; 
    fn project(&self, input: B) -> Result<A, InjectionError>; 
    fn contraMap<AA>(&self, input: Injection<AA, A>) -> Injection<AA, B>; 
    fn map<BB>(&self, input: Injection<B, BB>) -> Injection<A, BB>; 
} 

pub struct InjectionError { 
    msg: String, 
} 

Je ne suis pas sûr comment je peux instancier un anonyme Injection comme je le fais en Scala. Quelle serait la manière idiomatique de convertir ce trait Scala à Rust?

+2

S'il vous plaît produire un [MCVE], vous pouvez utiliser le terrain de jeu de rouille pour le faire. Vous pouvez également rechercher votre message d'erreur sur Google, il est déjà apparu beaucoup de fois sur stackoverflow. –

+1

Actuellement, votre définition de 'Injection' contient quatre ** fonctions statiques **. Si vous voulez définir des méthodes, vous devez spécifier le paramètre 'self'. Je recommande de (re) lire le chapitre sur la syntaxe de la méthode: https://doc.rust-lang.org/book/second-edition/ch05-03-method-syntax.html –

+2

Généralement, vous n'aurez pas de temps facile en essayant de traduire directement Scala à Rust. Il serait beaucoup plus facile de commencer en expliquant ce que vous essayez d'accomplir. –

Répondre

0

Dans Rust, les traits ne décrivent que le comportement et non les données. Le compilateur vous dit que votre trait n'est pas sûr pour les objets car vous voulez renvoyer tout ce qui implémente le trait, et que 'n'importe quoi' n'a pas de taille canonique connue au moment de la compilation.

Vous pouvez Box vos valeurs pour les mettre sur le tas, ou utiliser des références (ce qui nécessitera une jonglerie de vie effrayante et sera assez fragile, mais évitez l'allocation). Vous devrez également renvoyer un type concret de map et contraMap. Regardez comment le trait Iterator de Rust le fait: Il renvoie un Map qui est générique sur l'itérateur d'origine et le type de fonction qu'il mappe, enveloppe les deux et implémente Iterator.