Um dos novos recursos do Scala 2.8 são os limites de contexto. O que é um limite de contexto e onde ele é útil?
Claro que pesquisei primeiro (e encontrei, por exemplo, isto ), mas não consegui encontrar nenhuma informação realmente clara e detalhada.
scala
scala-2.8
context-bound
Jesper
fonte
fonte
Respostas:
Você achou este artigo ? Ele cobre o novo recurso de limite de contexto, dentro do contexto de melhorias de array.
Geralmente, um parâmetro de tipo com um limite de contexto é do formulário
[T: Bound]
; ele é expandido para um parâmetro de tipo simplesT
junto com um parâmetro implícito de tipoBound[T]
.Considere o método
tabulate
que forma uma matriz a partir dos resultados da aplicação de uma dada função f em um intervalo de números de 0 até um determinado comprimento. Até Scala 2.7, tabular poderia ser escrito da seguinte forma:No Scala 2.8 isso não é mais possível, porque as informações de tempo de execução são necessárias para criar a representação correta do
Array[T]
. É necessário fornecer essas informações passando umClassManifest[T]
para o método como um parâmetro implícito:Como uma forma abreviada, um limite de contexto pode ser usado no parâmetro de tipo
T
, fornecendo:fonte
A resposta de Robert cobre os detalhes técnicos de Context Bounds. Vou lhe dar minha interpretação de seu significado.
Em Scala, um View Bound (
A <% B
) captura o conceito de 'pode ser visto como' (enquanto um limite superior<:
captura o conceito de 'é um'). Um limite de contexto (A : C
) diz 'tem um' sobre um tipo. Você pode ler os exemplos sobre manifestos como "T
tem umManifest
". O exemplo que você vinculou a cerca deOrdered
vsOrdering
ilustra a diferença. Um métododiz que o parâmetro pode ser visto como um
Ordered
. Compare comque diz que o parâmetro tem um associado
Ordering
.Em termos de uso, demorou um pouco para que as convenções fossem estabelecidas, mas os limites de contexto são preferíveis aos limites de visualização (os limites de visualização agora estão obsoletos ). Uma sugestão é que um limite de contexto seja preferido quando você precisa transferir uma definição implícita de um escopo para outro sem precisar se referir a ela diretamente (este é certamente o caso do
ClassManifest
usado para criar um array).Outra maneira de pensar sobre limites de visão e limites de contexto é que o primeiro transfere conversões implícitas do escopo do chamador. O segundo transfere objetos implícitos do escopo do chamador.
fonte
has a
Faz mais sentido para mim](Esta é uma nota entre parênteses. Leia e entenda as outras respostas primeiro.)
Os limites de contexto realmente generalizam os limites de visualização.
Portanto, dado este código expresso com um View Bound:
Isso também pode ser expresso com um limite de contexto, com a ajuda de um alias de tipo que representa funções de tipo
F
para tipoT
.Um limite de contexto deve ser usado com um construtor de tipo do tipo
* => *
. No entanto, o construtorFunction1
de tipo é do tipo(*, *) => *
. O uso do alias de tipo aplica parcialmente o segundo parâmetro de tipo com o tipoString
, produzindo um construtor de tipo do tipo correto para uso como um limite de contexto.Existe uma proposta para permitir que você expresse diretamente tipos parcialmente aplicados em Scala, sem o uso do apelido de tipo dentro de uma característica. Você poderia então escrever:
fonte
From
de tipo do tipoTo[String]
. Não fornecemos um argumento de tipo paraFrom
, portanto, estamos nos referindo ao construtor de tipo, não a um tipo. Este construtor de tipo é do tipo certo para ser usado como um limite de contexto -* -> *
. Isso limita o parâmetro de tipoT
, exigindo um parâmetro implícito de tipoTo[String]#From[T]
. Expanda os aliases de tipo e pronto, você fica comFunction1[String, T]
.Esta é outra nota entre parênteses.
Como Ben apontou , um limite de contexto representa uma restrição "tem-a" entre um parâmetro de tipo e uma classe de tipo. Dito de outra forma, ele representa uma restrição de que existe um valor implícito de uma classe de tipo particular.
Ao utilizar um limite de contexto, muitas vezes é necessário revelar esse valor implícito. Por exemplo, dada a restrição
T : Ordering
, muitas vezes será necessária a instância deOrdering[T]
que satisfaça a restrição. Conforme demonstrado aqui , é possível acessar o valor implícito usando oimplicitly
método ou um método um pouco mais útilcontext
:ou
fonte