2012-03-09 13 views
7

ho un metodo, con un sacco di parametri impliciti:implicito all'interno di pattern match

def hello(message:String)(implicit a:A,b:B,c:C, ..., user: User) = {...} 

Consideriamo ora un tale classe:

object Users extends Controller { 
    implicit a: A = ... 
    implicit b: B = ... 
    ... 

    def index(id:String) = Action { 
    User.findById(id) match { 
     case Some(user) => { 
      implicit val _user = user 
      hello("implicit") 
     } 
     case _ => BadRequest 
    } 
    } 
} 

Si può vedere questa linea nel campione di cui sopra:

implicit val _user = user 

esiste solo per rendere l'oggetto user come oggetto implicito. In caso contrario, devo chiamare hello come:

hello("implicit")(a,b,c,... user) 

mi viene da pensare se non v'è alcun modo per migliorare il codice, ad esempio, non è necessario definire la variabile _user ma rendere lo user implicito.

risposta

5

Sì, c'è un modo per eliminare _user variabile mentre facendo user implicita:

def index(id:String) = Action { 
    User.findById(id) map (implicit user => hello("implicit")) getOrElse BadRequest 
} 

UPDATE: Addressing la tua domanda su molti casi nei commenti qui sotto.

Tutto dipende dal tipo di valore restituito da User.findById. Se si tratta di Option[User] ma si vuole abbinare sugli utenti specifici (supponendo User è una classe caso), allora la soluzione originale si applica ancora:

def index(id:String) = Action { 
    User.findById(id) map { implicit user => 
    user match { 
     case User("bob") => hello("Bob") 
     case User("alice") => hello("Alice") 
     case User("john") => hello("John") 
     case _ => hello("Other user") 
    } 
    } getOrElse BadRequest 

Oppure si può abbinare a qualsiasi altra cosa se si vuole, a patto che User.findById è String => Option[User]

Se, d'altra parte, è User.findByIdString => User allora si può semplicemente definire un oggetto di supporto come:

object withUser { 
    def apply[A](user: User)(block: User => A) = block(user) 
} 

e usarlo come fo llows (sempre assumendo User è una classe caso):

def index(id: String) = Action { 
    withUser(User findById id) { implicit user => 
    user match { 
     case User("bob") => hello("Bob") 
     case User("alice") => hello("Alice") 
     case User("john") => hello("John") 
     case _ => BadRequest 
    } 
    } 
} 

o corrispondente su un altro valore, diciamo un Int:

def index(id: String, level: Int) = Action { 
    withUser(User findById id) { implicit user => 
    level match { 
     case 1 => hello("Number One") 
     case 2 => hello("Number Two") 
     case 3 => hello("Number Three") 
     case _ => BadRequest 
    } 
    } 
} 

Spero che questo copre tutti gli scenari che si possono avere.

+0

+1, è una buona soluzione se il modello corrisponde ad una 'Opzione'. Ma cosa succede se ci sono molti 'case's? – Freewind

+0

@Freewind. Ho aggiornato la mia risposta per coprire molti 'casi'. – romusz

2

Non conosco nessun trucco come il caso Some(implicit user) ma per quanto riguarda

def hello(message: String, user: User)(implicit a: A, ... z: Z) = ... 
def hello(message: String)(implicit a: A, ... z: Z, user: User) = hello(message, user) 

case Some(user) => hello("implicit", user) 
+0

Grazie. Penso che 'ciao (messaggio) (implicito ...)' dovrebbe essere quello esistente e non può essere modificato, altrimenti non abbiamo bisogno di definirlo, basta definire un 'ciao (messaggio, utente) (implicito .. .) è sufficiente. – Freewind