Aqui estão algumas razões para usar o método deliciosamente simples implicitly
.
Para entender / solucionar problemas de vistas implícitas
Uma visualização implícita pode ser acionada quando o prefixo de uma seleção (considere, por exemplo, the.prefix.selection(args)
não contém um membro selection
aplicável a ele args
(mesmo depois de tentar converter args
com as visualizações implícitas) .Neste caso, o compilador procura por membros implícitos, definidos localmente nos escopos atuais ou anexos, herdados ou importados, que são Funções do tipo the.prefix
para um tipo com selection
métodos implícitos definidos ou equivalentes.
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
As vistas implícitas também podem ser acionadas quando uma expressão não está em conformidade com o tipo esperado, como abaixo:
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
Aqui o compilador procura esta função:
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
Acessando um parâmetro implícito introduzido por um limite de contexto
Parâmetros implícitos são indiscutivelmente um recurso mais importante do Scala que as visualizações implícitas. Eles suportam o padrão de classe de tipo. A biblioteca padrão usa isso em alguns lugares - veja scala.Ordering
e como é usado SeqLike#sorted
. Parâmetros implícitos também são usados para transmitir manifestos e CanBuildFrom
instâncias de matriz .
O Scala 2.8 permite uma sintaxe abreviada para parâmetros implícitos, chamados limites de contexto. Resumidamente, um método com um parâmetro de tipo A
que requer um parâmetro implícito do tipo M[A]
:
def foo[A](implicit ma: M[A])
pode ser reescrito como:
def foo[A: M]
Mas qual é o sentido de passar o parâmetro implícito, mas não de nomeá-lo? Como isso pode ser útil ao implementar o método foo
?
Freqüentemente, o parâmetro implícito não precisa ser referido diretamente, ele será encaminhado como um argumento implícito para outro método chamado. Se for necessário, você ainda pode manter a assinatura do método conciso com o Limite de Contexto e chamar implicitly
para materializar o valor:
def foo[A: M] = {
val ma = implicitly[M[A]]
}
Passando um subconjunto de parâmetros implícitos explicitamente
Suponha que você esteja chamando um método que imprima bastante uma pessoa, usando uma abordagem baseada em classe de 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 quisermos mudar a maneira como o nome é exibido? Podemos chamar explicitamente PersonShow
, passar explicitamente uma alternativa Show[String]
, mas queremos que o compilador passe a Show[Int]
.
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)
Implicitly
está disponível no Scala 2.8 e é definido no Predef como:É comumente usado para verificar se um valor implícito do tipo
T
está disponível e retorná-lo, se for o caso.Exemplo simples da apresentação do retronym :
fonte
implicitly[Ordering[(Int, String)]].compare( (1, "b"), (1, "a") )
, especialmente para recuperar um parâmetro implícito introduzido por um limite de contexto:def foo[A: Ordering](a1: A, a2: A) = implicitly[Ordering[A]].compare(a1, a2)
Uma resposta "ensinar você a pescar" é usar o índice alfabético de membros atualmente disponível nas noites de Scaladoc . As letras (e os
#
nomes não alfabéticos) na parte superior do painel pacote / classe são links para o índice de nomes de membros que começam com essa letra (em todas as classes). Se você escolherI
, por exemplo, você encontrará aimplicitly
entrada com uma ocorrência, emPredef
, que pode ser acessada no link lá.fonte
implicit
parece ser uma característica importante da linguagem em Scala e definitivamente merece uma explicação adequada. Pensar que os documentos que detalham apenas uma contagem de assinaturas de tipo parece mais com satisfação pessoal do que uma resposta genuína. Veja as perguntas específicas feitas pelo OP - o que é e como é usado? Nem respondeu por isso nem nos documentos noturnos aos quais você nem fornece um link real. scala-lang.org/files/archive/nightly/docs/library/… Isso não ensina nada. Veja Niklaus Wirth ou Turbo Pascal para exemplos de documentos originais. -1implicit
eimplicitly
são relacionados, mas bem distintos. Aimplicit
palavra-chave faz parte do idioma.implicitly
é definido no código Scala simples na biblioteca padrão. Como os documentos on-line incluem links de origem, acredito que ainda é melhor encaminhar os questionadores para esses documentos e a fonte vinculada.