¿Cuáles son las reglas precisas para cuando puede omitir (omitir) paréntesis, puntos, llaves, = (funciones), etc.?
Por ejemplo,
(service.findAllPresentations.get.first.votes.size) must be equalTo(2).
service
es mi objetodef findAllPresentations: Option[List[Presentation]]
votes
devolucionesList[Vote]
- deben y ser son funciones de especificaciones
¿Por qué no puedo ir?
(service findAllPresentations get first votes size) must be equalTo(2)
?
El error del compilador es:
"RestServicesSpecTest.this.service.findAllPresentations de tipo Option [List [com.sharca.Presentation]] no toma parámetros"
¿Por qué cree que estoy intentando pasar un parámetro? ¿Por qué debo usar puntos para cada llamada a un método?
¿Por qué debe (service.findAllPresentations get first votes size)
ser igual a (2) como resultado:
"no encontrado: valor primero"
Sin embargo, el "debe ser igual a 2" de
(service.findAllPresentations.get.first.votes.size)
debe ser igual a 2, es decir, ¿el encadenamiento de métodos funciona bien? - objeto cadena cadena cadena param.
He revisado el libro y el sitio web de Scala y no puedo encontrar una explicación completa.
¿Es de hecho, como explica Rob H en la pregunta de Stack Overflow, ¿Qué caracteres puedo omitir en Scala? , ese es el único caso de uso válido para omitir el '.' es para operaciones de estilo "operando operador operando", y no para el encadenamiento de métodos?
Definiciones de clase:
val
ovar
puede omitirse de los parámetros de la clase, lo que hará que el parámetro sea privado.Agregar var o val hará que sea público (es decir, se generan descriptores de acceso y mutadores de método).
{}
se puede omitir si la clase no tiene cuerpo, es decir,Creación de instancias de clase:
Los parámetros genéricos se pueden omitir si el compilador puede inferirlos. Sin embargo, tenga en cuenta que si sus tipos no coinciden, el parámetro de tipo siempre se infiere para que coincida. Entonces, sin especificar el tipo, es posible que no obtenga lo que espera, es decir, dado
Esto le dará un error de tipo (Int encontrado, Cadena esperada)
Considerando que esto funciona bien:
Porque el parámetro de tipo, T, se infiere como el supertipo menos común de los dos: Cualquiera.
Definiciones de funciones:
=
se puede descartar si la función devuelve Unit (nada).{}
para el cuerpo de la función se puede descartar si la función es una sola declaración, pero solo si la declaración devuelve un valor (necesita el=
signo), es decir,pero esto no funciona:
El tipo de retorno de la función se puede omitir si se puede inferir (un método recursivo debe tener especificado su tipo de retorno).
()
se puede descartar si la función no acepta ningún argumento, es decir,que por convención está reservado para métodos que no tienen efectos secundarios, más sobre eso más adelante.
()
en realidad no se descarta per se al definir un parámetro de paso por nombre , pero en realidad es una notación bastante diferente semánticamente, es decir,Dice que myOp toma un parámetro de paso por nombre, lo que da como resultado una cadena (es decir, puede ser un bloque de código que devuelve una cadena) en lugar de los parámetros de función,
que dice
myOp
toma una función que tiene cero parámetros y devuelve una cadena.(Eso sí, los parámetros de paso por nombre se compilan en funciones; solo hace que la sintaxis sea más agradable).
()
se puede eliminar en la definición del parámetro de función si la función solo toma un argumento, por ejemplo:Pero si toma más de un argumento, debe incluir el ():
Declaraciones:
.
se puede eliminar para usar la notación de operador, que solo se puede usar para operadores infijos (operadores de métodos que toman argumentos). Vea la respuesta de Daniel para obtener más información..
también se puede eliminar para funciones postfijas lista cola()
se puede eliminar para la lista de operadores de postfix.()
no se puede utilizar con métodos definidos como:Porque esta notación está reservada por convención para métodos que no tienen efectos secundarios, como List # tail (es decir, la invocación de una función sin efectos secundarios significa que la función no tiene ningún efecto observable, excepto por su valor de retorno).
()
se puede eliminar para la notación del operador al pasar un solo argumento()
puede ser necesario utilizar operadores de sufijo que no están al final de una declaración()
puede ser necesario para designar declaraciones anidadas, fines de funciones anónimas o para operadores que toman más de un parámetroAl llamar a una función que toma una función, no puede omitir el () de la definición de función interna, por ejemplo:
Cuando llama a una función que toma un parámetro por nombre, no puede especificar el argumento como una función anónima sin parámetros. Por ejemplo, dado:
Debes llamarlo como:
o
pero no:
En mi opinión, el uso excesivo de tipos de retorno descartables puede ser perjudicial para la reutilización del código. Solo mire las especificaciones para ver un buen ejemplo de legibilidad reducida debido a la falta de información explícita en el código. La cantidad de niveles de direccionamiento indirecto para determinar realmente cuál es el tipo de variable puede ser una locura. Con suerte, mejores herramientas pueden evitar este problema y mantener nuestro código conciso.
(De acuerdo, en la búsqueda para compilar una respuesta más completa y concisa (si me he perdido algo, o he recibido algo incorrecto / inexacto, por favor comente), agregué al principio de la respuesta. Tenga en cuenta que esto no es un idioma especificación, por lo que no estoy tratando de hacerlo exactamente académicamente correcto, sino más bien como una tarjeta de referencia).
fuente
Una colección de citas que dan una idea de las diversas condiciones ...
Personalmente, pensé que habría más en la especificación. Estoy seguro de que debe haberlos, simplemente no estoy buscando las palabras adecuadas ...
Sin embargo, hay un par de fuentes, y las he recopilado juntas, pero nada realmente completo / comprensible / comprensible / que me explique los problemas anteriores ...:
Del capítulo 2, "Escriba menos, haga más", de Programming Scala :
Del capítulo 1, "Zero to Sixty: Introducing Scala", de Programming Scala :
De la publicación del blog Scala Syntax Primer :
De la especificación del idioma:
De Scala for Java Refugees Parte 6: Superar Java :
¿Qué caracteres puedo omitir en Scala?
Pero lo que también me confunde es esta cita:
Porque por lo que puedo ver, no es un objeto para recibir la llamada ...
fuente
Me resulta más fácil seguir esta regla general: en las expresiones, los espacios alternan entre métodos y parámetros. En su ejemplo,
(service.findAllPresentations.get.first.votes.size) must be equalTo(2)
analiza como(service.findAllPresentations.get.first.votes.size).must(be)(equalTo(2))
. Tenga en cuenta que los paréntesis alrededor del 2 tienen una mayor asociatividad que los espacios. Los puntos también tienen una mayor asociatividad, por(service.findAllPresentations.get.first.votes.size) must be.equalTo(2)
lo que se analizarían como(service.findAllPresentations.get.first.votes.size).must(be.equalTo(2))
.service findAllPresentations get first votes size must be equalTo 2
analiza comoservice.findAllPresentations(get).first(votes).size(must).be(equalTo).2
.fuente
En realidad, en una segunda lectura, tal vez esta sea la clave:
Como se menciona en la publicación del blog: http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6 .
Entonces, tal vez esto sea en realidad un "azúcar sintáctico" muy estricto que solo funciona cuando se llama efectivamente a un método, en un objeto, que toma un parámetro . p.ej
Y nada más.
Esto explicaría mis ejemplos en la pregunta.
Pero como dije, si alguien pudiera señalar dónde se encuentra exactamente en la especificación del idioma, lo agradecería mucho.
Ok, un buen tipo (paulp_ de #scala) ha señalado en qué parte de la especificación de idioma se encuentra esta información:
Hmm, para mí no encaja con lo que estoy viendo o simplemente no lo entiendo;)
fuente
No hay ninguno. Es probable que reciba consejos sobre si la función tiene o no efectos secundarios. Esto es falso. La corrección consiste en no utilizar efectos secundarios en la medida razonable permitida por Scala. En la medida en que no pueda, entonces todas las apuestas están canceladas. Todas las apuestas. El uso de paréntesis es un elemento del conjunto "todos" y es superfluo. No proporciona ningún valor una vez que se cancelan todas las apuestas.
Este consejo es esencialmente un intento de un sistema de efectos que falla (no debe confundirse con: es menos útil que otros sistemas de efectos).
Trate de no tener efectos secundarios. Después de eso, acepta que todas las apuestas están canceladas. Esconderse detrás de una notación sintáctica de facto para un sistema de efectos solo puede causar daño.
fuente