0

J'ai du mal à obtenir un comportement «simple»: diviser le code de correspondance de modèle en deux fonctions distinctes.Correspondance de motif: code fractionné avec fonction partielle?

Je simplifie le modèle à des fins de clarté:

abstract class Animal 
case object Dog extends Animal 
case object Cat extends Animal 
case object Bird extends Animal 
case object Bat extends Animal 
case object Dolphin extends Animal 

Je veux match de motif sur ceux-ci sur les différentes fonctions (parce que le code actuel est assez long), mais il y a d'autres arguments si PartialFunctions donnent moi les malades ...
Dans un monde parfait, je pourrais écrire:

type PF = PartialFunction[(Animal, Int, String), String] 
private def processFlying(a: Animal, n: Int, loc: String): PF = { 
    a match { 
    case Bird => n + " birds found in " + loc 
    case Bat => n + " bats found in " + underground(loc) 
    } 
} 
private def processMarine(a: Animal, n: Int, loc: String): PF = { 
    a match { 
    case Dolphin => n + " dolphins found in " + submarine(loc) 
    } 
} 
private def processPet(a: Animal, n: Int, loc: String): PF = { 
    a match { 
    case Dog => n + " dogs found in " + loc 
    case Cat => n + " cats found in " + loc 
    } 
} 
def processAnimal(a: Animal, number: Int, location: String) = { 
    val processAll = processFlying orElse processMarine orElse processPet 
    processAll(a, n, location) 
} 

Cependant cela ne fonctionne pas. Principalement parce que j'ai besoin de plusieurs arguments dans mes fonctions. "Pourquoi ne pas utiliser de tuples?" Dirais-tu? Eh bien, j'ai essayé et le compilateur ne cesser de se plaindre du type attendu est différent de celui type réel et différent à mon alias :(

Toute aide, des conseils ou d'autres ides sera utile!
Vive


EDIT: Je suivi la réponse de Cyrille bu Je dois aussi effectuer des travaux avant le match, comme celui-ci:

val processFlying: PF = { 
    // doSomething, like declare a sub-function f 
    { 
     case (b: Bird, n, loc) => f(b) 
     case (b: Bat, n, loc) => f(b) 
    } 
} 
+0

Pourquoi votre sous-fonction doit-elle être dans le 'val'? Est-ce que ça ne peut pas être, disons un 'private def' à côté? –

+0

C'est ce que j'ai fait, mais je n'en ai pas besoin ailleurs, alors ... :) De plus, je voulais en profiter en utilisant une fermeture. C'est du zèle, il semble que les choses fonctionnent bien maintenant. Mais si quelqu'un a une solution, je reste conscient –

Répondre

2

Votre problème est que vous mixez définition de la méthode et la fonction d l'éfinition

def processFlying(a: Animal, n: Int, loc: String): PF 

est la signature d'un procédé (de votre objet environnant), qui prend trois arguments et retourner un PF, soit un PartialFunction[(Animal, Int, String), String].

Ainsi, en supposant cette signature est ce que vous voulez, vous ne serez en mesure d'obtenir un PartialFunction si vous avez déjà un Animal, un Int et String ...

Qu'est-ce que vous voulez plus probablement est de définir une valeur PF (sans paramètres), donc plus quelque chose comme

val processFlying: PF = { 
    case (Bird, n, loc) => ... 
    case (Bat, n, loc) => ... 
} 

EDIT

Pour répondre à votre deuxième demande (bien que ce soit probablement exagéré, puisque la définition de votre aide en tant que def privé fera le travail), vous pouvez alway mettre le bloc PF dans une fermeture:

val processFlying = { 
    def f = ... 
    val res = { 
    case (Bird, n, loc) => f(...) 
    case (Bat, n, loc) => f(...) 
    } 
    res 
} 

Cependant, vous devez attribuez une valeur au bloc définissant PartialFunction, sinon l'analyseur aura du mal à savoir quoi en faire. C'est uniquement parce que PartialFunction définition avec case s bloc et les fermetures partagent la syntaxe {}.

+0

Vous me donnez de bons indices. Je commence à comprendre comment tout cela fonctionne. Cependant, j'ai un cas particulier (bien sûr): dans l'une de mes fonctions j'ai besoin d'insérer le code "avant le match". Je ne sais pas comment insérer du code dans un commentaire alors j'ai édité mon premier message. –