martes, 19 de diciembre de 2017

Un resumen de Scala for the Impatient, parte 34

Si hemos programado en C++ recordaremos que nos permite sobrescribir operadores, pero esto requería una muy pesada definición. Esto es muy diferente en Scala, las definiciones son mucho más fáciles y claras.

Sobrescribir operadores nos da una sintaxis más clara de nuestro código y nos acerca a la notación matemática.

En esta parte veremos como definir operadores binarios y unarios. Pero antes debemos aclarar algunos conceptos.

Identificadores

El nombre de las variables, funciones, clases, etc. se denominan identificadores. En Scala tenes más opciones de nombres para los identificadores que en java. Por supuesto podemos hacerlo igual que java, una letra seguida de letra o dígito. Como Java también permite caracteres unicode, es decir :


 es una variable valida.

También se puede utilizar caracteres de operadores en identificadores como :

  • Caracteres ASCII como ! # % & * + - / : < = > ? @ \ ^ | ~ , dígitos, . , ; marcas de puntuación, guión bajo, paréntesis () [] {} o comillas “ ' `     
  • Caracteres de símbolos matemáticos


Por ejemplo





es un identificador valido y se puede hacer:



de esta manera podemos escribir



de forma valida.

Note que las palabras :  @ # : = _ => <- <: <% >: fi  ̈ son palabras reservadas.

Por lo dicho anteriormente este es una variable valida:

val happy_birthday_!!! = "Bonne anniversaire!!!"

Por ultimo se puede incluir cualquier conjunto de palabras en `` como por ejemplo:

val `val` = 42

Si bien no parece útil, lo es por ejemplo si deseamos llamar a un método java que sea palabra reservada en scala, de esta forma podremos hacerlo.

Operador infijo

Se puede escribir:

a identificador b

Donde identificador es un método con 2 parámetros. Uno implícito y el otro explicito. Por ejemplo:

1 to 10

Que es igual a llamar 1.to(10)

Esto se denomina una expresión infija porque se encuentra entre los 2 parámetros. El operador puede contener letras o no, como el caso de -> :

1 -> 10 es igual a 1.->(10)

Para definir un operador en una clase, solo debe definir un método con el nombre del operador. Por ejemplo la clase Fraction:

class Fraction(n: Int, d: Int) {
    private val num = ...
    private val den = ...
    ...
    def *(other: Fraction) = new Fraction(num * other.num, den * other.den)
}

Operadores unarios

Los operadores infijos son binarios, es decir necesitan 2 parámetros. Un operador con un parámetro se lo denomina unario.

Los cuatro operadores: -, +, !, ~ se pueden utilizar como operadores prefijos, es decir se puede escribir el operador y luego el parámetro como por ejemplo :

 -a es idual a llamar a : a.unary_-

Si es postfijo, en ese caso no hay problema, se puede llamar el método con . o espacio, por ejemplo :

12 toString

es igual a llamar a : 12.toString()

Cuando utilizamos el operador unario postfijo con espacio y sin paréntesis nos puede dar un error de compilación. Dado que no queda expresado que no estamos utilizando parámetros. Veamos un ejemplo:

val result = 42 toString
println(result)

En este caso el compilador interpreta que se esta escribiendo lo siguiente :

val result = 42.toString(println(result))

Por esta razón nos lanzara un error de compilación, que dirá que el método tiene muchos parámetros. Por esta razón el compilador, lanza un warning cuando utilizamos esta notación, esto se puede desactivar con el parámetro del compilador -language:postfixOps o agregando el import :

import scala.language.postfixOps