lunes, 11 de marzo de 2019

Intervalos

INTERVALO

Un intervalo es un espacio métrico comprendido entre dos valores. Los intervalos pueden referirse al intervalo de una variable o al intervalo de un array.
El intervalo de una variable está definido como la diferencia entre el valor más alto y el valor más bajo que esa variable puede guardar.
En el caso de una variable entera, la definición está restringida a números enteros, y el intervalo cubrirá todos los números dentro de su intervalo (incluyendo el máximo y el mínimo).El intervalo de un array son los límites superior e inferior del mismo.

Intervalos
 Funciones devuelven siempre el mismo valor
  Los lenguajes funcionales puros tienen la propiedad de transparencia referencial 
 Como consecuencia, en programación funcional, una función siempre devuelve el mismo valor cuando se le llama con los mismos parámetros 
 Las funciones no modifican ningún estado, no acceden a ninguna variable ni objeto global y modifican su valor Diferencia entre declaración y modificación de variables 
 En programación funcional pura una vez declarada una variable no se puede modificar su valor 
 En algunos lenguajes de programación (como Scala) este concepto se refuerza definiendo la variable como inmutable (con la directiva val). 
 En programación imperativa es habitual modificar el valor de una variable en distintos pasos de ejecución 
ejemplos de como utilizar los intervalos:




Funciones

Funciones de primera clase

Se dice que en un lenguaje las funciones son de primera clase (o que son "objetos de primera clase") cuando se pueden tratar como cualquier otro valor del lenguaje, es decir, cuando se pueden almacenar en variables, pasar como parámetro y devolver desde funciones, sin ningún tratamiento especial. El ejemplo más claro en un lenguaje popular lo encontramos en JavaScript, donde estas operaciones con funciones son muy comunes:
// Asignación a variable
var get_post = function(post_number) {
  return fetch(`https://example.org/posts/${post_number}`)
    // Paso como parámetro
    .then(response => response.json())
    .then(function(data) {
      console.log(data);
    });
};

var custom_exp = function(base) {
  // Valor de retorno
  return function(exponent) {
    return Math.pow(base, exponent);
  };
};
En este ejemplo he usado algunas características modernas de JavaScript: template strings y funciones flecha. Si tienes interés en aprender más tal vez quieras consultar el curso sobre Programacion avanzada en JavaScript y ECMAScript .
Como podemos ver, en JavaScript es natural utilizar funciones como parámetros, valores de retorno y en variables. Esto también es así en otros lenguajes como R o Scala. Muchos otros introducen un tipo de funciones denominadas lambdas (o funciones anónimas), que en ocasiones se comportan de forma distinta a las funciones usuales para permitir esas operaciones. Por ejemplo, en Ruby las lambdas son objetos pero no así el resto de funciones:
def greet who = "Mundo"
  "¡Hola #{who}!"
end

greet2 = -> who { "¡Hola #{who}!" }

greet  # => "¡Hola Mundo!"
greet2 # => #<Proc:... (lambda)>
En el ejemplo anterior, greet no hace referencia a la función sino que la ejecuta, devolviendo el mensaje "¡Hola Mundo!", mientras que greet2 sí nos indica que es un objeto de tipo Proc, el cual se puede pasar como argumento, devolver, etc.
Una aplicación interesante de la propiedad de funciones de primera clase es escribir versiones parcialmente aplicadas de otras funciones. Por ejemplo, supongamos que queremos evaluar la función de densidad de una distribución normal para una media y desviación dadas. Podríamos escribir nuestra función de la siguiente manera:
function gaussian(mean, variance, x) {
  return 1 / Math.sqrt(2 * Math.PI * variance) *
    Math.exp((x - mean)**2 / (-2 * variance));
}
Esta implementación nos impide reutilizar la media y la varianza de la distribución para evaluar en varios puntos sin escribir de nuevo los parámetros. En su lugar, consideremos la siguiente versión:
function gaussian_alt(mean, variance) {
  return function(x) {
    return 1 / Math.sqrt(2 * Math.PI * variance) *
      Math.exp((x - mean)**2 / (-2 * variance));
  };
}

var standard_normal = gaussian_alt(0, 1);
console.log(`N(3 | 0, 1) = ${standard_normal(3)}`);
Ahora podemos reutilizar la standard_normal tanto como queramos. Esto es aplicable a muchas otras situaciones donde conviene que nuestras funciones estén parametrizadas a varios niveles y podamos proporcionar los argumentos poco a poco. En ocasiones, el lenguaje proporciona la funcionalidad necesaria para obtener dichas versiones parcialmente aplicadas sin necesidad de reescribir la función:
// Aplicamos la media y varianza
standard_normal = gaussian.bind(null, 2, 1);
console.log(`N(3 | 0, 1) = ${standard_normal(3)}`);
La sintaxis para la aplicación parcial de funciones suele diferir entre lenguajes: en JavaScript usamos bindcomo en el ejemplo, en C++ está disponible std::bind, en Python functools.partial...

Funciones de orden superior

Cuando una función no recibe otras funciones como parámetro, se la denomina de primer orden. En el caso en el que sí las reciba, se llama de orden superior.
Muchos lenguajes nos proveen con una serie de funciones de orden superior para trabajar con estructuras de datos. De entre ellas, las más conocidas son map y reduce: la primera aplica la misma función sobre cada elemento de una colección, y la segunda acumula los elementos en un único valor según una función dada. Veamos un ejemplo:
const list = [1, 2, 3, 4, 5];

const squared = list.map(x => x ** 2);
// => [1, 4, 9, 16, 25]

const product = list.reduce((acc, item) => acc * item, 1);
// => 120
Es importante notar que map no modifica la colección original sino que devuelve una nueva, esto se verifica también en la mayoría de lenguajes que la proporcionan. También es de uso común una función filter, que seleccione elementos mediante un predicado booleano:
const even = list.filter(x => x % 2 == 0);
// => [2, 4]
Casos interesantes de uso de funciones de orden superior son el módulo Enumerable de Ruby, los métodos de la interfaz Stream de Java y los decoradores de Python.
Una última función de orden superior que resulta muy obvia pero no siempre viene integrada en los lenguajes es la composición de funciones. En JavaScript, por ejemplo, podríamos implementar la composición de dos funciones como sigue:
const comp2 = (f, g) => ((...arg) => g(f(...arg)));
const abs = comp2(x => x * x, Math.sqrt);
abs(-4); // => 4
Para componer más de dos funciones, podemos componerlas dos a dos aprovechando el ejemplo anterior y una variante de la función reduce que acabamos de aprender:
const compose = function(...functions) {
  return functions.reduceRight(comp2);
};

// Las funciones se aplican de derecha a izquierda
const f = compose(Math.floor, Math.log, Math.max)
f(10, 20) // => 2


Tipos de datos

Tipos de datos en programacion funcional

En lenguaje funcional el uso de los datos debe ser selectivo y se debe tener cuidado al momento de hacer uso de un tipo en especifico de dato para retornar algun otro, por naturaleza del lenguaje es imposible hacerlo directamente ya que una vez iniciado un procedimiento no se pueden incluir tipos de datos diferente a la entrada, para poder hacer eso se deben hacer especificaciones en la declaracion de la funcon como por ejemplo:

       <Haskell>

        Funcion :: Int -> String
        Funcion x = <parametros de la funcion>

donde "x" representa la entrada de datos que habra al nomas ser solo la x solo recibira un parametro,
en este caso se esta creando una funcion que va a recibir un entero y va a retornar una cadena, otro ejemplo de funciones que requieren mas trabajo la especificacion de tipos se hace de la siguiente manera:

        <Haskell>

         Funcion :: [a]->Int->Bool
         Funcion x = <parametros de la funcion>

En el ejemplo anterior se esta declarando una fucnion que recibira una lista, luego manejara enteros y retornara un booleano.

Los tipos de datos que puede recibir haskell son
Int
String
Bool
Char
[a] (lista)
[Int] (lista enteros)
Float
Double

Para crear un tipo de dato personalizado se utiliza la expresion type <nombre> = (<contenido>)
por ejemplo podemos crear un tipo nombre de la siguiente manera:
     type nombre = String

o un tipo numero de telefono
     type numero = Int

o un dato mas complejo como una tupla
    type contacto = (String,Int)
    o
    type contacto = (nombre,numero)

Lista:
Una lista es un conjunto de datos indefinido, que almacena solo un tipo de dato, algo similar a los arreglos con la limitande a un solo tipo de dato Ejemplo:

          [10,20,30,40] <- Lista Int
          ['a','b','c','d']         <- Lista String

Si tratamos de hacer una mezcla tal como [10,20,30,a,b,c] seria incorrecto y arrojaria error debido a que se esstan integrando enteros y caracteres en la lista cuando deberian ser solo enteros o solo cadenas

creacion de listas en haskell:
en haskell  para crear una lista se utiliza el comando let <nombre_lista> =  [<Valores>]
Ejemplo:
         Let lista1 = [1,2,3,4,5,6,7,8,9]
         Let lista2 = ['a','b','c']
una vez creadas es solo cuestion de teclear en el prompt de haskell en nombre de la lista para que muestre sus contenidos


Las listas pueden ser manipuladas de distintas formas como por ejemplo si usamos la palabra reservada head nos muestra el primer valor dentro de la lista:
       head lista1
       head lista2



Otros comandos que hay para el uso de las listas son tail, init ,last.
tail muestra todos los elementos menos el primero, init muestra todos los elementos menos el ultimo y last muestra solo el ultimo elemento, se tiene tambien otra funcion de uso en listas que

todos estos comandos pueden ser utilizados en combinacion para poder desarrollar ciertas operaciones con las listas como sumarlas, mezclarlas o recorrer valores dentro de la lista

Tupla:

Las tuplas en haskell a diferencia de las listas estas pueden tener multiples tipos de valores dentro
por ejemplo:
    let tupla = (1,a,3.5)

Las tuplas pueden tener un gran uso dentro de programacion funcional ya que se pueden conjuntar multiples datos en una tupla y luego asignar esa tupla como un tipo de dato

En lenguajes de tipo funcional se pueden crear tipos de datos personalizados, los cuales, son declarados como algun tipo de dato ya existente (para un uso mas sencillo al momento de declarar en un programa o mas entendible) o un conjunto de datos.