A sintaxe do Scala possui muitos símbolos. Como é difícil encontrar esses tipos de nomes usando os mecanismos de pesquisa, uma lista abrangente deles seria útil.
Quais são todos os símbolos em Scala e o que cada um deles faz?
Em particular, eu gostaria de saber sobre ->
, ||=
, ++=
, <=
, _._
, ::
, e :+=
.
Respostas:
Divido os operadores, para fins de ensino, em quatro categorias :
É uma sorte, então, que a maioria das categorias esteja representada na pergunta:
O significado exato da maioria desses métodos depende da classe que os está definindo. Por exemplo,
<=
onInt
significa "menor ou igual a" . O primeiro,->
vou dar como exemplo abaixo.::
é provavelmente o método definido emList
(embora possa ser o objeto com o mesmo nome) e:+=
provavelmente é o método definido em váriasBuffer
classes.Então, vamos vê-los.
Palavras-chave / símbolos reservados
Existem alguns símbolos em Scala que são especiais. Dois deles são considerados palavras-chave adequadas, enquanto outros são apenas "reservados". Eles são:
Tudo isso faz parte do idioma e, como tal, pode ser encontrado em qualquer texto que descreva adequadamente o idioma, como o próprio Scala Specification (PDF).
O último, o sublinhado, merece uma descrição especial, porque é amplamente utilizada e tem muitos significados diferentes. Aqui está uma amostra:
Eu provavelmente esqueci outro significado, no entanto.
Métodos importados automaticamente
Portanto, se você não encontrou o símbolo que está procurando na lista acima, ele deve ser um método ou parte dele. Mas, com frequência, você verá algum símbolo e a documentação da classe não terá esse método. Quando isso acontece, você está visualizando uma composição de um ou mais métodos com outra coisa ou o método foi importado para o escopo ou está disponível por meio de uma conversão implícita importada.
Eles ainda podem ser encontrados no ScalaDoc : você apenas precisa saber onde procurá-los. Ou, na sua falta, veja o índice (atualmente quebrado em 2.9.1, mas disponível todas as noites).
Todo código Scala tem três importações automáticas:
Os dois primeiros disponibilizam apenas classes e objetos singleton. O terceiro contém todas as conversões implícitas e métodos importados, pois
Predef
é um objeto em si.Olhando para dentro,
Predef
mostre rapidamente alguns símbolos:Qualquer outro símbolo será disponibilizado através de uma conversão implícita . Basta olhar para os métodos marcados com
implicit
que recebem, como parâmetro, um objeto do tipo que está recebendo o método. Por exemplo:No caso acima,
->
é definido na classeArrowAssoc
através do métodoany2ArrowAssoc
que leva um objeto do tipoA
, em queA
é um parâmetro do tipo ilimitado para o mesmo método.Métodos comuns
Portanto, muitos símbolos são simplesmente métodos em uma classe. Por exemplo, se você fizer
Você encontrará o método
++
no ScalaDoc for List . No entanto, há uma convenção que você deve estar ciente ao procurar métodos. Os métodos que terminam em dois pontos (:
) se ligam à direita em vez da esquerda. Em outras palavras, enquanto a chamada do método acima é equivalente a:Se eu tivesse,
1 :: List(2, 3)
isso seria equivalente a:Então, você precisa olhar para o tipo encontrado à direita ao procurar métodos que terminam em dois pontos. Considere, por exemplo:
O primeiro método (
+:
) se liga à direita e é encontrado emList
. O segundo método (:+
) é apenas um método normal e se liga à esquerda - novamente, ativadoList
.Açúcares sintáticos / composição
Então, aqui estão alguns açúcares sintáticos que podem ocultar um método:
O último é interessante, porque qualquer método simbólico pode ser combinado para formar um método semelhante a uma atribuição dessa maneira.
E, claro, existem várias combinações que podem aparecer no código:
fonte
val c = ex(2)
vez deval ex(c) = 2
?val ex(c) = 2
.Uma diferença (boa, IMO) entre o Scala e outros idiomas é que ele permite que você nomeie seus métodos com quase qualquer caractere.
O que você enumera não é "pontuação", mas métodos simples e simples, e, como tal, seu comportamento varia de um objeto para outro (embora existam algumas convenções).
Por exemplo, consulte a documentação do Scaladoc para obter a lista e você verá alguns dos métodos mencionados aqui.
Algumas coisas a ter em mente:
Na maioria das vezes a
A operator+equal B
combinação traduz aA = A operator B
, como nos||=
ou++=
exemplos.Os métodos que terminam
:
são associativos, isso significa queA :: B
é realmenteB.::(A)
.Você encontrará mais respostas navegando na documentação do Scala. Manter uma referência aqui duplicaria os esforços e ficaria para trás rapidamente :)
fonte
Você pode agrupá-los primeiro de acordo com alguns critérios. Neste post, explicarei apenas o caractere de sublinhado e a seta à direita.
_._
contém um período. Um período no Scala sempre indica uma chamada de método . Então, à esquerda do período, você tem o receptor e à direita a mensagem (nome do método). Agora_
é um símbolo especial em Scala. Existem várias postagens sobre o assunto, por exemplo, esta entrada de blog, todos os casos de uso. Aqui está um atalho de função anônima , que é um atalho para uma função que pega um argumento e invoca o método_
nele. Agora_
não é um método válido, então certamente você estava vendo_._1
ou algo semelhante, ou seja, invocando o método_._1
no argumento da função._1
a_22
são os métodos de tuplos que extraem um elemento particular de um tuplo. Exemplo:Agora vamos assumir um caso de uso para o atalho do aplicativo de funções. Dado um mapa que mapeia números inteiros para strings:
Wooop, já existe outra ocorrência de uma pontuação estranha. O hífen e caracteres maiores que, que se assemelham a uma seta à direita , são um operador que produz a
Tuple2
. Portanto, não há diferença no resultado de escrever um(1, "Eins")
ou outro1 -> "Eins"
, apenas que o último é mais fácil de ler, especialmente em uma lista de tuplas como o exemplo do mapa. O->
há mágica, é, como alguns outros operadores, disponível porque você tem todos os implícitos conversões em objetoscala.Predef
no espaço. A conversão que ocorre aqui éOnde
ArrowAssoc
tem o->
método que cria oTuple2
. Assim1 -> "Eins"
é real a chamadaPredef.any2ArrowAssoc(1).->("Eins")
. Está bem. Agora, de volta à pergunta original com o caractere sublinhado:O sublinhado aqui reduz o seguinte código equivalente:
Observe que o
map
método de um mapa passa a tupla de chave e valor para o argumento da função. Como estamos interessados apenas nos valores (as strings), os extraímos com o_2
método na tupla.fonte
->
método, mas sua frase "Portanto, não há diferença no resultado da escrita de um(1, "Eins")
ou outro1 -> "Eins"
" me ajudou a compreender a sintaxe e seu uso.Como complemento às brilhantes respostas de Daniel e 0__, devo dizer que Scala entende os análogos Unicode para alguns dos símbolos; portanto, em vez de
alguém pode escrever
fonte
A respeito,
::
há outra entrada Stackoverflow que cobre o::
caso. Em resumo, é usado para construirLists
' consing ' um elemento principal e uma lista final . É uma classe que representa uma lista cons'ed e que pode ser usada como extrator, mas o mais comum é um método em uma lista. Como Pablo Fernandez aponta, como termina em dois pontos, é associativo à direita , o que significa que o receptor da chamada de método está à direita e o argumento à esquerda do operador. Dessa forma, você pode elegantemente expressar a consing como prepending um novo elemento de cabeça para uma lista existente:Isso é equivalente a
O uso como objeto extrator é o seguinte:
Parece um operador aqui, mas é realmente apenas outra maneira (mais legível) de escrever
Você pode ler mais sobre extratores neste post .
fonte
<=
é exatamente como você "leria": 'menor ou igual'. Portanto, é um operador matemático, na lista de<
(é menor que?),>
(É maior que?),==
(Igual?),!=
(Não é igual?),<=
(É menor que ou igual?) E>=
(é maior que ou igual?).Isso não deve ser confundido com o
=>
que é uma espécie de seta dupla à direita , usada para separar a lista de argumentos do corpo de uma função e para separar a condição de teste na correspondência de padrões (umcase
bloco) do corpo executado quando ocorre uma correspondência . Você pode ver um exemplo disso nas minhas duas respostas anteriores. Primeiro, a função usa:que já é abreviado quando os tipos são omitidos. A função a seguir seria
e o uso de correspondência de padrões:
fonte
Considero que um IDE moderno é fundamental para entender grandes projetos de escala. Como esses operadores também são métodos, na idéia, apenas clico ou clico-b nas definições.
Você pode clicar com o botão direito do mouse em um operador contras (: :) e terminar no scala javadoc dizendo "Adiciona um elemento no início desta lista". Em operadores definidos pelo usuário, isso se torna ainda mais crítico, pois eles podem ser definidos em implícitos difíceis de encontrar ... seu IDE sabe onde o implícito foi definido.
fonte
Apenas adicionando às outras excelentes respostas. Scala oferece dois operadores simbólicos frequentemente criticados,
/:
(foldLeft
) e:\
(foldRight
), sendo o primeiro associativo. Portanto, as três instruções a seguir são equivalentes:Como são esses três:
fonte
O Scala herda a maioria dos operadores aritméticos de Java . Isso inclui bit a bit ou
|
(caractere de pipe único), bit a bit e&
, bit a bit exclusivo ou^
, além de lógico (booleano) ou||
(dois caracteres de pipe) e lógico e&&
. Curiosamente, você pode usar os operadores de caractere únicoboolean
, para que os operadores lógicos java'ish sejam totalmente redundantes:Como apontado em outro post, as chamadas que terminam em sinal de igual
=
são resolvidas (se um método com esse nome não existir!) Por uma reatribuição:Essa 'verificação dupla' possibilita a troca fácil de um mutável por uma coleção imutável:
fonte
true | { println( "Icke" ); true }
⇒ imprime!true || { println( "Icke" ); true }
⇒ não imprime!