VISITAS:

miércoles, 3 de agosto de 2016

Redis sorted sets

Qué son los sorted sets

Una de las estructuras de datos más potentes que tiene redis son los sorted sets (en castellano, conjuntos ordenados).
Los sorted sets son similares a los sets, o sea, son una colección de elementos (strings) únicos (no repetidos). La diferencia es que cada miembro de una lista ordenada tiene un score (puntuación), un valor en punto flotante que se utiliza para mantener ordenados los elementos, desde el más pequeño al más grande.
En resumen, un sorted set es un conjunto de elementos con un valor, que se mantiene ordenado por el valor.
Los elementos de un sorted set son únicos, pero los valores se pueden repetir.

Las operaciones de añadir, actualizar y borrar elemento+valor en un sorted set tienen un orden de computación de log(N), donde N es el número de elementos que tiene el set. O sea, es computacionalmente muy eficiente.

Ejemplos de uso

Ejemplos que se pueden modelar con sorted sets:

  • lista de records:
    • ZADD para añadir un nuevo record
    • ZRANGE para obtener las mejores puntuaciones
    • ZSCORE para saber los puntos de un usuario
    • ZRANK para saber el ranking de un usuario
  • indexar otros datos de redis, por ej, datos de usuarios
    • En un sorted set se puede almacenar element=userid y score=edad
    • ZRANGEBYSCORE para sacar los usuarios en un rango de edades

Ordenación

Los elementos en un sorted set se mantienen (siempre) ordenados, no se ordenan cuando se realiza una petición.
La ordenación sigue las siguientes reglas, suponiendo dos elementos A y B:
  • Si A.score != B.score, entonces se ordenan por score
  • Si A.score == B.score, entonces se ordenan lexicográficamente, es decir, por el elemento (A, B)

Comandos

A continuación se explican los comandos usados más frecuentemente para sorted sets. Aunque hay algunos más que se pueden consultar en: comandos redis para sorted sets

ZADD set-name score element

Añade un elemento con score a un sorted-set

ZRANGE set-name start stop [withscores]

Devuelve los elementos en las posiciones entre start y stop (inclusive). Los elementos van ordenados de menos a mayor (si se desea el orden inverso, utilizar ZREVRANGE). El primer elemento de la lista es el 0. Opcionalmente, WITHSCORES, puede devolver también el score asocado a cada elemento retornado.

ZRANGEBYSCORE set-name min max [WITHSCORES] [LIMIT offset count]

Devuelve los elementos con un score comprendido entre min y max (inclusive) ordenados de menos a mayor score (si se desea el orden inverso, utilizar ZREVRANGEBYSCORE). Se pueden utilizar los valores -inf y inf para min y max. Opcionalmente, WITHSCORES, puede devolver también el score asocado a cada elemento retornado. Opcionalmente también, se puede limitar el número de valores retornados con LIMIT (offset sería 0 y count el número máximo de elementos a retornar).

ZREM set-name element

Elimina un elemento del sorted set.

ZSCORE set-name element

Devuelve el score de un elemento.

ZCARD set-name

Devuelve el número de elementos en un sorted set.

ZCOUNT set-name min max

Devuelve el número de elementos con scores entre min y max.


miércoles, 30 de marzo de 2016

Funcionamiento de Redis Sentinel

Características de sentinel

Sentinel da alta disponibilidad a redis, permitiendo a redis recuperarse de algunos fallos sin intervención humana.
Estas son las características de sentinel:

  • Monitorización: sentinel está continuamente monitorizando si los redis master y slave están arriba y funcionando.
  • Notificación: sentinel puede avisar a los administradores del sistema o a otros programas, de caídas de instancias redis.
  • Failover automático: si la instancia master de redis no está funcionando adecuadamente, sentinel puede iniciar un proceso de failover donde un slave es promocionado a master y los demás slaves se reconfiguran para utilizar el nuevo master
  • Proveedor de configuración: sentinel actúa como descubridor de la instancia master de redis. Los clientes se conectan a sentinel, y éste les indica a qué instancia de redis se tienen que conectar. Cuando se realiza un failover, sentinel informa a sus clientes del nuevo master.

Sentinel es un sistema distribuido

Sentinel funciona de forma distribuida, es decir, varias instancias de sentinel se comunican entre sí cooperando. Las ventajas de tener varios sentinel ejecutando conjuntamente son:
  • la detección de fallos se realiza cuando varias instancias sentinel acuerdan que la instancia master ya no está disponible. Esto disminuye la probabilidad de falsos positivos.
  • sentinel puede funcionar incluso aunque no todas las instancias de sentinel estén disponibles, haciendo al sistema más robusto.

Ejecutar sentinel

Sentinel se ejecuta de la siguiente forma:

    redis-sentinel sentinel-config-file

Es obligatorio especificar un fichero de configuración para ejecutar sentinel, ya que este fichero puede ser reescrito por sentinel para guardar el estado actual, y se utilizará después de una caída. Además, el proceso sentinel tiene que tener permisos de escritura en este fichero.
Las distintas instancias de sentinel se comunican entre sí por el puerto configurado en sentinel.

Criterios de despliegue de sentinel

  1. Se recomienda desplgar al menos 3 instancias de sentinel
  2. Las 3 instancias de sentinel deben ejecutar en máquinas independientes desde el punto de vista de fallos
  3. No se garantiza que todas las escrituras permanezcan después de la caída de un master, ya que redis utiliza un sistema asíncrono de replicación
  4. No todas las librerías cliente soportan sentinel (jedis sí lo soporta)

Configuración de sentinel

La configuración mínima de una instancia sentinel sería como la siguiente:
sentinel monitor  127.0.0.1 6379 2
sentinel down-after-milliseconds  60000
sentinel failover-timeout  180000
sentinel parallel-syncs  1 1
Se especifica el nombre de un grupo de instancias redis. Este nombre es el que se utilizará para el grupo. Se especifica también la IP de la instancias redis master. No es necesario especificar las instancias slaves de redis, ya que sentinel es capaz de descubrirlas (preguntando al master). Cuando sentinel autodetecta esclavos, los escribe en su fichero de configuración:

    sentinel known-slave my_redis_group 168.190.1.45 6379

También se reescribe el fichero de configuración cuando después de un failover, cambia el master y cada vez que se descubre un nuevo sentinel:

    sentinel known-sentinel my_redis_group 168.190.1.47 26379 xxxxxxx

Detección de master caído

El último argumento de sentinel monitor, un 2 en este ejemplo, se denomina quorum, y su significado es el siguiente:

  • quorum es el número mínimo de instancias sentinel que es necesario que acuerden que un master no está disponible.
  • quorum sólo se utiliza para detectar un fallo del master, no para iniciar un failover. Para realmente iniciar un failover, una de las instancias sentinel es elegida como líder, pero debe ser autorizada para iniciar el failover. Esto sólo ocurre con el voto de la mayoría de las instancias sentinel.
Se puede entender con un ejemplo. Tenemos 5 instancias de sentinel vigilando un master reds y el quorum es 2. Si dos instancias de sentinel detectan que el master se ha caído, entonces uno de los dos es elegido para intentar iniciar el proceso de failover. Pero es necesario que al menos 3 instancias estén de acuerdo en iniciar el failover para realmente llevarlo a cabo.
Ya que es necesario que la mayoría de los sentinel decidan iniciar un failover, se RECOMIENDA/OBLIGA que haya al menos 3 instancias de sentinel en 3 máquinas distintas.

Otras opciones de sentinel

Las otras opciones de sentinel tienen el siguiente formato:

    sentinel

  • down-after-milliseconds es el tiempo que una instancia de redis no es alcanzable (no responde a pings o responde con error) para que sentinel piense que está caída
  • parallel-syncs determina el número de slaves que pueden ser reconfigurados en paralelo para usar el nuevo master después de un failover

Pérdidas de datos en failover

Ya que redis replica asíncronamente (no espera la confirmación), siempre hay un riesgo de perder algún dato cuando se cae el master, ya que éste puede caerse justo después de una escritura y justo antes de replicar esa escritura en los slaves.
Otro caso que puede ocurrir es que el master no se caiga, pero se interrumpa su conexión de red con los slaves. Entonces, podría ocurrir que los sentinel pensaran que se ha caído el master (ya que no responde, aunque realmente no se ha caído) y promocionaran a otra instancia de redis como master. El problema es que si había clientes conectados al master anterior y que no han perdido la conexión con él, pueden seguir escribiendo datos en el antiguo master. Mientras tanto, el master nuevo también puede recibir nuevos datos. Los datos escritos en el master antiguo se perderán cuando la conexión se arregle, ya que éste va a convertirse en slave y va a sincronizarse con el nuevo master.
Este problema puede reducirse bastante utilizando la siguiente configuración:

    min-slaves-to-write 1
    min-slaves-max-lag 10

Con esta configuración, una instancia redis actuando como master, dejará de aceptar escrituras si no puede escribir en al menos un slave en un máximo de 10 segundos. De esta forma, el antiguo master dejará de funcionar en 10 segundos. La desventaja es que si se pierde la conexión con los slaves, la instancia master dejará de funcionar.












lunes, 24 de agosto de 2015

SWIFT (V) : Control de flujo

Sea cual sea el lenguaje de programación en el que estemos trabajando, el desarrollo de aplicaciones es siempre un ejercicio de lógica: tomar decisiones en función de ciertas condiciones y ejecutar múltiples veces cierta lógica sobre unos datos. Todo esto se suele denominar control de flujo, y swift tiene su propia sintaxis, no muy diferente por cierto a la de otros lenguajes.

Sentencia for

Swift ofrece dos tipos de for: condition-increment y for-in

Condition-increment for

La sintaxis es similar (aunque no idéntica) a otros lenguajes C-like:

    for var i = 0; i < 15; i++ {
        println(i)
    }

For-in for

Esta estructura de control permite iterar por los datos de una colección (las colecciones se explican más adelante) o por un rango numérico.
La sintaxis es la siguiente:

    for nombre in colección_o_rango {
        ....
    }

Por ejemplo:

    for i in 1...5 {
        println(i)
    }

Este tipo de for también sirve para iterar por los caracteres de un string:

    for c in "Esto es un ejemplo" {
    }

La variable no es obligatorio declararla. Esto puede ser útil cuando, por ejemplo, sólo se quieren contar los elementos de la colección. En este caso se pone el carácter _:

    for  _  in "Esto es una cadena" {
        counter++
    }

Sentencia while

El bucle for se utiliza cuando sabemos de antemano el número de repeticiones. Pero en otras ocasiones necesitamos repetir hasta que se cumpla una determinada condición y no sabemos de antemano el número de repeticiones que habrá que hacer.

Sintaxis de while:

    while condición {
    }

La condición tiene que se de tipo Bool, y se ejecuta hasta que sea false.

Sentencia do .. while

Este bucle es similar al bucle while, excepto que siempre se ejecuta al menos una vez.

    do {
    } while condición

Salir de un bucle: break

A veces es necesario salir del bucle cuando en su interior se detecta alguna condición que obliga a salir. Para ello se utiliza la sentencia break:

    while a > 10 {
        ....
        if otra_condicion {
            break
        }
        ....
    }

Sentencia continue

La sentencia continue hace que volvamos al principio del bucle, saltando todo lo que queda. Suele ser útil para no hacer nada cuando se cumple una determinada condición.

    while a > 10 {
        if personas[a] == "001" {
            continue
        }
        .....
    }

Sentencia if

La sentencia if (y todas sus variantes) es muy similar a la de otros lenguajes de programación:

    if condición_1 {
        .....
    } else if condición_2 {
        .....
    } else if condición_3 {
        .....
    } else {
        .....
    }

Sentencia switch

La sentencia switch es equivalente a if/else if/else, pero se utiliza cuando el número de casos a comprobar es grande:

    switch expresión {
        case valor1:
            .....  // no se pone break
        case valor2:
            .....  // no se pone break
        default:
            ....
    }

Se pueden combinar varios valores:

    switch expresión {
        case valor1, valor2, valor3:
            ..... 
        case valor4, valor5:
            ..... 
        default:
            ....
    }

También se pueden poner rangos:

    switch expresión {
        case valor1 ... valor2:
            ..... 
        default:
            ....
    }

Algo muy novedoso de la sentencia switch en swift es el uso de la cláusula where, que añade una condición adicional a evaluar:

    switch expresión {
        case valor1 where condición:
            ..... 
        default:
            ....
    }




SWIFT (VIII) : Arrays y Diccionarios

Los arrays y los diccionarios de swift son colecciones de otros objetos y son muy similares a los que ya existen en otros lenguajes de programación. La diferencia entre ambos es el modo de acceso a los objetos que contienen: en los arrays se suele acceder por índice y en los diccionarios se suele acceder por clave. Los diccionarios en otros lenguajes de programación se denominan mapas.

Colecciones mutables e inmutables

Antes de empezar a ver tanto arrays como diccionarios, es preciso indicar que estas colecciones en swift pueden ser mutables o inmutables. Una colección inmutable no se puede modificar una vez que se ha inicializado. Para hacer una colección inmutable, la asignamos a una constante (let constante = colección). Por otro lado, las colecciones mutables sí se pueden modificar después de haberse inicializado. Para hacer una colección mutable, se asigna a una variable (var variable = colección).

Arrays

Un array es una colección que guarda múltiples objetos de forma ordenada. Todos los valores que se guardan en un array tienen que ser del mismo tipo.

Inicialización de arrays

Un array puede inicializarse en la creación mediante una colección de valores (array literal):

    var array : [type] = [ value1, value2, value3 ]

Por ejemplo:

    var cadenas : [String] = [ "Hola", "Mundo" ]

Igualmente, podemos crear un array inmutable:

    let plantas : [String] = [ "helecho", "tomillo" ]

No es obligatorio declarar el tipo del array, se puede dejar que el compilador lo infiera (tanto en constantes como en variables):

    let plantas = [ "helecho", "tomillo" ]

También podemos crear un array vacío:

    var lista = [String]()

Existe una forma de crear un array con una serie de elementos repetidos:

    var nombres = [String](count: 12, repeatedValue: "nombre")

Por último, se puede crear un array con la concatenación de otros arrays:

    var lista = lista1 + lista2

Trabajando con arrays

Tamaño de un array:

    array.count

Comprobar si un array está vacío:

    array,isEmpty

Acceder (en lectura y en escritura) a los items de un array (el primer elemento es el índice 0):

    var a = array[3]
    array[3] = 4

Añadir items a un array

Se pueden añadir elementos a un array mediante la función append o mediante el operador +. Los nuevos items se añaden al final del array, aumentando su tamaño:

    array.append("Hola")
    array += [ "Pepe", "Mundo" ]

También se pueden insertar elementos en una posición concreta de un array, desplazando los demás elementos hacia la derecha:

    array.insert("Manzano", atIndex: 3)

Eliminar items de un array

Se puede eliminar un elemento de una posición concreta de un array, desplazando los demás elementos hacia la izquierda:

    array.removeAtIndex(2)

También se puede eliminar el último elemento de un array:

    array.removeLast()

Iterar por un array

Se puede iterar por un array mediante for:

    for arbol in listaArboles {
        println(arbol)
    }

Diccionarios

Los diccionarios en swift, al igual que en otros lenguajes de programación, permiten almacenar datos en forma de parejas clave-valor. Las claves son únicas y permiten acceder a los valores correspondientes. Los diccionarios son colecciones no ordenadas.
Actualmente, swift sólo permite que las claves sean de tipo String, Int, Double y Bool (supongo que más adelante se ampliarán estos tipos utilizando técnicas similares a las de Java).

Inicialización de diccionarios

Forma de crear e inicializar un diccionario:

    var diccionario : [tipo-key: tipo-valor] = [ key1: value1, key2 : value2 ]

Por ejemplo:

    var personas = [ "001":"José Luis", "005":"Pedro" ]

En este caso se podría haber especificado el tipo, pero se puede dejar que el compilador lo infiera:

    var personas : [String: String] = [ "001":"José Luis", "005":"Pedro" ]

Creación de un diccionario vacío:

    var personas = [String: String]()

Trabajando con diccionarios

Número de elementos en un diccionario:

    personas.count

Acceso a un elemento:

    personas["001"]

Escritura:

    personas["001"] = "Samuel"

Añadir elementos a un diccionario

Se puede añadir un elemento a un diccionario directamente, por su clave:

    personas["045"] = "John"

Eliminar elementos de un diccionario

Para eliminar un elemento de un diccionario, ponemos su valor a nil:

    personas["001"] = nil

Iterar por un diccionario

Al igual que ocurría con los arrays, se puede iterar por todos los elementos de un diccionario utilizando un bucle for:

    for (id, nombre) in personas {
        println("Id = \(id) es \(nombre)")
    }






jueves, 20 de agosto de 2015

SWIFT (IV) Operadores y expresiones

Swift tiene prácticamente los mismos operadores que casi todos los lenguajes C-like (C, C++, Java, Objective-C, Javascript, etc), así que este artículo no será muy novedoso para los programadores experimentados en alguno de estos lenguajes.

Operador de asignación

El operador de asignación simplemente asigna el resultado de una expresión (a la derecha) a una variable (a la izquierda):

    var x : Int?
    x = 10 + 45
    x = x! + 1

Operadores aritméticos

    -  si es unario cambiar el signo, si es binario resta
    * multiplicación
    / división
    + suma
    % módulo o resto

Operador de asignación compuesta

    x += 3

Es equivalente a:

    x = x + 3

Operadores de incremento y decremento

    x++;

Es equivalente a:

    x = x + 1

Y también:

    x--

Es equivalente a:

    x = x - 1

Operadores de comparación

Igualdad:    ==
Desigualdad:   !=
Comparaciones numéricas:   <, >, <=, >=

Operadores lógicos booleanos

NOT ! invierte el valor de un booleano
OR || retorna true si uno de sus operandos es true
AND && retorna true si sus dos operandos son true
XOR ^ retorna true si sus dos operandos son distintos (true, false o false,true)

Operadores de rango

Los operadores de rango se suelen emplear en bucles.
La sintaxis del operador de rango básico es:

    a ... b

Esto representa el rango de valores entre a y b, ambos incluidos. Por ejemplo, 3 ... 6 representa los números 3, 4, 5 y 6.
Si se desea no incluir el último número:

    a ..< b

En este caso, el número b no va incluido en el rango.

Operador ternario

Al igual que en muchos lenguajes C-like en swift existe también el operador ternario:

    condición ? expresión_true : expresión_false

El resultado de esta expresión depende del valor de la condición. Si la condición es true, entonces el resultado de la expresión será la expresión_true. Si la condición es false, entonces el resultado de la expresión será la expresión_false.

Operadores de bit

Operador unario NOT de bit, cambia los bits a 1 por 0 y los bits 0 por 1:

    var x : UInt8 = 3      // 00000011
    var y : UInt8 = ~x    // 11111100       

Operador binario AND de bit, realiza un AND a nivel de bit de los dos operandos:

    var x : UInt8 = 12        // 00001100
    var y : UInt8 = 5          // 00000101
    var z : UInt8 = x & y   // 00000100

Operador binario OR de bit, realiza un OR a nivel de bit de los dos operandos:

    var x : UInt8 = 12        // 00001100
    var y : UInt8 = 5          // 00000101
    var z : UInt8 = x | y     // 00001101

Operador binario XOR de bit, realiza un XOR a nivel de bit de los dos operandos:

    var x : UInt8 = 12        // 00001100
    var y : UInt8 = 5          // 00000101
    var z : UInt8 = x ^ y    // 00001001

Desplazamiento de bits a la izquierda, metiendo ceros por la derecha:

    var x : UInt8 = 12       // 00001100
    var z : UInt8 = x << 1 // 00011000

Desplazamiento de bits a la derecha, metiendo ceros por la izquierda:

    var x : UInt8 = 12       // 00001100
    var z : UInt8 = x >> 1 // 00000110

    

martes, 18 de agosto de 2015

SWIFT (VII) : Clases y Objetos

Swift es un lenguaje orientado a objetos para desarrollar aplicaciones iOS y OSX.
No es el objetivo de este capítulo explicar los conceptos de orientación a objetos (para eso existen multitud de libros y artículos), sino explicar cómo estos conceptos se implementan con swift.

Clases

Una clase se define de la siguiente forma:

class NombreDeLaClase : ClasePadre {
    // propiedades
    // métodos de instancia
    // metodos de clase
}

Las propiedades son variables y constantes. Se declaran de la misma forma que las variables y constantes en swift, es decir, con var y let.
Los métodos de instancia son funciones que se invocarán a través de un objeto de la clase. Se declaran de forma similar a las funciones de swift, es decir, con func.
Los métodos de clase son comunes a toda la clase y no se necesita un objeto para invocarlos (son similares a los métodos estáticos de otros lenguajes). Se declaran como funciones normales, pero con class func.

Veamos un ejemplo:

class GraphicObject {
    var x : Float = 0
    var y : Float = 0
    func show() {
        println("x=\(x), y=\(y)")
    }
    class func getMaxWidth() -> Float {
        return 240.0
    }
}

Clase derivada:

class Rectangle : GraphicObject {
    var width : Float = 0
    var height : Float = 0
}

Objetos

Declaración de un objeto:

var obj : Rectangle = Rectangle()

Constructores

En swift, una forma más correcta de llamar a los constructores sería: inicializadores.
Declaración del constructor (nótese que no se pone func en el constructor):

class Rectangle : GraphicObject {
    var width : Float = 0
    var height : Float = 0
    init( w : Float, h : Float ) {
        width = w
        height = h
    }
}

Cuando se instancia el objeto hay que pasar los argumentos que necesita el constructor (si no se pasan los argumentos adecuados el compilador da un error, además, los argumentos deben pasarse nombrados obligatoriamente):

var obj = Rectangle( w: 20.0, h: 10.0 )

Como se puede ver, los constructores no son funciones normales: no empiezan con func; hay que nombrar los argumentos obligatoriamente en la llamada; tienen un nombre especial (init).

Deinicializadores

Un deinicializador (destructor en otros lenguajes) se invoca justo antes de que el objeto se destruya. La destrucción del objeto ocurre cuando el recolector de basura así lo decide.

La sintaxis del deinicializador es especial, aunque es similar a la de un inicializador sin parámetros:

class Rectangle : GraphicObject {
    var width : Float = 0
    var height : Float = 0
    init( w : Float, h : Float ) {
        width = w
        height = h
    }
    deinit {
        // labores de limpieza del objeto
        println("cleanup")
    }
}

Llamada a métodos y acceso a propiedades

El acceso a las propiedades y métodos de un objeto es muy sencillo en swift (similar a otros lenguajes):

var a = obj.width
obj.width = 70.0
obj.show()

Para llamar a un método de clase:

Rectangle.getMaxWidth()

Propiedades almacenadas y calculadas

Las propiedades pueden ser de uno de los siguientes tipos: almacenadas o calculadas.
Las propiedades almacenadas son las que hemos visto hasta ahora, contienen su valor en una variable o una constante.
Una propiedad calculada es el resultado de un cálculo o una lógica. Para implementar variables calculadas tenemos que declarar un método getter y (opcionalmente) un método setter, para leer y escribir el valor de la variable respectivamente. La variable en sí misma podría incluso no existir.

class Rectangle : GraphicObject {
    .......
    var area : Float {
        get {
            return w * h
        }
    }
}

Se puede declarar igualmente el setter con la palabra reservada set.

class Rectangle : GraphicObject {
    .......
    var widthInInches : Float {
        get {
            return width / 2.54
        }
        set(inches) {
            width = inches * 2.54
        }
    }
}

Self

En swift, al igual que en otros muchos lenguajes orientados a objetos, desde dentro de los métodos de instancia se puede acceder al propio objeto. Para ello, se utiliza self (similar a this en otros lenguajes). No es obligatorio utilizar self, pero sí es recomendable para aclarar. Aunque en algunos casos sí es obligatorio, por ejemplo cuando algún nombre de parámetro de función coincido con el nombre de una propiedad:

    func setValues(width : Float, height : Float) {
        self.width = width
        slef.height = height
    }

Sobreescribir métodos

La herencia de clases supone que la clase hija hereda todas las propiedades y métodos de la clase padre, pero además, la clase hija puede añadir nuevas propiedades y métodos, ampliando así la funcionalidad de la clase padre. Pero otra manera de ampliar (o especializar) la funcionalidad de la clase padre es sobreescribiendo métodos en la clase hija:

override func show() {
    println("width=\(width), height=\(height)")
}

Desde un método sobreescrito se puede invocar al método original de la clase padre de la siguiente forma:

override func show() {
    super.show()
    println("width=\(width), height=\(height)")
}

Inicialización de subclases

La inicialización de un objeto se realiza en el inicializador de la clase, como ya hemos visto. En el caso de subclases, la clase hija es responsable de llamar al inicializador de la clase padre:

init( x: Float, y : Float, w : Float, h : Float ) {
    width = w
    height = h
    super.init(x : x, y : y)
}

La llamada al constructor de la clase padre se puede realizar en cualquier punto del inicializador de la clase hija (en algunos lenguajes se obliga a llamarlo al principio).




lunes, 17 de agosto de 2015

SWIFT (I) Tipos de datos, constantes y variables

Tipos de datos

Todas las constantes y variables swift tienen un tipo de datos. El programador puede especificar el tipo de datos de una constante o variable, o bien puede dejar que sea el compilador el que decida el tipo en función del valor que se asigna inicialmente a la constante o variable.

Enteros

Los enteros pueden almacenar números positivos o negativos sin decimales.
Swift proporciona los siguientes tipos enteros: con signo (Int8, Int16, Int32, Int64) y sin signo (UInt8, UInt16, UInt32, UInt64).También proporciona el tipo Int que el compilador asignará al tipo más adecuado para la plataforma. Apple recomienda utilizar el tipo Int, salvo que se desee una longitud específica.
Todos los tipos tienen las propiedades min y max para obtener los valores mínimo y máximo respectivamente de cada tipo.

Punto flotante

Los números en punto flotante pueden tener dígitos decimales.
Swift proporciona dos tipos de punto flotante: Float (32 bits, precisión 6 decimales) y Double (64 bits, precisión 15 decimales).

Boolean

Swift proporciona el tipo Bool con las constantes true y false para definir el tipos booleano.

Carácter

El tipo Character para almacenar un único carácter. Las variables carácter pueden tener un carácter imprimible como "A" o bien un carácter UNICODE: "\u{0058}"
Existen algunos caracteres especiales:

    var newline = "\n"
    var backslash = "\\"
    var doublequote = "\""
    var singlequote = "\'"

String

Un String es una cadena de caracteres.
Los String en swift se pueden construir utilizando "string interpolation":

    var message = "Juan tiene \(edad) años"

Variables

Las variables en swift se declaran mediante la palabra reservada var y se puede añadir opcionalmente el tipo de datos:

    var contador = 7
    var otroContador : Int = 67

Constantes

Una constante es similar a una variable, pero no se puede modificar.
Al igual que las variables, las contantes se declaran mediante la palabra reservada let y se puede añadir opcionalmente el tipo de datos:

    let maximo = 6757
    let nombre : String = "Valor"

Apple recomienda utilizar constantes siempre que sea posible, ya que su rendimiento es superior ligeramente al de las variables.

Tuplas

Las tuplas en swift permiten almacenar varios valores en una única entidad. Los items de una tupla pueden ser de cualquier tipo (dentro de una misma tupla, cada valor puede ser de un tipo diferente).
Por ejemplo:

    let tupla = ( 10, 4.56, "Nombre" )

Se accede a sus componentes por índice (empezando en cero):

    tupla.1  --> 4.56

Se pueden crear tuplas asignando un nombre a cada valor de la tupla:

    let tupla = ( contador : 7, media : 47.5, nombre : "Nombre" )

    tupla.media --> 47.5

Las tuplas son muy útiles para retornar múltiples valores desde una función.