Domanda

Ho visto una funzione denominata implicitly utilizzato negli esempi di Scala.Cos'è e come viene utilizzato?

Esempio qui:

scala> sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
     |                         implicit def stringImpl = new Foo[String] {
     |                             def apply(list : List[String]) = println("String")
     |                         }
     |                         implicit def intImpl = new Foo[Int] {
     |                             def apply(list : List[Int]) =  println("Int")
     |                         }
     |                     } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit

scala> foo(1)
<console>:8: error: type mismatch;
 found   : Int(1)
 required: List[?]
       foo(1)
           ^
scala> foo(List(1,2,3))
Int
scala> foo(List("a","b","c"))
String
scala> foo(List(1.0))
<console>:8: error: could not find implicit value for evidence parameter of type
 Foo[Double]
       foo(List(1.0))
          ^

Nota che dobbiamo scrivere implicitly[Foo[A]].apply(x) poiché il compilatore lo pensa implicitly[Foo[A]](x) significa che chiamiamo implicitly con parametri.

Vedi anche Come indagare su oggetti/tipi/ecc.dalla Scala REPL? E Dove cerca Scala gli impliciti?

È stato utile?

Soluzione

Ecco alcuni motivi per utilizzare questo metodo deliziosamente semplice implicitly.

Comprendere/risolvere i problemi relativi alle visualizzazioni implicite

Una vista implicita può essere attivata quando il prefisso di una selezione (considerare ad esempio, the.prefix.selection(args) non contiene un membro selection questo è applicabile a args (anche dopo aver provato a convertire args con visualizzazioni implicite).In questo caso, il compilatore cerca membri impliciti, definiti localmente negli ambiti corrente o di inclusione, ereditati o importati, che siano funzioni del tipo di quello the.prefix a un tipo con selection metodi impliciti definiti o equivalenti.

scala> 1.min(2) // Int doesn't have min defined, where did that come from?                                   
res21: Int = 1

scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>

scala> res22(1) // 
res23: AnyRef{def min(i: Int): Int} = 1

scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt

Le visualizzazioni implicite possono anche essere attivate quando un'espressione non è conforme al tipo previsto, come di seguito:

scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1

Qui il compilatore cerca questa funzione:

scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>

Accesso a un parametro implicito introdotto da un contesto vincolato

I parametri impliciti sono probabilmente una caratteristica più importante di Scala rispetto alle visualizzazioni implicite.Supportano il modello di classe tipo.La libreria standard lo usa in alcuni posti - vedi scala.Ordering e come viene utilizzato SeqLike#sorted.I parametri impliciti vengono utilizzati anche per passare manifest di array e CanBuildFrom istanze.

Scala 2.8 consente una sintassi abbreviata per i parametri impliciti, chiamata Limiti di contesto.In breve, un metodo con un parametro di tipo A che richiede un parametro implicito di tipo M[A]:

def foo[A](implicit ma: M[A])

può essere riscritto come:

def foo[A: M]

Ma che senso ha passare il parametro implicito ma non nominarlo?Come può essere utile quando si implementa il metodo foo?

Spesso non è necessario fare riferimento direttamente al parametro implicito, ma verrà incanalato come argomento implicito in un altro metodo chiamato.Se è necessario, puoi comunque conservare la firma concisa del metodo con Context Bound e chiamare implicitly per materializzare il valore:

def foo[A: M] = {
   val ma = implicitly[M[A]]
}

Passaggio esplicito di un sottoinsieme di parametri impliciti

Supponiamo di chiamare un metodo che stampa in modo carino una persona, utilizzando un approccio basato sulla classe di tipo:

trait Show[T] { def show(t: T): String }
object Show {
  implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
  implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }

  def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}

case class Person(name: String, age: Int)
object Person {
  implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
    def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
  }
}

val p = Person("bob", 25)
implicitly[Show[Person]].show(p)

E se volessimo cambiare il modo in cui viene visualizzato il nome?Possiamo chiamare esplicitamente PersonShow, passa esplicitamente un'alternativa Show[String], ma vogliamo che il compilatore passi il file Show[Int].

Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)

Altri suggerimenti

Implicitly è Disponibile in Scala 2.8 ed è definito nella Predef come:

def implicitly[T](implicit e: T): T = e

È comunemente usato per controllo se un implicito valore di tipo T è disponibile e restituirlo se tale è il caso.

Esempio semplice da di retronym presentazione :

scala> implicit val a = "test" // define an implicit value of type String
a: java.lang.String = test
scala> val b = implicitly[String] // search for an implicit value of type String and assign it to b
b: String = test
scala> val c = implicitly[Int] // search for an implicit value of type Int and assign it to c
<console>:6: error: could not find implicit value for parameter e: Int
       val c = implicitly[Int]
                         ^

A "insegnerà a pescare" risposta è quella di utilizzare l'indice membro alfabetica attualmente disponibile nel Scaladoc . Le lettere (e il #, per i nomi non alfabetici) nella parte superiore del riquadro pacchetto / classe sono collegamenti con l'indice per i nomi dei membri che iniziano con quella lettera (in tutte le classi). Se si sceglie I, per esempio, troverete la voce implicitly con una sola occorrenza, in Predef, che si può visitare dal link lì.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top