Introducción rápida a PHP

Variables

  • SON una forma de almacenar datos de forma temporal
  • SIRVEN para guardar datos temporalmente y utilizarlos más de una vez
  • SE IDENTIFICAN anteponiendo un signo dólar $
$variable = 1;

Instrucciones

  • SON órdenes que se le dan al ordenador en forma de código fuente
  • SIRVEN para que el ordenador haga lo que necesitamos
  • SE IDENTIFICAN colocando un punto y coma ; al final de cada orden
print "Hola Mundo";
print $variable;
print 15;

Tipos de datos

  • SON el tipo de información que puede contener una variable
  • SIRVEN para saber qué puedo hacer con la información de esa variable (por ejemplo, si sé que la información es un número sabré que puedo hacer operaciones matemáticas)
// Número entero
$edad = 45;

// Número real (la coma se indica con un punto .):
$precio = 43.75;

// Verdadero o Falso:
// Disponemos de un tipo de datos llamado "boolean" que sirve para decir si algo es verdadero o no
$estoy_vivo = true;
$soy_italiano = false;

// Texto y otros datos:
// Todos los demás datos, son considerados "cadenas de texto" y se suelen delimitar entre comillas dobles:
$ciudad = "Buenos Aires";
$fecha_de_nacimiento = "25/08/1978";

Operadores matemáticos

  • SON símbolos que indican operaciones a realizar entre dos operandos
  • SIRVEN para efectuar operaciones matemáticas con números y variables numéricas
$suma = 10 + 15;
$resta = $a - $b;
$multiplicacion = 15 * $b;
$division = $a / $b;
$operacion_combinada = ($a + $b) * $c – (12 / 4 * $n);

Operadores de comparación

  • SON símbolos que permiten comparar dos valores
  • SIRVEN para comparar datos y variables obteniendo sí o no (true o false) como respuesta a la comparación
  • SE IDENTIFICAN agrupando los valores a comparar entre paréntesis
$es_igual_a = ($a == $b);
$es_distinto_que = ($a != $b);
$es_mayor_que = ($a > $b);
$es_mayor_o_igual_que = ($a >= $b);
$es_menor_que = ($a < $b);
$es_menor_o_igual_que = ($a <= $b);

Operadores lógicos

  • SON símbolos o palabras que evalúan dos o más valores como verdaderos o falsos
  • SIRVEN para evaluar la información y controlar el flujo de la misma
  • SE IDENTIFICAN agrupando los valores a evaluar entre paréntesis
($a AND $b) $a y $b deben ser verdaderos
($a && $b)  $a y $b deben ser verdaderos
($a OR $b)  $a o $b deben ser verdaderos
($a || $b)  $a o $b deben ser verdaderos
($a XOR $b) $a o $b deben ser verdaderos (pero no ambos)
(!$a)       $a NO debe ser verdadero

Estructuras de control de flujo

  • SIRVEN para modificar el flujo de ejecución de las instrucciones
  • SE IDENTIFICAN fácilmente si agrupamos las instrucciones entre llaves { }
if ($a == $b AND !$c) {
    print "$a es igual a $b";
}
while ($a < $b) {
    print "$a es menor que $b";
    $a = $a * 2;
}

Condicionales

  • SON estructuras de control para evaluar condiciones
  • SIRVEN para ejecutar determinadas instrucciones dependiendo de si una condición se cumple o no
// Ejecutar solo si la condición de cumple
if ($edad > 18) {
    print "Solo imprimo esto si la variable edad es mayor que 18";
}

// Ejecutar ciertas instrucciones si la condición se cumple y en caso contrario ejecutar otras instrucciones
if ($edad > 18) {
    print "Imprimo esto si la variable edad es mayor que 18";
} else {
    print "Pero si la condición anterior no se cumple imprimo esto otro";
}

// Evaluar más de una condición
if ($edad <= 11) {
    print "Eres un niño";
} elseif ($edad > 11 AND $edad < 14) {
    print "Eres preadolescente";
} elseif ($edad >= 14 AND $edad < 18) {
    print "Eres adolescente";
} else {
    print "Ya eres adulto";
}

Colecciones de datos (arrays)

  • SON una forma de almacenamiento que nos permite guardar varios valores del mismo o diferentes tipos en una misma variable
  • SIRVEN para agrupar valores
  • SE IDENTIFICAN con la palabra array
// Uso simple (cada valor se asocia implícitamente a su número de posición, comenzando en cero, dentro de la colección):
$coleccion = array("Pérez", "Juan", 75, 1.83, true);
print $coleccion[1]; // Imprime Juan

// Asociando a nombres de claves explícitos
$coleccion = array(
   "apellido" => "Pérez",
   "nombre" => "Juan",
   "edad" => 75,
   "estatura" => 1.83,
   "casado" => true
);
print $coleccion["nombre"]; // Imprime Juan

Estructura de control iterativa foreach

  • ES una estructura de control de flujo
  • SIRVE para repetir una misma acción de forma iterativa sobre cada elemento de una misma colección
$coleccion = array("manzana", "pera", "naranja");
// Imprime: La manzana está en la posición 0. La pera está en la posición 1. La naranja está en la posición 2.
foreach($coleccion as $posicion => $fruta) {
    print "La $fruta está en la posición $posicion. ";
}

$datos = array(
   "Apellido" => "Pérez",
   "Nombre" => "Juan",
   "Edad" => 75,
   "Estatura" => 1.83,
   "Casado" => true
);
// Imprime: Apellido:Pérez. Nombre:Juan. Edad:75. Estatura:1.83. Casado: 1
foreach($datos as $clave=>$valor) {
    print "$clave:$valor. ";
}

Funciones

  • SON grupos de instrucciones que pretendemos ejecutar varias veces. Del mismo modo que las variables almacenan datos, las funciones almacenan instrucciones
  • SIRVEN para reutilizar código
  • SE IDENTIFICAN anteponiendo la palabra function al nombre (para definirlas) y encerrando las instrucciones entre llaves
// Para definir una función
function calcular_iva($importe_bruto=0) {
    $iva = $importe_bruto * 0.21;
    $importe_neto = $importe_bruto + $iva;
    print "El IVA de $importe_bruto es $importe_neto \n";
}

// Para ejecutar el código de la función
calcular_iva(1500);
calcular_iva(303.45);
calcular_iva(100);
calcular_iva(97);

Clases

  • SON agrupaciones de variables y funciones
  • SIRVEN para crear colecciones de datos personalizadas
  • SE IDENTIFICAN anteponiendo la palabra class al nombre (para definirlas) y encerrando las variables y funciones entre llaves
// Para definir una clase
class Producto {
    public $denominacion = '';
    public $precio = 0.0;
    function guardar() {
        // instrucciones de la función guardar
    }
    function eliminar($producto=0) {
        // instrucciones de la función eliminar
    }
}

// Para usar una clase primero debemos crear una variable con el nuevo tipo de dato
$producto = new Producto();

// Para acceder a una variable dentro de una clase
$producto->precio = 100.75;
print $producto->precio;

// Para acceder a una función dentro de una clase
$producto->guardar();

Swift – Funciones

Concepto de función

Al igual que en cualquier otro lenguaje de programación, uno de los puntos básicos que todo desarrollador Swift debe conocer es la manera de trabajar con funciones.

Podríamos decir que forma parte del núcleo de un lenguaje y provee un sinfín de beneficios al momento de escribir código claro y mantenible.

Una función es una porción de código que se encapsula bajo un nombre y puede ser invocado las veces que sea necesario.

La primer ventaja que ofrece es la posibilidad de reutilizar esa funcionalidad evitando tener que escribir el algoritmo repetidas veces a lo largo del programa. Se espera que el nombre asignado a la función sea descriptivo y relacionado a la tarea que la misma realiza.

La forma en la que las funciones están pensadas en Swift le da al desarrollador una flexibilidad considerable al momento de utilizarlas.

En este sentido, es posible escribir funciones súper básicas como así también otras mucho más rebuscadas.

Para poder escribir una función, se utiliza la palabra reservada funcseguida del nombre de la misma. La forma más básica sería:

func saludar() {
print("Hola mundo!")
}

saludar()

//Devuelve:
//Hola mundo!

Parámetros y valores de retorno

Asimismo, las funciones pueden recibir valores de entrada para poder trabajar en función a ellos, los cuales son conocidos como parámetros. De la misma manera, una función puede devolver un valor a quien lo invoca una vez finalizada su ejecución, conocido como valor de retorno.

//Función con un parámetro
func saludar(nombre: String) {
print("Hola \(nombre)!")
}

saludar(nombre: "Gabriel")

//Devuelve:
//Hola Gabriel!

//Función con un parámetro y un valor de retorno
func saludarA(nombre: String) -> String {
return "Hola \(nombre)!"
}

let saludo = saludarA(nombre: "Gabriel")
print(saludo)

//Devuelve:
//Hola Gabriel!

Como muestran los ejemplos anteriores, la invocación a una función se realiza escribiendo el nombre de la misma seguido de paréntesis. Si la función posee parámetros, los mismos se incluyen dentro de los paréntesis y si la función devuelve un valor se utiliza la flecha -> seguida del tipo de dato a devolver. Este tipo puede ser cualquiera, ya sea un StringInt, una tupla, una clase o struct que definamos nosotros, un opcional, etc. Asimismo, se debe utilizar algún mecanismo para recibir ese dato (por ejemplo, guardarlo en una constante o variable).

Los valores de entrada pasados a una función al momento de invocarla se denominan Argumentos. Estos argumentos deben coincidir con el tipo de dato de los parámetros esperados de la función.
Por otro lado, el conjunto conformado por el nombre de la función, los parámetros y su valor de retorno conforman la definición de la función, y no puede haber en un mismo código dos funciones con la misma definición.
Cuando tenemos dos o más funciones con el mismo nombre pero distinta definición, decimos que esa función está sobrecargada o que existe una sobrecarga de la misma.

En el caso en que se desee usar dos o más parámetros, se deben separar por una coma en la definición de la función:

//Función con dos parámetros
func saludar(nombre: String, edad: Int) {
print("Felices \(edad) años \(nombre)!")
}

saludar(nombre: "Gabriel", edad: 29)

//Devuelve
//Felices 29 años Gabriel!

Devolver más de un dato

La forma que nos brinda Swift para retornar más de un valor es mediante las tuplas. En este caso, al momento de invocar la función podemos hacer referencia a cualquiera de los datos obtenidos simplemente utilizando su nombre o posición en la tupla:

//Función que devuelve más de un dato
func minMax(array: [Int]) -> (min: Int, max: Int) {
var minimo = array[0]
var maximo = array[0]

for valor in array[1..<array.count] {
if valor < minimo { minimo = valor } else if valor > maximo {
maximo = valor
}
}

return (minimo, maximo)
}

let notas = minMax(array: [1, 2, 10, 8, 5])
print("La nota mas baja es \(notas.min) y la mas alta es \(notas.max)")

//Devuelve:
//La nota más baja es 1 y la más alta es 10

Etiquetas de argumento

Cuando especificamos nuestros parámetros podemos definir una etiqueta de argumento (argument label), la cual se utiliza al momento de llamar a la función y se especifica delante del nombre del parámetro en la definición de la misma. En este sentido, el parámetro se usa internamente en la implementación de la función cuando se requiere hacer uso de él.

//Etiquetas de argumento
func saludar(a nombre: String, porCumplir edad: Int){
print("Felices \(edad) años \(nombre)!")
}

saludar(a: "Gabriel", porCumplir: 30)

//Devuelve:
//Felices 30 años Gabriel!

Como se aprecia en el ejemplo, se está usando un argument label por cada parámetro. Internamente en la función se usa el nombre del parámetro, pero al momento de invocarla solo se usan las etiquetas de argumento. Nótese lo claro que resulta entender lo que hace la función saludar(a:porCumplir:) al momento de invocarla.

En el caso de que no se especifique una etiqueta de argumento, el mismo nombre de parámetro funciona como nombre de parámetro y etiqueta. Sin embargo, si se desea omitir por completo la etiqueta al momento de invocar a la función, se utiliza un guión bajo (_):

//Omitiendo argument label
func sumar(_ primerNumero: Int, _ segundoNumero:Int) -> Int
{
return primerNumero + segundoNumero
}

print("El resultado de 4 + 5 es \(sumar(4,5))")

//Devuelve:
//El resultado de 4 + 5 es 9

Parámetros con valores por defecto

Otra posibilidad que nos habilita Swift es la de asignar un valor por defecto a los parámetros, de forma tal que obtengan ese valor en caso de que no se le pase ninguno al momento de invocar a la función.

En el caso de utilizar esta metodología, se recomienda listar primero los parámetros que no tienen valores por defecto (que en la mayoría de los casos son más representativos para la función) y luego los que sí tienen.

//Parámetros por defecto
func saludar(a nombre:String, cumpleAños:Bool = false) {
if cumpleAños {
print("Feliz cumpleaños \(nombre)")
}
else {
print("Buen día \(nombre)")
}
}

saludar(a: "Gabriel", cumpleAños: true)
saludar(a: "Gabriel")

//Devuelve:
//Feliz cumpleaños Gabriel
//Buen día Gabriel

Como se aprecia en el ejemplo anterior, al tener un parámetro opcional la función puede ser llamada incluyendo ese argumento o no.

Parámetros variádicos

Este tipo de parámetros permite especificar una cantidad de cero o más valores de un tipo determinado. Se utiliza para dar flexibilidad al momento de usar la función para pasar una cantidad variables de valores sabiendo que la misma siempre va a trabajar correctamente.

Para indicar que un parámetro es variádico, se usan 3 puntos suspensivos luego del tipo del parámetro, e internamente ese valor se usa como un array.

//Parámetros variádicos
func sumar(numeros:Int…) -> Int {
var suma:Int=0

for valor in numeros {
suma = suma+valor
}

return suma
}

print(“La suma es igual a \(sumar(numeros: 4,6,2,3,10,6,7,5,4))”)

//Devuelve:
//La suma es igual a 47

Las funciones pueden tener 1 solo parámetro variádico. En caso de que se necesite usar varios parámetros, siendo uno solo de ellos variádico, éste debe quedar al final.

Parámetros in-out

Los parámetros que usamos en nuestras funciones son constantes, es decir que no pueden ser modificadas internamente en la función. Si por ejemplo quisiéramos agregar un número más al ejemplo anterior, recibiríamos este error:

error: cannot use mutating member on immutable value: ‘numeros’ is a ‘let’ constant

 numeros.append(3)

Esta característica funciona así de manera intencionada para evitar que se cambie el valor de un parámetro por error, lo que puede causar comportamientos extraños a lo largo del código y genere una alta dificultad para encontrar el motivo.

De todas maneras, si lo que queremos es modificar los valores de los parámetros internamente en la función y que ese cambio persista incluso cuando la función termina, debemos usar el modificador inout entre el nombre del parámetro y su tipo.

Existen unas reglas a tener en cuenta:

  • Al momento de invocar la función, si el parámetro es inout, solo pueden pasarse variables. Constantes o literales no están permitidos ya que justamente no pueden ser modificados
  • Los parámetros variádicos no pueden ser inout
  • Los parámetros inout no pueden tener valores por defecto
  • Se debe utilizar un ampersand (&) delante de la variable en el llamado a la función
//Parámetros inout
func cambiarDosEnteros(_ a: inout Int, _ b: inout Int) {
let auxiliar = a
a = b
b = auxiliar
}

var numero1 = 5
var numero2 = 8

print("Numero1: \(numero1)")
print("Numero2: \(numero2)")

cambiarDosEnteros(&numero1, &numero2)

print("Numero1: \(numero1)")
print("Numero2: \(numero2)")

//Devuelve
//Numero1: 5
//Numero2: 8

//Numero1: 8
//Numero2: 5

El uso del ampersand (&) viene del lenguaje C y se utiliza para indicar la posición en memoria de la variable. Como el objetivo es modificar el valor del parámetro dentro de la función, se pasa su dirección para poder introducir allí el nuevo dato.

Tipo de una función

Todas las funciones tienen su propio tipo, que está formado por el tipo de sus parámetros y el tipo de su valor de retorno. Veamos algunos ejemplos:

func saludar() {
print("Hola mundo!")
}

El tipo de esta función es () -> Void, o lo que es lo mismo “una función que no recibe parámetros y devuelve Void”

func saludarA(nombre: String) -> String {
return "Hola \(nombre)!"
}

El tipo de esta función es (String) -> String, o lo que es lo mismo “una función que recibe un parámetro del tipo String y devuelve un String”

En este sentido, se pueden definir variables o constantes del tipo de una función. Por ejemplo:

//Tipos de una función
func sumarDosNumeros(_ a: Int, _ b: Int) -> Int {
return a + b
}

func multiplicarDosNumeros(_ a: Int, _ b: Int) -> Int {
return a * b
}

var calculo:(Int,Int) -> Int = sumarDosNumeros

print("El resultado de sumar 3 + 7 es \(calculo(3,7))")

calculo = multiplicarDosNumeros

print("El resultado de multiplicar 3 x 7 es \(calculo(3,7))")

//Devuelve:
//El resultado de sumar 3 + 7 es 10
//El resultado de multiplicar 3 x 7 es 21

Lo que hicimos fue definir dos funciones distintas pero del mismo tipo: ambas reciben dos parámetros Int y devuelven un Int. Luego, definimos una variable de ese tipo (Int, Int) -> Int al cual primero lo igualamos a la primer función y luego a la segunda.

De la misma manera, se puede utilizar a las funciones como parámetros, definiéndolos con el tipo correspondiente. Esto permite que parte de la implementación de la función se la deje a la clase o struct que la invoca. Más adelante veremos cómo funcionan las clases en swift.

func imprimirResultado(_ operacion:(Int,Int) -> Int, _ a:Int, _ b:Int ) {
print("El resultado es \(operacion(a,b))")
}

imprimirResultado(sumarDosNumeros, 10, 60)

//Devuelve:
//El resultado es 70

En el ejemplo, la función imprimirResultado(_:_:_:) solo hace eso, imprime un resultado de una operación que no se conoce al momento de la implementación pero que se recibe por parámetro. Recién al momento de llamar a la función se sabe que lo que se quiere es sumar los números pasados a la misma.

Ejemplos completos

//Funcion sin parametros
func saludar() {
    print("Hola mundo!")
}

saludar()

//Devuelve:
//Hola mundo!

//Función con un parámetro
func saludar(nombre: String) {
    print("Hola \(nombre)!")
}

saludar(nombre: "Gabriel")

//Devuelve:
//Hola Gabriel!

//Función con un parámetro y un valor de retorno
func saludarA(nombre: String) -> String {
    return "Hola \(nombre)!"
}

let saludo = saludarA(nombre: "Gabriel")
print(saludo)

//Función con dos parámetros
func saludar(nombre: String, edad: Int) {
    
    print("Felices \(edad) años \(nombre)!")
}

saludar(nombre: "Gabriel", edad: 29)

//Devuelve
//Felices 29 años Gabriel!

//Función que devuelve más de un dato
func minMax(array: [Int]) -> (min: Int, max: Int) {
    var minimo = array[0]
    var maximo = array[0]
    for valor in array[1..<array.count] {
        if valor < minimo {
            minimo = valor
        } else if valor > maximo {
            maximo = valor
        }
    }
    return (minimo, maximo)
}

let notas = minMax(array: [1, 2, 10, 8, 5])
print("La nota más baja es \(notas.min) y la más alta es \(notas.max)")

//Devuelve:
//La nota más baja es 1 y la más alta es 10

//Etiquetas de argumento
func saludar(a nombre: String, porCumplir edad: Int){
    print("Felices \(edad) años \(nombre)!")
}

saludar(a: "Gabriel", porCumplir: 30)

//Devuelve:
//Felices 30 años Gabriel!

//Omitiendo argument label
func sumar(_ primerNumero: Int, _ segundoNumero:Int) -> Int
{
    return primerNumero + segundoNumero
}

print("El resultado de 4 + 5 es \(sumar(4,5))")

//Devuelve:
//El resultado de 4 + 5 es 9

//Parámetros por defecto
func saludar(a nombre:String, cumpleAños:Bool = false) {
    if cumpleAños {
        print("Feliz cumpleaños \(nombre)")
    }
    else {
        print("Buen día \(nombre)")
    }
}

saludar(a: "Gabriel", cumpleAños: true)
saludar(a: "Gabriel")

//Devuelve:
//Feliz cumpleaños Gabriel
//Buen día Gabriel

//Parámetros variádicos
func sumar(numeros:Int...) -> Int {
    var suma:Int=0
    for valor in numeros {
        suma = suma+valor
    }
    return suma
}

print("La suma es igual a \(sumar(numeros: 4,6,2,3,10,6,7,5,4))")

//Devuelve:
//La suma es igual a 47

//Parámetros inout
func cambiarDosEnteros(_ a: inout Int, _ b: inout Int) {
    let auxiliar = a
    a = b
    b = auxiliar
}

var numero1=5
var numero2=8

print("Numero1: \(numero1)")
print("Numero2: \(numero2)")

cambiarDosEnteros(&numero1, &numero2)

print("Numero1: \(numero1)")
print("Numero2: \(numero2)")

//Devuelve
//Numero1: 5
//Numero2: 8
//Numero1: 8
//Numero2: 5


//Tipos de una función
func sumarDosNumeros(_ a: Int, _ b: Int) -> Int {
    return a + b
}
func multiplicarDosNumeros(_ a: Int, _ b: Int) -> Int {
    return a * b
}

var calculo:(Int,Int) -> Int = sumarDosNumeros

print("El resultado de sumar 3 + 7 es \(calculo(3,7))")

calculo = multiplicarDosNumeros
print("El resultado de multiplicar 3 x 7 es \(calculo(3,7))")

//Devuelve:
//El resultado de sumar 3 + 7 es 10
//El resultado de multiplicar 3 x 7 es 21

func imprimirResultado(_ operacion:(Int,Int)->Int, _ a:Int, _ b:Int ) {
    print("El resultado es \(operacion(a,b))")
}

imprimirResultado(sumarDosNumeros, 10, 60)

//Devuelve:
//El resultado es 70