Quais são as regras precisas para quando você pode omitir (omitir) parênteses, pontos, colchetes, = (funções), etc.?
Por exemplo,
(service.findAllPresentations.get.first.votes.size) must be equalTo(2).
service
é meu objetodef findAllPresentations: Option[List[Presentation]]
votes
retornaList[Vote]
- deve e ser são funções de especificações
Por que não posso ir:
(service findAllPresentations get first votes size) must be equalTo(2)
?
O erro do compilador é:
"RestServicesSpecTest.this.service.findAllPresentations do tipo Option [List [com.sharca.Presentation]] não leva parâmetros"
Por que ele acha que estou tentando passar um parâmetro? Por que devo usar pontos para cada chamada de método?
Por que deve (service.findAllPresentations get first votes size)
ser igual a (2) resultar em:
"não encontrado: valor primeiro"
Ainda assim, "deve ser igual a 2" de
(service.findAllPresentations.get.first.votes.size)
deve ser igual a 2, ou seja, o encadeamento de métodos funciona bem? - parâmetro de cadeia de cadeia de objeto.
Eu olhei o livro e o site do Scala e realmente não consigo encontrar uma explicação abrangente.
É mesmo, como Rob H explica na questão Stack Overflow Quais personagens posso omitir em Scala? , que é o único caso de uso válido para omitir o '.' é para operações de estilo "operando operador operando" e não para encadeamento de método?
Definições de classe:
val
ouvar
pode ser omitido dos parâmetros de classe, o que tornará o parâmetro privado.Adicionar var ou val fará com que seja público (isto é, acessadores e modificadores de método são gerados).
{}
pode ser omitido se a classe não tiver corpo, ou seja,Instanciação de classe:
Os parâmetros genéricos podem ser omitidos se puderem ser inferidos pelo compilador. No entanto, observe que se seus tipos não corresponderem, o parâmetro de tipo sempre será inferido para que corresponda. Portanto, sem especificar o tipo, você pode não obter o que espera - isto é, dado
Isso lhe dará um erro de tipo (Int encontrado, String esperada)
Considerando que isso funciona bem:
Porque o parâmetro de tipo, T, é inferido como o supertipo menos comum dos dois - Qualquer.
Definições de função:
=
pode ser descartado se a função retornar Unit (nada).{}
pois o corpo da função pode ser eliminado se a função for uma única instrução, mas apenas se a instrução retornar um valor (você precisa do=
sinal), ou seja,mas isso não funciona:
O tipo de retorno da função pode ser omitido se puder ser inferido (um método recursivo deve ter seu tipo de retorno especificado).
()
pode ser descartado se a função não receber nenhum argumento, ou seja,que por convenção é reservado para métodos que não têm efeitos colaterais - mais sobre isso mais tarde.
()
não é descartado per se ao definir um parâmetro de passagem por nome , mas é na verdade uma notação semanticamente diferente, isto é,Diz que myOp usa um parâmetro de passagem por nome, que resulta em uma String (ou seja, pode ser um bloco de código que retorna uma string) em vez de parâmetros de função,
que diz que
myOp
pega uma função que tem zero parâmetros e retorna uma String.(Lembre-se, os parâmetros passados por nome são compilados em funções; isso apenas torna a sintaxe mais agradável.)
()
pode ser descartado na definição do parâmetro da função se a função tiver apenas um argumento, por exemplo:Mas se for necessário mais de um argumento, você deve incluir o ():
Afirmações:
.
pode ser descartado para usar a notação de operador, que só pode ser usada para operadores infixos (operadores de métodos que recebem argumentos). Veja a resposta de Daniel para mais informações..
também pode ser descartado para o final da lista de funções postfix()
pode ser descartado para operadores postfix list.tail()
não pode ser usado com métodos definidos como:Porque essa notação é reservada por convenção para métodos que não têm efeitos colaterais, como List # tail (ou seja, a invocação de uma função sem efeitos colaterais significa que a função não tem efeito observável, exceto por seu valor de retorno).
()
pode ser descartado para notação de operador ao passar um único argumento()
pode ser necessário usar operadores postfix que não estão no final de uma instrução()
pode ser necessário para designar instruções aninhadas, fins de funções anônimas ou para operadores que usam mais de um parâmetroAo chamar uma função que assume uma função, você não pode omitir o () da definição de função interna, por exemplo:
Ao chamar uma função que usa um parâmetro por nome, você não pode especificar o argumento como uma função anônima sem parâmetro. Por exemplo, dado:
Você deve chamá-lo como:
ou
mas não:
IMO, o uso excessivo de tipos de retorno de descarte pode ser prejudicial para o código a ser reutilizado. Basta olhar a especificação para um bom exemplo de legibilidade reduzida devido à falta de informações explícitas no código. O número de níveis de indireção para realmente descobrir qual é o tipo de uma variável pode ser louco. Esperançosamente, ferramentas melhores podem evitar esse problema e manter nosso código conciso.
(OK, na busca para compilar uma resposta mais completa e concisa (se eu perdi alguma coisa ou entendi algo errado / impreciso, por favor, comente), adicionei no início da resposta. Observe que esta não é uma linguagem especificação, portanto, não estou tentando torná-la exatamente academicamente correta - apenas mais como um cartão de referência.)
fonte
Uma coleção de citações que fornecem informações sobre as várias condições ...
Pessoalmente, pensei que haveria mais na especificação. Tenho certeza que deve haver, só não estou procurando as palavras certas ...
Existem algumas fontes, entretanto, e eu as reuni, mas nada realmente completo / abrangente / compreensível / que explique os problemas acima para mim ...:
Do capítulo 2, "Digite menos, faça mais", do Scala de programação :
Do capítulo 1, "Zero a sessenta: Apresentando Scala", de Programação Scala :
Da postagem do blog Scala Syntax Primer :
Da especificação do idioma:
Do Scala for Java Refugees Part 6: Getting Over Java :
Quais personagens posso omitir em Scala?
Mas o que também me confunde é esta citação:
Porque tanto quanto eu posso ver, não é um objeto para receber a chamada ...
fonte
Acho mais fácil seguir esta regra: nas expressões, os espaços se alternam entre métodos e parâmetros. Em seu exemplo,
(service.findAllPresentations.get.first.votes.size) must be equalTo(2)
analisa como(service.findAllPresentations.get.first.votes.size).must(be)(equalTo(2))
. Observe que os parênteses em torno do 2 têm uma associatividade maior do que os espaços. Os pontos também têm maior associatividade, portanto(service.findAllPresentations.get.first.votes.size) must be.equalTo(2)
, analisaria como(service.findAllPresentations.get.first.votes.size).must(be.equalTo(2))
.service findAllPresentations get first votes size must be equalTo 2
analisa comoservice.findAllPresentations(get).first(votes).size(must).be(equalTo).2
.fonte
Na verdade, em uma segunda leitura, talvez esta seja a chave:
Conforme mencionado na postagem do blog: http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6 .
Então, talvez este seja realmente um "açúcar de sintaxe" muito estrito que só funciona quando você está efetivamente chamando um método, em um objeto, que leva um parâmetro . por exemplo
E nada mais.
Isso explicaria meus exemplos na pergunta.
Mas, como eu disse, se alguém pudesse apontar exatamente onde na especificação do idioma isso está especificado, ficaria muito grato.
Ok, um bom sujeito (paulp_ de #scala) apontou onde na especificação do idioma esta informação é:
Hmm - para mim não combina com o que estou vendo ou simplesmente não entendo;)
fonte
Não existe nenhum. Você provavelmente receberá conselhos sobre se a função tem ou não efeitos colaterais. Isso é falso. A correção é não usar efeitos colaterais na extensão razoável permitida pelo Scala. Na medida em que não pode, todas as apostas estão canceladas. Todas as apostas. O uso de parênteses é um elemento do conjunto "tudo" e é supérfluo. Não fornece nenhum valor uma vez que todas as apostas estejam encerradas.
Este conselho é essencialmente uma tentativa de um sistema de efeitos que falha (não deve ser confundido com: é menos útil do que outros sistemas de efeitos).
Tente não ter efeito colateral. Depois disso, aceite que todas as apostas estão canceladas. Esconder-se atrás de uma notação sintática de fato para um sistema de efeitos só pode causar danos.
fonte