Friday, 18 October 2013 20:11

Estructuras de control y Funciones

Hola a tod@s, continuamos con los resúmenes del Libro "SCALA for Impatient". Toca el Capitulo 2:  Estructuras de control y funciones. Los próximos capítulos serán más continuos. Saludos :D

Capitulo II - Estructuras de control y Funciones

2.1 Expresiones condicionales

Scala presenta al igual que java y C++ un condicional if/else, como podemos ver en el ejemplo:

Scala> val x = 7
res8: Int =7
Scala> if (x > 0) 1 else -1
res9: Int = 1

Las expresiones en Scala tienen un tipo, como puede observar en el anterior ejemplo es de tipo entero, en el siguiente ejemplo podemos ver que Scala presenta un tipo "Any" , ya que la expresión condicional presenta por un lado el tipo String y por otro un Int.

Scala> if (x > 0) "Número Positivo" else -1
res9: Any = Número Positivo

Una expresión condicional puede presentar o no un else o en su defecto tener paréntesis vacios.

PRECAUCION: Si va a escribir la sentencia if then else en varias líneas el compilador podría no reconocer el caso else. Ejemplo:

Scala> if(x > 0) 1
res10: AnyVal = 1
Scala> else if( x == 0 ) 0 else -1
:1: error: illegal start of definition
else if( x == 0) 0 else -1
^

La forma ideal de realizar el anterior ejemplo es:

Scala> if(x>0) 1 else if(x==0)0 else -1
res11: Int = 1

2.2 Terminación de una sentencia

Scala permite que se pueda o no escribir el punto y coma al final de una sentencia; pero en caso de querer agregar varias sentencias en una sola línea, debe separarlas mediante un punto y coma, ejemplo:

Scala> var r = 3
r: Int = 3
Scala> var n = 2
n: Int = 2
cala>
if(n > 0) { r = r * n; n-=1}
Scala> println(r)
6
Scala> println(n)
1

2.3 Expresiones en bloque y asignaciones

En Scala un bloque {} contiene una secuencia de expresiones y el resultado es además una expresión. El valor del bloque, es el valor de la última expresión.

Esta característica puede ser bien aprovechada si la inicialización de un val toma más de un paso.

Ejemplo:

Scala> val distancia = { val dx = x – x0; val dy = y-y0; sqrt(dx * dx + dy * dy)}
distancia: Double = 3.1622776601683795

En Scala las asignaciones no tienen un valor, o estrictamente hablando, tienen un valor de tipo Unit. Por tanto, no se puede realizar el siguiente tipo de asignaciones:

Scala> x = y = 1
:8: error: reassignment to val
x = y = 1
^

Porque el resultado de y = 1 es un Unit (equivalente a un void de Java) y lo que espera el valor de x es un Int.

2.4 Entrada y Salida

Scala permite obtener y mostrar información usando las siguientes sentencias:

print () - para imprimir

println - para imprimir con salto de línea

readLine – para leer

readInt - para leer enteros específicamente.

printf - para leer como el formato de C

En el siguiente ejemplo puede observar la lectura y escritura de información

Scala> val name= readLine("Your name:")
Your name:name: String = genso
Scala> val age= readInt()
age: Int = 5

2.5 Bucles

El bucle while tiene la misma estructura que se presenta en java y en C++

Scala> var r= 5
r: Int = 5
Scala> var n=3
n: Int = 3
Scala> while(n>0){r = r * n; n-=1}
Scala> println(r)
30
Scala> println(n)
0

En Scala no se tiene el ciclo for, tal como es conocido en otros lenguajes,pero puede utilizar el método de la clase RichInt, que muestra el siguiente constructor:

For(i <- expr)

Donde se aprecia que en el rango que se coloca en el for puede utilizar to ó until, es decir; to nos permite incluir al último valor del rango mientras que until excluye al último valor del rango, como se muestra en el siguiente ejemplo:

Scala> for(i <- 0 to 4) print(" &"+i)
&0 &1 &2 &3 &4
Scala> for(i <- 0 until 4) print(" *"+i)
*0 *1 *2 *3

2.6 For Loops y for Comprehensions – Avanzado

Scala permite iterar varias expresiones separadas por un punto y coma dentro del for

Ejemplo:

Scala> for(i<-1 to 3; j<-1 to 3) print((10 * i * j)+ " ")
10 20 30 20 40 60 30 60 90

 Dentro del for se puede declarar variables que se usarán dentro del bucle, por ejemplo:

Scala> for(i<-1 to 3; aux=4-i; j<-aux to 3) print((10 * i + j)+ " ")
13 22 23 31 32 33

 Recuerde, cuando el cuerpo del for comienza con yield se construyen colecciones para cada iteración, como se muestra en el ejemplo:

Scala> for(m <- "Hello"; i <- 0 to 1) yield (m + i).toChar
res22: String = HIeflmlmop

2.7 Funciones

Scala tiene funciones además de métodos, un método opera en un objeto, pero una función no. C++ también tiene funciones, pero en Java se puede imitar el comportamiento con métodos estáticos.

Para comprender bien la diferencia entre funciones y métodos en Scala puede consultar el artículo Scala Functions vs. Methods

Una función está determinada por un nombre, parámetros y cuerpo, por Ejemplo:

Scala> def fac(n : Int) = {
var r= 1
for(i <- 1 to n)
 fac: (n: Int)Int
r = r * i
r
}
 Scala> def abs(x: Double) = if(x>0) x else -x
abs: (x: Double)Double

La palabra reservada "return" no es necesaria para devolver el valor de la función. Es posible utilizar return como en Java o C++ para salir de una función inmediatamente, pero no es comúnmente realizado en Scala.

Para funciones recursivas es necesario definir el tipo de retorno de la función.

2.8 Argumentos con nombre y argumentos por defecto

En Scala puede definir los argumentos con nombre y además agregarle un valor por defecto como se muestra en el siguiente ejemplo:

Scala> def argumentos(cadena: String, left:String="[", right:String="]")= left+cadena+right
argumentos: (cadena: String, left: String, right: String)String

2.9 Argumentos variables

En Scala puede enviar como parámetro de la función una cantidad de argumentos o parámetros no definidos, que sean del mismo tipo, como se muestra en el ejemplo.

 Scala> def suma(args: Int*)={var res=0;for(arg<-args) res+= arg; res} suma: (args: Int*)Int Scala> val s= suma(1,3,5,7,8) s: Int = 24

 Ojo, en el ejemplo anterior, no es posible enviar una secuencia de números directamente por medio de una función:

Scala> val su= suma(1 to 10) // Error

 Pero se puede solucionar indicándole al compilador que se desea que parámetro sea considerado como una secuencia de argumentos, agregando : _* para convertir a un argumento de secuencias, como se muestra en el ejemplo:

Scala> val su= suma(1 to 10:_*)
su: Int = 55

 Esta técnica también puede ser utilizada en definiciones recursivas.

2.10 Procedimientos

Scala tiene una notación especial para funciones que no retornan un valor. Si el cuerpo de la función está entre llaves sin que se anteceda el símbolo = entonces el tipo que se retorna es Unit. Tal función se llama Procedimiento. Un procedimiento no retorna un valor y solo es llamado para su efecto secundario.

Ejemplo:

def box(s : String){
val border = "-" + s.length + "--\n"
println(border + "|" + s + "|\n" + border)
}

  2.11 Valores Lazy/Perezosos

Cuando un val es declarado como lazy , su inicialización no sucede hasta que es accedido la primera vez.

Lazy val words = Scala.oi.Source.fromFile("/usr/share/dict/words").mkString

Si el programa nunca accede a words , el archivo nunca es abierto. Los valores lazy son utilizados para retardar el costo de inicialización.

Se puede pensar en los valores lazy, como un intermedio entre un val y un def. Comparando se tiene:

val words = Scala.oi.Source.fromFile("/usr/share/dict/words").mkString
// evaluado cuando word es definido
Lazy val words = Scala.oi.Source.fromFile("/usr/share/dict/words").mkString
// evaluado la primera vez que word es usado
def words = Scala.oi.Source.fromFile("/usr/share/dict/words").mkString
// Evaluado cada vez que word es usado

2.12 Excepciones

Una exception en Scala es trabaja de la misma forma que en Java o C++, cuando se lanza una excepción, el proceso actual es abortado y el sistema de ejecución va por un manejador de excepción que puede aceptar un tipo IllegalArgumentException.

Como en Java los objetos que se lanzan necesitan pertenecer a una subclase de java.lang.Throwable , sin embargo a diferencia de Java Scala no realiza un "chekeo" de excepciones, es decir, nunca tiene que declarar como una función o un método que podría lanzar una excepción.

Una expresión throw tiene el tipo especial Nothing el cual es usado dentro de una expresión if/else. Si una de las ramas tiene el tipo Nothing el tipo de la expresión if/else toma el tipo de la otra rama, por ejemplo:

if (x >= 0) {
sqrt(x)
} else throw new IllegalArgumentExpression("x no debe ser negativo")

La primera rama tiene tipo Double, la segunda tiene tipo Nothing. Por lo tanto la expresión if/else tiene tipo Double

La sintaxis para la captura de excepciones esta modelada en base a la sintaxis de pattern matching:

try {
process(new URL("http://horstmann.com/fred-tiny.gif"))
} catch {
case _ : MalformedURLException => println("Bar URL " + url)
case ex: IOException => ex.printStackTrace()
}

Al igual que Java o C++ los tipos generales de las excepciones deben ir después de los específicos. Nótese que se puede usar el símbolo _ para un nombre de variable que no se necesita.

La declaración try/finally permite disponer de un recurso o no, respecto a una excepción que ha ocurrido, por ejemplo:

var in =new URL("http://horstmann.com/fred-tiny.gif").openStream()
try {
process(in)
} finallly {
in.close()
}

La cláusula finally es ejecutada ocurra o no una excepción en la función process

Notar que las cláusulas try/catch y try/finally tienen objetivos complementarios. La declaración try/catch maneja excepciones y la declaración try/finally toma una acción, generalmente una "limpieza", cuando una excepción no es manejada, es posible combinar ambas declaraciones.

try { ... } catch { ...} finallly { ...}
que es lo mismo que
try { try{...} catch { ...} } finallly { ...}

Sin embargo, esta última combinación es raramente usada.

 Artículo elaborado de manera conjunta por: Nataly Nanda Huanca Patzi y Apolinar Linares Flores

Published in Blog

Hola a tod@s, con este artículo empezamos una serie de publicaciones de artículos que presentarán resúmenes del Libro "SCALA for Impatient", como resultado del ciclo de capacitaciones internas realizadas en Genso iniciativas web (poner enlace principal de la pagina web) para la mejora continua de los integrantes, espero que sea de ayuda cada una de las publicaciones que realizaremos, en caso de tener alguna dificultad no duden en consultar.

¿Qué es Scala?
Scala es un moderno lenguaje de programación multi-paradigma diseñado para expresar patrones de programación comunes de una forma concisa, elegante, y de tipado seguro. Integra fácilmente características de lenguajes orientados a objetos y funcionales.

1 Capítulo I.- Información Básica

1.1 Interprete de Scala

Para probar y practicar con algunos ejemplos es necesario instalar SCALA en su ordenador, luego asegurarse de que scala/bin este agregado en el PATH, una vez realizado lo anterior usted debe abrir una pantalla de símbolo del sistema o de comando y sólo escribir la palabra scala, luego pulsar enter, de esta forma ingresa al intérprete de SCALA como se puede ver en la figura Nro. 1

ÿ Inicio/Accesorios/símbolo_del_sistema/

Fig. 1

En la figura 1 puede observar que al ingresar una línea de código el interprete inmediatamente le muestra el tipo de dato y el resultado asignado a una variable por defecto, en el primer ejercicio la variable es res0.

Ejemplos:

scala> 8 * 5 + 9 
scala>  res0 * 0.5
scala> “Hola,  “ + res1
res0: Int = 49
res1:  Double = 24.5
res2: String = Hola, 24.5

Dentro del intérprete puede llamar a algunos métodos tan solo pulsando la tecla TAB, en caso de haber varios el interprete le muestra que métodos puede utilizar, por ejemplo en la variable res2 llamamos al método que convierte a mayúsculas el texto:

scala> res2.toUpperCase
res3: String = HOLA, 24.5

1.1 Declarar Variables

En el intérprete de Scala usted puede declarar sus propias variables por ejemplo:

scala> val respuesta = 10 * 5 + 4
respuesta: Int = 54

Debe tener en cuenta que al declarar una variable con val el resultado que le asigne es constante, es decir; que no puede asignarle un nuevo valor, si lo intenta le saldrá un mensaje de error, ejemplo:

scala> respuesta = 10
< console > :8: error: reassignment to val

Si desea tener una variable que no sea constante, entonces debe declararla como var, por ejemplo:

scala> var prueba = 10 * 7 + 3
prueba: Int = 73
scala> prueba = 4
prueba: Int = 4

Ojo. Si bien puede cambiar el valor de la variable, debe tener cuidado en reasignar por otro valor del mismo tipo.

Al declarar una variable en scala no es necesario que indique que tipo de dato desea agregar, el intérprete induce qué tipo de dato esta agregando. Lo mejor es que usted declare el tipo de dato que intenta asignar, ejemplo:

scala> val saludo: String = "Hola"

Usted puede declarar varias variables a la vez, sólo debe separar las variables usando una coma "," como puede ver en el ejemplo:

scala> val num1, num2, num3 = 10
num1: Int = 10
num2: Int = 10
num3: Int = 10

1.2 Tipos comúnmente usados

Scala tiene tipos de datos que utiliza de forma común como ser: Byte, Chart, Short, Int, Long, Float, Double and Boolean.

El intérprete de scala puede realizar conversiones entre variables primitivas y wrapper sin dificultad. Además se puede modificar un String con con los métodos que tiene la clase StringOps.

Recuerde que scala utiliza métodos no casts para realizar conversiones de números.

1.3 Operadores aritméticos y sobrecarga

Scala utiliza operadores usuales como + - * / % y los operadores de comparación & | ^ >> <<, donde estos operadores son realmente métodos, por ejemplo:

a.method(b) donde su forma abreviada es a method b

El nombre del method puede ser + por ejemplo.

scala> 1.+(10)
res5: Double = 11.0

SCALA permite la sobrecarga de operadores:

contador+=1 que es lo mismo que en java contador++

1.4 Llamadas a funciones y métodos

Para realizar alguna operación se puede importar funciones matemáticas propias de SCALA, por ejemplo:

scala> Import scala.math._

Usted puede usar ._ de la misma forma que utiliza * en java

Para usar los métodos estáticos, pow,sqrt, min,Pi. Semejantes a Java.

Scala no tiene métodos estáticos, pero cada clase tiene un companion object donde sus métodos trabajan de forma similar a un método estático en java, ejemplo:

scala> BigInt.probablePrime(100, scala.util.Random)
res6: scala.math.BigInt = 1036819622350713618865780051451

Los métodos que no presentan parámetros no es necesario utilizar paréntesis.

scala> "Hello".distinct
res7: String = Helo

1.5 El metodo Apply

Este método es parecido al charAt(i) de java y s[i] de C++. Es un método que convierte tipos de datos, donde enseña a la clase como convertirse a un cierto tipo de dato requerido.

Todas las clases tienen su Apply.

Ejemplo:

scala> "Hello"(4)
res8: Char = o
scala> "Hello".apply(4)
res9: Char = o
scala> BigInt("1234567890")
res10: scala.math.BigInt = 1234567890
scala> BigInt.apply("1234567890")
res11: scala.math.BigInt = 1234567890

1.6 Scaladoc

Revisar www.scala-lang.org /api

Fuente: SCALA for the Impatient by Cay S. Horstmann

Artículo elaborado de manera conjunta por: Nataly Nanda Huanca Patzi y Apolinar Linares Flores

Published in Blog
FaLang translation system by Faboba