Definizione di una funzione con più argomenti impliciti in Scala


94

Come posso definire una funzione con più argomenti impliciti.

def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work

2
Nel testo della domanda chiedi informazioni su una funzione. Nello snippet di codice hai un metodo. Stai chiedendo informazioni su una funzione o un metodo?
Jörg W Mittag

Risposte:


190

Devono essere inseriti tutti in un elenco di parametri e questo elenco deve essere l'ultimo.

def myfun(arg:String)(implicit p1: String, p2:Int)={} 

1
Se fosse una classe la sintassi sarebbe class MyClass () (implicit p1: String, implicit p2: Int) {}
skjagini

2

In realtà c'è un modo per fare esattamente ciò che richiede l'OP. Un po 'contorto, ma funziona.

class MyFunPart2(arg: String, /*Not implicit!*/ p1: String) {
  def apply(implicit p2: Int) = {
    println(arg+p1+p2)
    /* otherwise your actual code */
  }
}

def myFun(arg: String)(implicit p1: String): MyFunPart2= {
  new MyFunPart2(arg, p1)
}

implicit val iString= " world! "
implicit val iInt= 2019

myFun("Hello").apply
myFun("Hello")(" my friend! ").apply
myFun("Hello")(" my friend! ")(2020)

//  Output is:
//      Hello world! 2019
//      Hello my friend! 2019
//      Hello my friend! 2020

In Scala 3 (noto anche come "Dotty", sebbene questo sia il nome del compilatore) invece di restituire un oggetto MyFunPart2 ausiliario , è possibile restituire direttamente un valore di funzione con argomenti impliciti. Questo perché Scala 3 supporta le "funzioni implicite" (cioè "il parametro implicito" ora fa parte dei tipi di funzione). Più elenchi di parametri impliciti diventano così facili da implementare che è possibile che il linguaggio li supporti direttamente, anche se non ne sono sicuro.


1

C'è un altro modo (IMO più semplice e più flessibile) per ottenere un effetto simile:

// Note the implicit is now a Tuple2
def myFun(arg: String)(implicit p: (String, Int) ): Unit = {
  println(arg + p._1 + p._2)
  /*otherwise your actual code*/
}

// These implicit conversion are able to produce the basic implicit (String,Int) Tuples
implicit def idis(implicit is: String, ii: Int): (String,Int)= (is,ii)
implicit def idi(s: String)(implicit ii: Int): (String,Int)= (s,ii)

// The basic implicit values for both underlying parameters
implicit val iString = " world! "
implicit val iInt = 2019

myFun("Hello")
myFun("Hello")(" my friend! ")
myFun("Hello")(" my friend! ",2020)

// Output is:
//     Hello world! 2019
//     Hello my friend! 2019
//     Hello my friend! 2020

// If we add the following implicit, 
implicit def ids(i: Int)(implicit is: String)= (is,i)

// we can even do
myFun("Hello")(2020)

// , and output is:
//     Hello world! 2020

Usare una tupla come rappresentazione sottostante per i parametri non è una buona idea perché le conversioni implicite potrebbero interferire con altri usi. In realtà, le conversioni implicite a qualsiasi tipo standard (comprese quelle di libreria) di solito creano problemi in qualsiasi applicazione non banale. La soluzione è creare una classe case dedicata per contenere i parametri invece di una tupla. Un vantaggio importante è che potrebbero essere assegnati nomi molto più significativi di _1 e _2.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.